Index: cfe/trunk/lib/Sema/SemaStmtAsm.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaStmtAsm.cpp +++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp @@ -617,45 +617,57 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc) { Offset = 0; + SmallVector Members; + Member.split(Members, "."); + LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(), LookupOrdinaryName); if (!LookupName(BaseResult, getCurScope())) return true; - if (!BaseResult.isSingleResult()) - return true; + LookupResult CurrBaseResult(BaseResult); - const RecordType *RT = nullptr; - NamedDecl *FoundDecl = BaseResult.getFoundDecl(); - if (VarDecl *VD = dyn_cast(FoundDecl)) - RT = VD->getType()->getAs(); - else if (TypedefNameDecl *TD = dyn_cast(FoundDecl)) { - MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); - RT = TD->getUnderlyingType()->getAs(); - } else if (TypeDecl *TD = dyn_cast(FoundDecl)) - RT = TD->getTypeForDecl()->getAs(); - if (!RT) - return true; + for (StringRef NextMember : Members) { - if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0)) - return true; + if (!CurrBaseResult.isSingleResult()) + return true; - LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(), - LookupMemberName); + const RecordType *RT = nullptr; + NamedDecl *FoundDecl = CurrBaseResult.getFoundDecl(); + if (VarDecl *VD = dyn_cast(FoundDecl)) + RT = VD->getType()->getAs(); + else if (TypedefNameDecl *TD = dyn_cast(FoundDecl)) { + MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false); + RT = TD->getUnderlyingType()->getAs(); + } else if (TypeDecl *TD = dyn_cast(FoundDecl)) + RT = TD->getTypeForDecl()->getAs(); + else if (FieldDecl *TD = dyn_cast(FoundDecl)) + RT = TD->getType()->getAs(); + if (!RT) + return true; - if (!LookupQualifiedName(FieldResult, RT->getDecl())) - return true; + if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0)) + return true; - // FIXME: Handle IndirectFieldDecl? - FieldDecl *FD = dyn_cast(FieldResult.getFoundDecl()); - if (!FD) - return true; + LookupResult FieldResult(*this, &Context.Idents.get(NextMember), + SourceLocation(), LookupMemberName); + + if (!LookupQualifiedName(FieldResult, RT->getDecl())) + return true; - const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); - unsigned i = FD->getFieldIndex(); - CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); - Offset = (unsigned)Result.getQuantity(); + // FIXME: Handle IndirectFieldDecl? + FieldDecl *FD = dyn_cast(FieldResult.getFoundDecl()); + if (!FD) + return true; + + CurrBaseResult = FieldResult; + + const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); + unsigned i = FD->getFieldIndex(); + CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); + Offset += (unsigned)Result.getQuantity(); + } return false; } Index: cfe/trunk/test/CodeGen/ms-inline-asm.c =================================================================== --- cfe/trunk/test/CodeGen/ms-inline-asm.c +++ cfe/trunk/test/CodeGen/ms-inline-asm.c @@ -470,6 +470,18 @@ int b; } A; +typedef struct { + int b1; + A b2; +} B; + +typedef struct { + int c1; + A c2; + int c3; + B c4; +} C; + void t39() { // CHECK-LABEL: define void @t39 __asm mov eax, [eax].A.b @@ -478,6 +490,14 @@ // CHECK: mov eax, [eax] .4 __asm mov eax, fs:[0] A.b // CHECK: mov eax, fs:[$$0] .4 + __asm mov eax, [eax].B.b2.a +// CHECK: mov eax, [eax].4 + __asm mov eax, [eax] B.b2.b +// CHECK: mov eax, [eax] .8 + __asm mov eax, fs:[0] C.c2.b +// CHECK: mov eax, fs:[$$0] .8 + __asm mov eax, [eax]C.c4.b2.b +// CHECK: mov eax, [eax].24 // CHECK: "~{eax},~{dirflag},~{fpsr},~{flags}"() }