diff options
| author | Reid Kleckner <rnk@google.com> | 2015-08-26 21:57:20 +0000 |
|---|---|---|
| committer | Reid Kleckner <rnk@google.com> | 2015-08-26 21:57:20 +0000 |
| commit | 14e96b49302ba90b50078b6a9f48248ab79dd0d3 (patch) | |
| tree | 316752ba25d92a48efa5d34d513de9806206278a /clang/lib/Sema | |
| parent | 06c199ac9dde91cdebbf7e3899d773db797b0fdb (diff) | |
| download | bcm5719-llvm-14e96b49302ba90b50078b6a9f48248ab79dd0d3.tar.gz bcm5719-llvm-14e96b49302ba90b50078b6a9f48248ab79dd0d3.zip | |
[ms-inline-asm] Add field access to MS inline asm identifier lookup
Now we can parse code like this:
struct A {
int field;
};
int f(A o) {
__asm mov eax, o.field
}
Fixes PR19117.
llvm-svn: 246088
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaStmtAsm.cpp | 62 |
1 files changed, 55 insertions, 7 deletions
diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 799689f1995..52987cc1316 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -528,6 +528,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, return NS; } +static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T, + llvm::InlineAsmIdentifierInfo &Info) { + // Compute the type size (and array length if applicable?). + Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity(); + if (T->isArrayType()) { + const ArrayType *ATy = Context.getAsArrayType(T); + Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); + Info.Length = Info.Size / Info.Type; + } +} + ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, @@ -575,13 +586,7 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, return ExprError(); } - // Compute the type size (and array length if applicable?). - Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity(); - if (T->isArrayType()) { - const ArrayType *ATy = Context.getAsArrayType(T); - Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); - Info.Length = Info.Size / Info.Type; - } + fillInlineAsmTypeInfo(Context, T, Info); // We can work with the expression as long as it's not an r-value. if (!Result.get()->isRValue()) @@ -636,6 +641,49 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, return false; } +ExprResult +Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, unsigned &Offset, + llvm::InlineAsmIdentifierInfo &Info, + SourceLocation AsmLoc) { + Info.clear(); + + const RecordType *RT = E->getType()->getAs<RecordType>(); + // FIXME: Diagnose this as field access into a scalar type. + if (!RT) + return ExprResult(); + + LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc, + LookupMemberName); + + if (!LookupQualifiedName(FieldResult, RT->getDecl())) + return ExprResult(); + + // Only normal and indirect field results will work. + ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); + if (!FD) + FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl()); + if (!FD) + return ExprResult(); + + Offset = (unsigned)Context.toCharUnitsFromBits(Context.getFieldOffset(FD)) + .getQuantity(); + + // Make an Expr to thread through OpDecl. + ExprResult Result = BuildMemberReferenceExpr( + E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(), + SourceLocation(), nullptr, FieldResult, nullptr); + if (Result.isInvalid()) + return Result; + Info.OpDecl = Result.get(); + + fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info); + + // Fields are "variables" as far as inline assembly is concerned. + Info.IsVarDecl = true; + + return Result; +} + StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef<Token> AsmToks, StringRef AsmString, |

