forked from OSchip/llvm-project
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. llvm-svn: 224916
This commit is contained in:
parent
4b4be84a2f
commit
0f4d641005
|
@ -132,31 +132,54 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
|
|||
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(SourceLocation AsmLoc, bool IsSimple,
|
|||
<< 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.
|
||||
|
|
|
@ -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@+1{{overloaded function could not be resolved}}
|
||||
__asm__ ("":"+r" (test4)); // expected-error{{invalid lvalue in asm output}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue