mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-29 00:21:14 +00:00
Model list initialization more directly; fixes an assert with coverage mapping
Instead of using the validity of a brace's source location as a flag for list initialization, this now uses a PointerIntPair to model it so we do not increase the size of the AST node to track this information. This allows us to retain the valid source location information, which fixes the coverage assertion. Fixes https://github.com/llvm/llvm-project/issues/62105 Differential Revision: https://reviews.llvm.org/D148245
This commit is contained in:
parent
e78881ebf8
commit
b0e61de707
@ -300,6 +300,8 @@ Bug Fixes in This Version
|
||||
- Work around with a clang coverage crash which happens when visiting
|
||||
expressions/statements with invalid source locations in non-assert builds.
|
||||
Assert builds may still see assertions triggered from this.
|
||||
- Fix a failed assertion due to an invalid source location when trying to form
|
||||
a coverage report for an unresolved constructor expression.
|
||||
(`#62105 <https://github.com/llvm/llvm-project/issues/62105>`_)
|
||||
|
||||
Bug Fixes to Compiler Builtins
|
||||
|
@ -3504,8 +3504,9 @@ class CXXUnresolvedConstructExpr final
|
||||
friend class ASTStmtReader;
|
||||
friend TrailingObjects;
|
||||
|
||||
/// The type being constructed.
|
||||
TypeSourceInfo *TSI;
|
||||
/// The type being constructed, and whether the construct expression models
|
||||
/// list initialization or not.
|
||||
llvm::PointerIntPair<TypeSourceInfo *, 1> TypeAndInitForm;
|
||||
|
||||
/// The location of the left parentheses ('(').
|
||||
SourceLocation LParenLoc;
|
||||
@ -3515,30 +3516,31 @@ class CXXUnresolvedConstructExpr final
|
||||
|
||||
CXXUnresolvedConstructExpr(QualType T, TypeSourceInfo *TSI,
|
||||
SourceLocation LParenLoc, ArrayRef<Expr *> Args,
|
||||
SourceLocation RParenLoc);
|
||||
SourceLocation RParenLoc, bool IsListInit);
|
||||
|
||||
CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs)
|
||||
: Expr(CXXUnresolvedConstructExprClass, Empty), TSI(nullptr) {
|
||||
: Expr(CXXUnresolvedConstructExprClass, Empty) {
|
||||
CXXUnresolvedConstructExprBits.NumArgs = NumArgs;
|
||||
}
|
||||
|
||||
public:
|
||||
static CXXUnresolvedConstructExpr *Create(const ASTContext &Context,
|
||||
QualType T, TypeSourceInfo *TSI,
|
||||
SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> Args,
|
||||
SourceLocation RParenLoc);
|
||||
static CXXUnresolvedConstructExpr *
|
||||
Create(const ASTContext &Context, QualType T, TypeSourceInfo *TSI,
|
||||
SourceLocation LParenLoc, ArrayRef<Expr *> Args,
|
||||
SourceLocation RParenLoc, bool IsListInit);
|
||||
|
||||
static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &Context,
|
||||
unsigned NumArgs);
|
||||
|
||||
/// Retrieve the type that is being constructed, as specified
|
||||
/// in the source code.
|
||||
QualType getTypeAsWritten() const { return TSI->getType(); }
|
||||
QualType getTypeAsWritten() const { return getTypeSourceInfo()->getType(); }
|
||||
|
||||
/// Retrieve the type source information for the type being
|
||||
/// constructed.
|
||||
TypeSourceInfo *getTypeSourceInfo() const { return TSI; }
|
||||
TypeSourceInfo *getTypeSourceInfo() const {
|
||||
return TypeAndInitForm.getPointer();
|
||||
}
|
||||
|
||||
/// Retrieve the location of the left parentheses ('(') that
|
||||
/// precedes the argument list.
|
||||
@ -3553,7 +3555,7 @@ public:
|
||||
/// Determine whether this expression models list-initialization.
|
||||
/// If so, there will be exactly one subexpression, which will be
|
||||
/// an InitListExpr.
|
||||
bool isListInitialization() const { return LParenLoc.isInvalid(); }
|
||||
bool isListInitialization() const { return TypeAndInitForm.getInt(); }
|
||||
|
||||
/// Retrieve the number of arguments.
|
||||
unsigned getNumArgs() const { return CXXUnresolvedConstructExprBits.NumArgs; }
|
||||
|
@ -8147,7 +8147,7 @@ ExpectedStmt ASTNodeImporter::VisitCXXUnresolvedConstructExpr(
|
||||
|
||||
return CXXUnresolvedConstructExpr::Create(
|
||||
Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc,
|
||||
llvm::ArrayRef(ToArgs), ToRParenLoc);
|
||||
llvm::ArrayRef(ToArgs), ToRParenLoc, E->isListInitialization());
|
||||
}
|
||||
|
||||
ExpectedStmt
|
||||
|
@ -1392,17 +1392,16 @@ ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C,
|
||||
return new (buffer) ExprWithCleanups(empty, numObjects);
|
||||
}
|
||||
|
||||
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(QualType T,
|
||||
TypeSourceInfo *TSI,
|
||||
SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> Args,
|
||||
SourceLocation RParenLoc)
|
||||
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(
|
||||
QualType T, TypeSourceInfo *TSI, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> Args, SourceLocation RParenLoc, bool IsListInit)
|
||||
: Expr(CXXUnresolvedConstructExprClass, T,
|
||||
(TSI->getType()->isLValueReferenceType() ? VK_LValue
|
||||
: TSI->getType()->isRValueReferenceType() ? VK_XValue
|
||||
: VK_PRValue),
|
||||
OK_Ordinary),
|
||||
TSI(TSI), LParenLoc(LParenLoc), RParenLoc(RParenLoc) {
|
||||
TypeAndInitForm(TSI, IsListInit), LParenLoc(LParenLoc),
|
||||
RParenLoc(RParenLoc) {
|
||||
CXXUnresolvedConstructExprBits.NumArgs = Args.size();
|
||||
auto **StoredArgs = getTrailingObjects<Expr *>();
|
||||
for (unsigned I = 0; I != Args.size(); ++I)
|
||||
@ -1411,11 +1410,12 @@ CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(QualType T,
|
||||
}
|
||||
|
||||
CXXUnresolvedConstructExpr *CXXUnresolvedConstructExpr::Create(
|
||||
const ASTContext &Context, QualType T, TypeSourceInfo *TSI, SourceLocation LParenLoc,
|
||||
ArrayRef<Expr *> Args, SourceLocation RParenLoc) {
|
||||
const ASTContext &Context, QualType T, TypeSourceInfo *TSI,
|
||||
SourceLocation LParenLoc, ArrayRef<Expr *> Args, SourceLocation RParenLoc,
|
||||
bool IsListInit) {
|
||||
void *Mem = Context.Allocate(totalSizeToAlloc<Expr *>(Args.size()));
|
||||
return new (Mem)
|
||||
CXXUnresolvedConstructExpr(T, TSI, LParenLoc, Args, RParenLoc);
|
||||
return new (Mem) CXXUnresolvedConstructExpr(T, TSI, LParenLoc, Args,
|
||||
RParenLoc, IsListInit);
|
||||
}
|
||||
|
||||
CXXUnresolvedConstructExpr *
|
||||
@ -1426,7 +1426,7 @@ CXXUnresolvedConstructExpr::CreateEmpty(const ASTContext &Context,
|
||||
}
|
||||
|
||||
SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const {
|
||||
return TSI->getTypeLoc().getBeginLoc();
|
||||
return TypeAndInitForm.getPointer()->getTypeLoc().getBeginLoc();
|
||||
}
|
||||
|
||||
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(
|
||||
|
@ -1522,16 +1522,10 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
|
||||
Entity = InitializedEntity::InitializeTemporary(TInfo, Ty);
|
||||
}
|
||||
|
||||
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) {
|
||||
// FIXME: CXXUnresolvedConstructExpr does not model list-initialization
|
||||
// directly. We work around this by dropping the locations of the braces.
|
||||
SourceRange Locs = ListInitialization
|
||||
? SourceRange()
|
||||
: SourceRange(LParenOrBraceLoc, RParenOrBraceLoc);
|
||||
return CXXUnresolvedConstructExpr::Create(Context, Ty.getNonReferenceType(),
|
||||
TInfo, Locs.getBegin(), Exprs,
|
||||
Locs.getEnd());
|
||||
}
|
||||
if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs))
|
||||
return CXXUnresolvedConstructExpr::Create(
|
||||
Context, Ty.getNonReferenceType(), TInfo, LParenOrBraceLoc, Exprs,
|
||||
RParenOrBraceLoc, ListInitialization);
|
||||
|
||||
// C++ [expr.type.conv]p1:
|
||||
// If the expression list is a parenthesized single expression, the type
|
||||
|
@ -2006,9 +2006,10 @@ ASTStmtReader::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
|
||||
Record.skipInts(1);
|
||||
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
|
||||
E->setArg(I, Record.readSubExpr());
|
||||
E->TSI = readTypeSourceInfo();
|
||||
E->TypeAndInitForm.setPointer(readTypeSourceInfo());
|
||||
E->setLParenLoc(readSourceLocation());
|
||||
E->setRParenLoc(readSourceLocation());
|
||||
E->TypeAndInitForm.setInt(Record.readInt());
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOverloadExpr(OverloadExpr *E) {
|
||||
|
@ -1921,6 +1921,7 @@ ASTStmtWriter::VisitCXXUnresolvedConstructExpr(CXXUnresolvedConstructExpr *E) {
|
||||
Record.AddTypeSourceInfo(E->getTypeSourceInfo());
|
||||
Record.AddSourceLocation(E->getLParenLoc());
|
||||
Record.AddSourceLocation(E->getRParenLoc());
|
||||
Record.push_back(E->isListInitialization());
|
||||
Code = serialization::EXPR_CXX_UNRESOLVED_CONSTRUCT;
|
||||
}
|
||||
|
||||
|
24
clang/test/Coverage/unresolved-ctor-expr.cpp
Normal file
24
clang/test/Coverage/unresolved-ctor-expr.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 -fcoverage-mapping %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
// GH62105 demonstrated a crash with this example code when calculating
|
||||
// coverage mapping because some source location information was being dropped.
|
||||
// Demonstrate that we do not crash on this code.
|
||||
namespace std { template <typename> class initializer_list {}; }
|
||||
|
||||
template <typename> struct T {
|
||||
T(std::initializer_list<int>, int = int());
|
||||
bool b;
|
||||
};
|
||||
|
||||
template <typename> struct S1 {
|
||||
static void foo() {
|
||||
class C;
|
||||
(void)(0 ? T<C>{} : T<C>{});
|
||||
}
|
||||
};
|
||||
|
||||
void bar() {
|
||||
S1<int>::foo();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user