Index: include/clang/AST/Expr.h =================================================================== --- include/clang/AST/Expr.h +++ include/clang/AST/Expr.h @@ -458,6 +458,10 @@ /// \brief Returns whether this expression refers to a vector element. bool refersToVectorElement() const; + /// \brief Returns whether this expression refers to a global register + /// variable. + bool refersToGlobalRegisterVar() const; + /// \brief Returns whether this expression has a placeholder type. bool hasPlaceholderType() const { return getType()->isPlaceholderType(); Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -6333,8 +6333,8 @@ "remove the cast or build with -fheinous-gnu-extensions">; def err_invalid_asm_value_for_constraint : Error <"value '%0' out of range for constraint '%1'">; - def err_asm_bitfield_in_memory_constraint - : Error <"reference to a bit-field in asm " + def err_asm_non_addr_value_in_memory_constraint + : Error <"reference to a non-addressable value in asm " "%select{input|output}0 with a memory constraint '%1'">; def warn_asm_label_on_auto_decl : Warning< Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -3429,6 +3429,18 @@ return false; } +bool Expr::refersToGlobalRegisterVar() const { + const Expr *E = this->IgnoreParenImpCasts(); + + if (const DeclRefExpr *DRE = dyn_cast(E)) + if (const auto *VD = dyn_cast(DRE->getDecl())) + if (VD->getStorageClass() == SC_Register && + VD->hasAttr() && !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 { Index: lib/Sema/SemaStmtAsm.cpp =================================================================== --- lib/Sema/SemaStmtAsm.cpp +++ lib/Sema/SemaStmtAsm.cpp @@ -154,12 +154,14 @@ if (CheckNakedParmReference(OutputExpr, *this)) return StmtError(); - // Bitfield can't be referenced with a pointer. - if (Info.allowsMemory() && OutputExpr->refersToBitField()) + // Bitfields, vector elements and global register variables can't be + // referenced with a pointer. + if (Info.allowsMemory() && (OutputExpr->refersToBitField() || + OutputExpr->refersToVectorElement() || + OutputExpr->refersToGlobalRegisterVar())) return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_bitfield_in_memory_constraint) - << 1 - << Info.getConstraintStr() + diag::err_asm_non_addr_value_in_memory_constraint) + << 1 << Info.getConstraintStr() << OutputExpr->getSourceRange()); OutputConstraintInfos.push_back(Info); @@ -238,12 +240,14 @@ if (CheckNakedParmReference(InputExpr, *this)) return StmtError(); - // Bitfield can't be referenced with a pointer. - if (Info.allowsMemory() && InputExpr->refersToBitField()) + // Bitfields, vector elements and global register variables can't be + // referenced with a pointer. + if (Info.allowsMemory() && (InputExpr->refersToBitField() || + InputExpr->refersToVectorElement() || + InputExpr->refersToGlobalRegisterVar())) return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_bitfield_in_memory_constraint) - << 0 - << Info.getConstraintStr() + diag::err_asm_non_addr_value_in_memory_constraint) + << 0 << Info.getConstraintStr() << InputExpr->getSourceRange()); // Only allow void types for memory constraints. Index: test/Sema/asm.c =================================================================== --- test/Sema/asm.c +++ test/Sema/asm.c @@ -211,13 +211,28 @@ unsigned int field2 : 2; unsigned int field3 : 3; } test16_foo; -test16_foo x; +typedef __attribute__((vector_size(16))) int test16_bar; +register int test16_baz asm("rbx"); + void test16() { + test16_foo a; + test16_bar b; + + __asm__("movl $5, %0" + : "=rm" (a.field2)); // expected-error {{reference to a non-addressable value in asm output with a memory constraint '=rm'}} + __asm__("movl $5, %0" + : + : "m" (a.field3)); // expected-error {{reference to a non-addressable value in asm input with a memory constraint 'm'}} + __asm__("movl $5, %0" + : "=rm" (b[2])); // expected-error {{reference to a non-addressable value in asm output with a memory constraint '=rm'}} + __asm__("movl $5, %0" + : + : "m" (b[3])); // expected-error {{reference to a non-addressable value in asm input with a memory constraint 'm'}} __asm__("movl $5, %0" - : "=rm" (x.field2)); // expected-error {{reference to a bit-field in asm output with a memory constraint '=rm'}} + : "=rm" (test16_baz)); // expected-error {{reference to a non-addressable value in asm output with a memory constraint '=rm'}} __asm__("movl $5, %0" : - : "m" (x.field3)); // expected-error {{reference to a bit-field in asm input with a memory constraint 'm'}} + : "m" (test16_baz)); // expected-error {{reference to a non-addressable value in asm input with a memory constraint 'm'}} }