summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-08-26 21:57:20 +0000
committerReid Kleckner <rnk@google.com>2015-08-26 21:57:20 +0000
commit14e96b49302ba90b50078b6a9f48248ab79dd0d3 (patch)
tree316752ba25d92a48efa5d34d513de9806206278a /clang/lib/Sema
parent06c199ac9dde91cdebbf7e3899d773db797b0fdb (diff)
downloadbcm5719-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.cpp62
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,
OpenPOWER on IntegriCloud