When glass panes are placed they do not bind with the full block back of stairs like they should.
Related issues
is duplicated by
relates to
Attachments
Comments

Glass panes, fences and iron bars do not connect to stairs.

... because stairs are transparent.

The above is the explanation (=excuse) why they are not connected with the current code, but does not mean they are not intended to connect. See, for example, MC-8345. The issue can be fixed to work as players would expect.
(Seems I had already bookmarked this issue so I'd try fixing it, but haven't had yet time to get into it.)
Edit: I took a look at it, and using the changes from MC-8345, this can be fixed somewhat easily. Unfortunately, easy doesn't equal to little work; certain change must be propagated through a bunch of classes, which means too much work for this night. Alternately, certain methods can be changed a tiny bit, but that would in turn require a lot of testing (to not break something else), or, a bunch of code could be copied and adapted to this specific case, but that is just bad coding style.
Hmm.. looks like lots of the code to be copied in that last choice has already duplication in it, so it might actually give a decent result after some combining and cleanup. Have to have a better look at this... perhaps tomorrow.
I'm very much with MArkku here. And would those who use the excuse that stairs are transparent kindly explain why glass panes /do/ join to leaves, glass blocks and glowstone, all of which are classed as transparent blocks?

The reason why glass panes connect to the above blocks is that they are hard-coded to do so, the glass panes has been intentionally programmed to not connect to transparent blocks, and have a few exceptions (eg. if(par1IBlockAccess.isBlockSolid(par2 - 1, par3, par4) || par1IBlockAccess.getBlockId(par2 - 1, par3, par4) == Block.glass.blockId){ } this is just a simple example).

Exactly like fuj1n explains. And that is the part I'm going to "attack". I'll add similar smartness as in the torch placement bug. Just it wasn't as trivial to apply to this issue as to the other one, due to some design decisions/architecture hiccups. I'm still at work, but I'll get to this later today.

Sample screenshot 'fixed-panes-stairs.png' showing both torches attached and glass panes connected to backside of stair blocks. Code fixes incoming.

(NOTE: would be best to fix all of this, MC-8345 and MC-2938 at the same time; see the MC-2938 for more text.)
Fix
The basic reason for the issue is the same as for the MC-8345; the code does not have own method to check only surfaces of blocks, so it checks just the full block type, and also typically has some special case handling here and there (like fuj1n explained for this issue).
To resolve the torches vs. backs of stairs, I added a method to check just for the block's surface (if it is a full and solid surface). It didn't directly work for this issue, as it was made just for the torch-stuff at the time. I made the necessary changes to accommodate both issues, and as a side-effect, made the new method work more correctly. (I'll update the code in the other issue, too.)
However, I also had to adjust certain method calls in a way that may have some undesired side-effects. Testing recommended.
Here are the code changes, using mix of MCP and my own namings:
Block
/**
* Override as necessary.
* @param side 1 = bottom, 2 = z+1, 3 = z-1, 4 = x+1, 5 = x-1, top = 0 or anything else
* @return true if that side is solid and full surface
*/
public boolean hasSolidFullSurfaceAt(IBlockAccess access, int x, int y, int z, int side) {
switch (side) {
case 1: return access.isBlockNormalCube(x, y, z);
case 2:
case 3:
case 4:
case 5: return access.isBlockNormalCube(x, y, z);
default: return access.doesBlockHaveSolidTopSurface(x, y, z);
}
}
BlockStairs
public boolean hasSolidFullSurfaceAt(IBlockAccess access, int x, int y, int z, int side) {
int metaData = access.getBlockMetadata(x, y, z);
switch (side) {
case 1: return (metaData & 4) == 0;
case 2: return (metaData & 3) == 3;
case 3: return (metaData & 3) == 2;
case 4: return (metaData & 3) == 1;
case 5: return (metaData & 3) == 0;
default: return (metaData & 4) == 1; // true if it is upside down
}
}
BlockPane
public void addCollidingBlockToList(World world, int x, int y, int z, AxisAlignedBB par5AxisAlignedBB, List par6List, Entity par7Entity) {
// boolean north = this.canThisPaneConnectToThisBlockID(world.getBlockId(x, y, z - 1));
// boolean south = this.canThisPaneConnectToThisBlockID(world.getBlockId(x, y, z + 1));
// boolean west = this.canThisPaneConnectToThisBlockID(world.getBlockId(x - 1, y, z));
// boolean east = this.canThisPaneConnectToThisBlockID(world.getBlockId(x + 1, y, z));
boolean north = this.canPaneAtConnectToDir(world, x, y, z, 3);
boolean south = this.canPaneAtConnectToDir(world, x, y, z, 2);
boolean west = this.canPaneAtConnectToDir(world, x, y, z, 5);
boolean east = this.canPaneAtConnectToDir(world, x, y, z, 4);
...
public void setBlockBoundsBasedOnState(IBlockAccess blockAccess, int x, int y, int z) {
...
// boolean north = this.canThisPaneConnectToThisBlockID(blockAccess.getBlockId(x, y, z - 1));
// boolean south = this.canThisPaneConnectToThisBlockID(blockAccess.getBlockId(x, y, z + 1));
// boolean west = this.canThisPaneConnectToThisBlockID(blockAccess.getBlockId(x - 1, y, z));
// boolean east = this.canThisPaneConnectToThisBlockID(blockAccess.getBlockId(x + 1, y, z));
boolean north = this.canPaneAtConnectToDir(blockAccess, x, y, z, 3);
boolean south = this.canPaneAtConnectToDir(blockAccess, x, y, z, 2);
boolean west = this.canPaneAtConnectToDir(blockAccess, x, y, z, 5);
boolean east = this.canPaneAtConnectToDir(blockAccess, x, y, z, 4);
...
/**
* ADDED METHOD.
* @param dir 1 = bottom, 2 = z+1, 3 = z-1, 4 = x+1, 5 = x-1, top = 0 or anything else
*/
public final boolean canPaneAtConnectToDir(IBlockAccess access, int x, int y, int z, int dir) {
switch (dir) {
case 2: { z++; break; }
case 3: { z--; break; }
case 4: { x++; break; }
case 5: { x--; break; }
default: return false;
}
int blockId = access.getBlockId(x, y, z);
if (this.canThisPaneConnectToThisBlockID(blockId)) return true; // Old check
// ADDED CHECK (compared to old operation), THE CORE OF THIS FIX:
Block block = Block.blocksList[blockId];
if (block == null)
return false;
return block.hasSolidFullSurfaceAt(access, x, y, z, dir);
}
RenderBlocks.renderBlockPane()
...
// boolean north = par1BlockPane.canThisPaneConnectToThisBlockID(this.blockAccess.getBlockId(x, y, z - 1));
// boolean south = par1BlockPane.canThisPaneConnectToThisBlockID(this.blockAccess.getBlockId(x, y, z + 1));
// boolean west = par1BlockPane.canThisPaneConnectToThisBlockID(this.blockAccess.getBlockId(x - 1, y, z));
// boolean east = par1BlockPane.canThisPaneConnectToThisBlockID(this.blockAccess.getBlockId(x + 1, y, z));
boolean north = blockPane.canPaneAtConnectToDir(blockAccess, x, y, z, 3);
boolean south = blockPane.canPaneAtConnectToDir(blockAccess, x, y, z, 2);
boolean west = blockPane.canPaneAtConnectToDir(blockAccess, x, y, z, 5);
boolean east = blockPane.canPaneAtConnectToDir(blockAccess, x, y, z, 4);
...
I tested changes on 1.4.7, results as in the screenshot. (Though the torches need also the MC-8345 fixes applied, too.)

Affects 13w09b.

Affects 13w09c.

Markku wrote a fix... why is this still unresolved?
I seriously hope this is not considered to be intended behavior. Voted.
I am seeing the same issue in the new 1.7.2 release.
Confirmed for 1.7.5, 14w08a and 14w10c
Confirmed for 14w11b

Confirmed in 1.8.1-pre1.

Confirmed in 1.8.1-pre5.

Still happening in 15w42a.

Still happening in 15w44b.

Still happening in 15w45a.

Still happening in 15w47a.

Still happening in 1.9-pre2.
Confirmed in 1.10.
still in 16w44a
still in 1.11 Pre-Release 1