r224916 - Sema: Only permit permit modifiable l-values as asm output params
David Majnemer
david.majnemer at gmail.com
Mon Dec 29 01:30:33 PST 2014
Author: majnemer
Date: Mon Dec 29 03:30:33 2014
New Revision: 224916
URL: http://llvm.org/viewvc/llvm-project?rev=224916&view=rev
Log:
Sema: Only permit permit modifiable l-values as asm output params
Functions are l-values in C++ but shouldn't be available as output
parameters in inline assembly. Neither should overloaded function
l-values.
This fixes PR21949.
Modified:
cfe/trunk/lib/Sema/SemaStmtAsm.cpp
cfe/trunk/test/SemaCXX/statements.cpp
Modified: cfe/trunk/lib/Sema/SemaStmtAsm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=224916&r1=224915&r2=224916&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Mon Dec 29 03:30:33 2014
@@ -132,31 +132,54 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
diag::err_asm_invalid_output_constraint)
<< Info.getConstraintStr());
+ ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
+ if (ER.isInvalid())
+ return StmtError();
+ Exprs[i] = ER.get();
+
// Check that the output exprs are valid lvalues.
Expr *OutputExpr = Exprs[i];
- if (CheckAsmLValue(OutputExpr, *this))
- return StmtError(Diag(OutputExpr->getLocStart(),
- diag::err_asm_invalid_lvalue_in_output)
- << OutputExpr->getSourceRange());
// Referring to parameters is not allowed in naked functions.
if (CheckNakedParmReference(OutputExpr, *this))
return StmtError();
- if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
- diag::err_dereference_incomplete_type))
- return StmtError();
-
OutputConstraintInfos.push_back(Info);
- const Type *Ty = OutputExpr->getType().getTypePtr();
-
- // If this is a dependent type, just continue. We don't know the size of a
- // dependent type.
- if (Ty->isDependentType())
+ // If this is dependent, just continue.
+ if (OutputExpr->isTypeDependent())
continue;
- unsigned Size = Context.getTypeSize(Ty);
+ Expr::isModifiableLvalueResult IsLV =
+ OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
+ switch (IsLV) {
+ case Expr::MLV_Valid:
+ // Cool, this is an lvalue.
+ break;
+ case Expr::MLV_LValueCast: {
+ const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
+ if (!getLangOpts().HeinousExtensions) {
+ Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
+ << OutputExpr->getSourceRange();
+ } else {
+ Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
+ << OutputExpr->getSourceRange();
+ }
+ // Accept, even if we emitted an error diagnostic.
+ break;
+ }
+ case Expr::MLV_IncompleteType:
+ case Expr::MLV_IncompleteVoidType:
+ if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
+ diag::err_dereference_incomplete_type))
+ return StmtError();
+ default:
+ return StmtError(Diag(OutputExpr->getLocStart(),
+ diag::err_asm_invalid_lvalue_in_output)
+ << OutputExpr->getSourceRange());
+ }
+
+ unsigned Size = Context.getTypeSize(OutputExpr->getType());
if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
Size))
return StmtError(Diag(OutputExpr->getLocStart(),
@@ -182,6 +205,11 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL
<< Info.getConstraintStr());
}
+ ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
+ if (ER.isInvalid())
+ return StmtError();
+ Exprs[i] = ER.get();
+
Expr *InputExpr = Exprs[i];
// Referring to parameters is not allowed in naked functions.
Modified: cfe/trunk/test/SemaCXX/statements.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/statements.cpp?rev=224916&r1=224915&r2=224916&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/statements.cpp (original)
+++ cfe/trunk/test/SemaCXX/statements.cpp Mon Dec 29 03:30:33 2014
@@ -20,3 +20,13 @@ namespace PR6536 {
struct A {};
void a() { goto out; A x; out: return; }
}
+
+void test3() {
+ __asm__ ("":"+r" (test3)); // expected-error{{invalid lvalue in asm output}}
+}
+
+void test4(); // expected-note{{possible target for call}}
+void test4(int) { // expected-note{{possible target for call}}
+ // expected-error at +1{{overloaded function could not be resolved}}
+ __asm__ ("":"+r" (test4)); // expected-error{{invalid lvalue in asm output}}
+}
More information about the cfe-commits
mailing list