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)
|
diag::err_asm_invalid_output_constraint)
|
||||||
<< Info.getConstraintStr());
|
<< Info.getConstraintStr());
|
||||||
|
|
||||||
|
ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
|
||||||
|
if (ER.isInvalid())
|
||||||
|
return StmtError();
|
||||||
|
Exprs[i] = ER.get();
|
||||||
|
|
||||||
// Check that the output exprs are valid lvalues.
|
// Check that the output exprs are valid lvalues.
|
||||||
Expr *OutputExpr = Exprs[i];
|
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.
|
// Referring to parameters is not allowed in naked functions.
|
||||||
if (CheckNakedParmReference(OutputExpr, *this))
|
if (CheckNakedParmReference(OutputExpr, *this))
|
||||||
return StmtError();
|
return StmtError();
|
||||||
|
|
||||||
if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
|
|
||||||
diag::err_dereference_incomplete_type))
|
|
||||||
return StmtError();
|
|
||||||
|
|
||||||
OutputConstraintInfos.push_back(Info);
|
OutputConstraintInfos.push_back(Info);
|
||||||
|
|
||||||
const Type *Ty = OutputExpr->getType().getTypePtr();
|
// If this is dependent, just continue.
|
||||||
|
if (OutputExpr->isTypeDependent())
|
||||||
// If this is a dependent type, just continue. We don't know the size of a
|
|
||||||
// dependent type.
|
|
||||||
if (Ty->isDependentType())
|
|
||||||
continue;
|
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(),
|
if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
|
||||||
Size))
|
Size))
|
||||||
return StmtError(Diag(OutputExpr->getLocStart(),
|
return StmtError(Diag(OutputExpr->getLocStart(),
|
||||||
|
@ -182,6 +205,11 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
|
||||||
<< Info.getConstraintStr());
|
<< Info.getConstraintStr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
|
||||||
|
if (ER.isInvalid())
|
||||||
|
return StmtError();
|
||||||
|
Exprs[i] = ER.get();
|
||||||
|
|
||||||
Expr *InputExpr = Exprs[i];
|
Expr *InputExpr = Exprs[i];
|
||||||
|
|
||||||
// Referring to parameters is not allowed in naked functions.
|
// Referring to parameters is not allowed in naked functions.
|
||||||
|
|
|
@ -20,3 +20,13 @@ namespace PR6536 {
|
||||||
struct A {};
|
struct A {};
|
||||||
void a() { goto out; A x; out: return; }
|
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