diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmtAsm.cpp | 53 |
2 files changed, 51 insertions, 14 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 4882f536d52..89f47f980c9 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3437,6 +3437,18 @@ bool Expr::refersToVectorElement() const { return false; } +bool Expr::refersToGlobalRegisterVar() const { + const Expr *E = this->IgnoreParenImpCasts(); + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) + if (VD->getStorageClass() == SC_Register && + VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl()) + return true; + + return false; +} + /// isArrow - Return true if the base expression is a pointer to vector, /// return false if the base expression is a vector. bool ExtVectorElementExpr::isArrow() const { diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index 8e584919363..799689f1995 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -107,6 +107,37 @@ static bool CheckNakedParmReference(Expr *E, Sema &S) { return false; } +/// \brief Returns true if given expression is not compatible with inline +/// assembly's memory constraint; false otherwise. +static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E, + TargetInfo::ConstraintInfo &Info, + bool is_input_expr) { + enum { + ExprBitfield = 0, + ExprVectorElt, + ExprGlobalRegVar, + ExprSafeType + } EType = ExprSafeType; + + // Bitfields, vector elements and global register variables are not + // compatible. + if (E->refersToBitField()) + EType = ExprBitfield; + else if (E->refersToVectorElement()) + EType = ExprVectorElt; + else if (E->refersToGlobalRegisterVar()) + EType = ExprGlobalRegVar; + + if (EType != ExprSafeType) { + S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint) + << EType << is_input_expr << Info.getConstraintStr() + << E->getSourceRange(); + return true; + } + + return false; +} + StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, @@ -154,13 +185,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (CheckNakedParmReference(OutputExpr, *this)) return StmtError(); - // Bitfield can't be referenced with a pointer. - if (Info.allowsMemory() && OutputExpr->refersToBitField()) - return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_bitfield_in_memory_constraint) - << 1 - << Info.getConstraintStr() - << OutputExpr->getSourceRange()); + // Check that the output expression is compatible with memory constraint. + if (Info.allowsMemory() && + checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false)) + return StmtError(); OutputConstraintInfos.push_back(Info); @@ -238,13 +266,10 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (CheckNakedParmReference(InputExpr, *this)) return StmtError(); - // Bitfield can't be referenced with a pointer. - if (Info.allowsMemory() && InputExpr->refersToBitField()) - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_bitfield_in_memory_constraint) - << 0 - << Info.getConstraintStr() - << InputExpr->getSourceRange()); + // Check that the input expression is compatible with memory constraint. + if (Info.allowsMemory() && + checkExprMemoryConstraintCompat(*this, InputExpr, Info, true)) + return StmtError(); // Only allow void types for memory constraints. if (Info.allowsMemory() && !Info.allowsRegister()) { |

