This revision was automatically updated to reflect the committed changes. Closed by commit rGb0e61de70759: Model list initialization more directly; fixes an assert with coverage mapping (authored by aaron.ballman).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D148245/new/ https://reviews.llvm.org/D148245 Files: clang/docs/ReleaseNotes.rst clang/include/clang/AST/ExprCXX.h clang/lib/AST/ASTImporter.cpp clang/lib/AST/ExprCXX.cpp clang/lib/Sema/SemaExprCXX.cpp clang/lib/Serialization/ASTReaderStmt.cpp clang/lib/Serialization/ASTWriterStmt.cpp clang/test/Coverage/unresolved-ctor-expr.cpp
Index: clang/test/Coverage/unresolved-ctor-expr.cpp =================================================================== --- /dev/null +++ clang/test/Coverage/unresolved-ctor-expr.cpp @@ -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(); +} + Index: clang/lib/Serialization/ASTWriterStmt.cpp =================================================================== --- clang/lib/Serialization/ASTWriterStmt.cpp +++ clang/lib/Serialization/ASTWriterStmt.cpp @@ -1921,6 +1921,7 @@ Record.AddTypeSourceInfo(E->getTypeSourceInfo()); Record.AddSourceLocation(E->getLParenLoc()); Record.AddSourceLocation(E->getRParenLoc()); + Record.push_back(E->isListInitialization()); Code = serialization::EXPR_CXX_UNRESOLVED_CONSTRUCT; } Index: clang/lib/Serialization/ASTReaderStmt.cpp =================================================================== --- clang/lib/Serialization/ASTReaderStmt.cpp +++ clang/lib/Serialization/ASTReaderStmt.cpp @@ -2006,9 +2006,10 @@ 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) { Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -1522,16 +1522,10 @@ 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 Index: clang/lib/AST/ExprCXX.cpp =================================================================== --- clang/lib/AST/ExprCXX.cpp +++ clang/lib/AST/ExprCXX.cpp @@ -1392,17 +1392,16 @@ 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::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 @@ } SourceLocation CXXUnresolvedConstructExpr::getBeginLoc() const { - return TSI->getTypeLoc().getBeginLoc(); + return TypeAndInitForm.getPointer()->getTypeLoc().getBeginLoc(); } CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr( Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -8147,7 +8147,7 @@ return CXXUnresolvedConstructExpr::Create( Importer.getToContext(), ToType, ToTypeSourceInfo, ToLParenLoc, - llvm::ArrayRef(ToArgs), ToRParenLoc); + llvm::ArrayRef(ToArgs), ToRParenLoc, E->isListInitialization()); } ExpectedStmt Index: clang/include/clang/AST/ExprCXX.h =================================================================== --- clang/include/clang/AST/ExprCXX.h +++ clang/include/clang/AST/ExprCXX.h @@ -3504,8 +3504,9 @@ 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 @@ 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 @@ /// 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; } Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -300,6 +300,8 @@ - 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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits