Fix crash with align_value diagnostic reporting (#135013)

We were passing the address of a local variable to a call to Diag()
which then tried to use the object after its lifetime ended, resulting
in crashes. We no longer pass the temporary object any longer.

Fixes #26612
This commit is contained in:
Aaron Ballman 2025-04-09 12:39:03 -04:00 committed by GitHub
parent 751c3f51eb
commit 543e5f5842
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 54 additions and 20 deletions

View File

@ -386,6 +386,10 @@ Bug Fixes to Attribute Support
or too few attribute argument indicies for the specified callback function.
(#GH47451)
- No longer crashing on ``__attribute__((align_value(N)))`` during template
instantiation when the function parameter type is not a pointer or reference.
(#GH26612)
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -4510,7 +4510,7 @@ public:
getAttrLoc(const AttrInfo &AL) {
return AL.getLocation();
}
SourceLocation getAttrLoc(const ParsedAttr &AL);
SourceLocation getAttrLoc(const AttributeCommonInfo &CI);
/// If Expr is a valid integer constant, get the value of the integer
/// expression and return success or failure. May output an error.

View File

@ -86,7 +86,9 @@ static unsigned getNumAttributeArgs(const ParsedAttr &AL) {
return AL.getNumArgs() + AL.hasParsedType();
}
SourceLocation Sema::getAttrLoc(const ParsedAttr &AL) { return AL.getLoc(); }
SourceLocation Sema::getAttrLoc(const AttributeCommonInfo &CI) {
return CI.getLoc();
}
/// Wrapper around checkUInt32Argument, with an extra check to be sure
/// that the result will fit into a regular (signed) int. All args have the same
@ -1415,13 +1417,11 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
Expr *OE) {
QualType ResultType = getFunctionOrMethodResultType(D);
SourceRange SR = getFunctionOrMethodResultSourceRange(D);
AssumeAlignedAttr TmpAttr(Context, CI, E, OE);
SourceLocation AttrLoc = TmpAttr.getLocation();
SourceLocation AttrLoc = CI.getLoc();
if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
<< &TmpAttr << TmpAttr.getRange() << SR;
<< CI << CI.getRange() << SR;
return;
}
@ -1430,12 +1430,10 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
if (!(I = E->getIntegerConstantExpr(Context))) {
if (OE)
Diag(AttrLoc, diag::err_attribute_argument_n_type)
<< &TmpAttr << 1 << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
<< CI << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange();
else
Diag(AttrLoc, diag::err_attribute_argument_type)
<< &TmpAttr << AANT_ArgumentIntegerConstant
<< E->getSourceRange();
<< CI << AANT_ArgumentIntegerConstant << E->getSourceRange();
return;
}
@ -1452,8 +1450,7 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) {
Diag(AttrLoc, diag::err_attribute_argument_n_type)
<< &TmpAttr << 2 << AANT_ArgumentIntegerConstant
<< OE->getSourceRange();
<< CI << 2 << AANT_ArgumentIntegerConstant << OE->getSourceRange();
return;
}
@ -1463,19 +1460,17 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *ParamExpr) {
QualType ResultType = getFunctionOrMethodResultType(D);
AllocAlignAttr TmpAttr(Context, CI, ParamIdx());
SourceLocation AttrLoc = CI.getLoc();
if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) {
Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only)
<< &TmpAttr << CI.getRange() << getFunctionOrMethodResultSourceRange(D);
<< CI << CI.getRange() << getFunctionOrMethodResultSourceRange(D);
return;
}
ParamIdx Idx;
const auto *FuncDecl = cast<FunctionDecl>(D);
if (!checkFunctionOrMethodParameterIndex(FuncDecl, TmpAttr,
if (!checkFunctionOrMethodParameterIndex(FuncDecl, CI,
/*AttrArgNum=*/1, ParamExpr, Idx))
return;
@ -1483,8 +1478,7 @@ void Sema::AddAllocAlignAttr(Decl *D, const AttributeCommonInfo &CI,
if (!Ty->isDependentType() && !Ty->isIntegralType(Context) &&
!Ty->isAlignValT()) {
Diag(ParamExpr->getBeginLoc(), diag::err_attribute_integers_only)
<< &TmpAttr
<< FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
<< CI << FuncDecl->getParamDecl(Idx.getASTIndex())->getSourceRange();
return;
}
@ -4383,7 +4377,6 @@ static void handleAlignValueAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
}
void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) {
AlignValueAttr TmpAttr(Context, CI, E);
SourceLocation AttrLoc = CI.getLoc();
QualType T;
@ -4397,7 +4390,7 @@ void Sema::AddAlignValueAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E) {
if (!T->isDependentType() && !T->isAnyPointerType() &&
!T->isReferenceType() && !T->isMemberPointerType()) {
Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only)
<< &TmpAttr << T << D->getSourceRange();
<< CI << T << D->getSourceRange();
return;
}

View File

@ -24,3 +24,17 @@ struct nope {
// expected-note@+1 {{in instantiation of template class 'nope<long double, 4>' requested here}}
nope<long double, 4> y2;
namespace GH26612 {
// This used to crash while issuing the diagnostic about only applying to a
// pointer or reference type.
// FIXME: it would be ideal to only diagnose once rather than twice. We get one
// diagnostic from explicit template arguments and another one for deduced
// template arguments, which seems silly.
template <class T>
void f(T __attribute__((align_value(4))) x) {} // expected-warning 2 {{'align_value' attribute only applies to a pointer or reference ('int' is invalid)}}
void foo() {
f<int>(0); // expected-note {{while substituting explicitly-specified template arguments into function template 'f'}} \
expected-note {{while substituting deduced template arguments into function template 'f' [with T = int]}}
}
} // namespace GH26612

View File

@ -47,3 +47,15 @@ void dependent_impl(int align) {
dependent_param_func<int>(1);
dependent_param_func<float>(1); // expected-note {{in instantiation of function template specialization 'dependent_param_func<float>' requested here}}
}
namespace GH26612 {
// This issue was about the align_value attribute, but alloc_align has the
// same problematic code pattern, so is being fixed at the same time despite
// not having the same crashing behavior.
template <class T>
__attribute__((alloc_align(1))) T f(T x); // expected-warning {{'alloc_align' attribute only applies to return values that are pointers or references}}
void foo() {
f<int>(0); // expected-note {{in instantiation of function template specialization 'GH26612::f<int>' requested here}}
}
} // namespace GH26612

View File

@ -91,3 +91,14 @@ void test24() {
atest5<s3>(); // expected-note {{in instantiation of function template specialization 'atest5<s3>' requested here}}
}
namespace GH26612 {
// This issue was about the align_value attribute, but assume_aligned has the
// same problematic code pattern, so is being fixed at the same time despite
// not having the same crashing behavior.
template <class T>
__attribute__((assume_aligned(4))) T f(T x); // expected-warning {{'assume_aligned' attribute only applies to return values that are pointers or references}}
void foo() {
f<int>(0); // expected-note {{in instantiation of function template specialization 'GH26612::f<int>' requested here}}
}
} // namespace GH26612