diff options
author | Vedant Kumar <vsk@apple.com> | 2018-01-17 18:53:51 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2018-01-17 18:53:51 +0000 |
commit | a14a1f923f45381ba96acd5246506b470ae7b23c (patch) | |
tree | 9811639e7fab91d76fc9d727a9c4ad7e473e9f03 /clang/lib | |
parent | cc9fd4b6617944ff19cb2faa505f6d23d4578e62 (diff) | |
download | bcm5719-llvm-a14a1f923f45381ba96acd5246506b470ae7b23c.tar.gz bcm5719-llvm-a14a1f923f45381ba96acd5246506b470ae7b23c.zip |
[Parse] Forward brace locations to TypeConstructExpr
When parsing C++ type construction expressions with list initialization,
forward the locations of the braces to Sema.
Without these locations, the code coverage pass crashes on the given test
case, because the pass relies on getLocEnd() returning a valid location.
Here is what this patch does in more detail:
- Forwards init-list brace locations to Sema (ParseExprCXX),
- Builds an InitializationKind with these locations (SemaExprCXX), and
- Uses these locations for constructor initialization (SemaInit).
The remaining changes fall out of introducing a new overload for
creating direct-list InitializationKinds.
Testing: check-clang, and a stage2 coverage-enabled build of clang with
asserts enabled.
Differential Revision: https://reviews.llvm.org/D41921
llvm-svn: 322729
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CoverageMappingGen.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 29 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 58 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 51 |
7 files changed, 100 insertions, 79 deletions
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp index 89a30dc7040..5eb48c2b579 100644 --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -74,7 +74,10 @@ public: bool hasEndLoc() const { return LocEnd.hasValue(); } - void setEndLoc(SourceLocation Loc) { LocEnd = Loc; } + void setEndLoc(SourceLocation Loc) { + assert(Loc.isValid() && "Setting an invalid end location"); + LocEnd = Loc; + } SourceLocation getEndLoc() const { assert(LocEnd && "Region has no end location"); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 554ab24b02e..914f6f3613b 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1672,9 +1672,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { if (Init.isInvalid()) return Init; Expr *InitList = Init.get(); - return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(), - MultiExprArg(&InitList, 1), - SourceLocation()); + return Actions.ActOnCXXTypeConstructExpr( + TypeRep, InitList->getLocStart(), MultiExprArg(&InitList, 1), + InitList->getLocEnd(), /*ListInitialization=*/true); } else { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -1702,9 +1702,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); - return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(), - Exprs, - T.getCloseLocation()); + return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(), + Exprs, T.getCloseLocation(), + /*ListInitialization=*/false); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6873feb7802..28a88d5bb8b 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3589,9 +3589,12 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, ExprResult Init = InitExpr; if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { InitializedEntity Entity = InitializedEntity::InitializeMember(FD); - InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit - ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) - : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc); + InitializationKind Kind = + FD->getInClassInitStyle() == ICIS_ListInit + ? InitializationKind::CreateDirectList(InitExpr->getLocStart(), + InitExpr->getLocStart(), + InitExpr->getLocEnd()) + : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc); InitializationSequence Seq(*this, Entity, Kind, InitExpr); Init = Seq.Perform(*this, Entity, Kind, InitExpr); if (Init.isInvalid()) { @@ -3986,9 +3989,10 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, : InitializedEntity::InitializeMember(IndirectMember, nullptr); InitializationKind Kind = - InitList ? InitializationKind::CreateDirectList(IdLoc) - : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), - InitRange.getEnd()); + InitList ? InitializationKind::CreateDirectList( + IdLoc, Init->getLocStart(), Init->getLocEnd()) + : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, MemberEntity, Kind, Args); ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, @@ -4040,9 +4044,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = - InitList ? InitializationKind::CreateDirectList(NameLoc) - : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), - InitRange.getEnd()); + InitList ? InitializationKind::CreateDirectList( + NameLoc, Init->getLocStart(), Init->getLocEnd()) + : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args); ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, Args, nullptr); @@ -4174,9 +4179,9 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, InitializedEntity BaseEntity = InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); InitializationKind Kind = - InitList ? InitializationKind::CreateDirectList(BaseLoc) - : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), - InitRange.getEnd()); + InitList ? InitializationKind::CreateDirectList(BaseLoc) + : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), + InitRange.getEnd()); InitializationSequence InitSeq(*this, BaseEntity, Kind, Args); ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr); if (BaseInit.isInvalid()) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1d7a5d2e128..d7490b68a6f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11601,8 +11601,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, // C++11 5.17p9: // The meaning of x = {v} [...] is that of x = T(v) [...]. The meaning // of x = {} is x = T(). - InitializationKind Kind = - InitializationKind::CreateDirectList(RHSExpr->getLocStart()); + InitializationKind Kind = InitializationKind::CreateDirectList( + RHSExpr->getLocStart(), RHSExpr->getLocStart(), RHSExpr->getLocEnd()); InitializedEntity Entity = InitializedEntity::InitializeTemporary(LHSExpr->getType()); InitializationSequence InitSeq(*this, Entity, Kind, RHSExpr); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 5bbb367eee5..f0994d7bcdc 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1244,11 +1244,16 @@ bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) { return Class && Class->isBeingDefined(); } +/// Parse construction of a specified type. +/// Can be interpreted either as function-style casting ("int(x)") +/// or class type construction ("ClassType(x,y,z)") +/// or creation of a value-initialized type ("int()"). ExprResult Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, - SourceLocation LParenLoc, + SourceLocation LParenOrBraceLoc, MultiExprArg exprs, - SourceLocation RParenLoc) { + SourceLocation RParenOrBraceLoc, + bool ListInitialization) { if (!TypeRep) return ExprError(); @@ -1257,7 +1262,8 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); - auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); + auto Result = BuildCXXTypeConstructExpr(TInfo, LParenOrBraceLoc, exprs, + RParenOrBraceLoc, ListInitialization); // Avoid creating a non-type-dependent expression that contains typos. // Non-type-dependent expressions are liable to be discarded without // checking for embedded typos. @@ -1267,38 +1273,40 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, return Result; } -/// ActOnCXXTypeConstructExpr - Parse construction of a specified type. -/// Can be interpreted either as function-style casting ("int(x)") -/// or class type construction ("ClassType(x,y,z)") -/// or creation of a value-initialized type ("int()"). ExprResult Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, - SourceLocation LParenLoc, + SourceLocation LParenOrBraceLoc, MultiExprArg Exprs, - SourceLocation RParenLoc) { + SourceLocation RParenOrBraceLoc, + bool ListInitialization) { QualType Ty = TInfo->getType(); SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) { - return CXXUnresolvedConstructExpr::Create(Context, TInfo, LParenLoc, Exprs, - RParenLoc); + // 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, TInfo, Locs.getBegin(), + Exprs, Locs.getEnd()); } - bool ListInitialization = LParenLoc.isInvalid(); assert((!ListInitialization || (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) && "List initialization must have initializer list as expression."); - SourceRange FullRange = SourceRange(TyBeginLoc, - ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc); + SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc); InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); InitializationKind Kind = Exprs.size() ? ListInitialization - ? InitializationKind::CreateDirectList(TyBeginLoc) - : InitializationKind::CreateDirect(TyBeginLoc, LParenLoc, - RParenLoc) - : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc); + ? InitializationKind::CreateDirectList( + TyBeginLoc, LParenOrBraceLoc, RParenOrBraceLoc) + : InitializationKind::CreateDirect(TyBeginLoc, LParenOrBraceLoc, + RParenOrBraceLoc) + : InitializationKind::CreateValue(TyBeginLoc, LParenOrBraceLoc, + RParenOrBraceLoc); // C++1z [expr.type.conv]p1: // If the type is a placeholder for a deduced class type, [...perform class @@ -1319,7 +1327,8 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, if (Exprs.size() == 1 && !ListInitialization && !isa<InitListExpr>(Exprs[0])) { Expr *Arg = Exprs[0]; - return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenLoc, Arg, RParenLoc); + return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenOrBraceLoc, Arg, + RParenOrBraceLoc); } // For an expression of the form T(), T shall not be an array type. @@ -1367,9 +1376,12 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // CXXTemporaryObjectExpr. It's also weird that the functional cast // is sometimes handled by initialization and sometimes not. QualType ResultType = Result.get()->getType(); + SourceRange Locs = ListInitialization + ? SourceRange() + : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); Result = CXXFunctionalCastExpr::Create( - Context, ResultType, Expr::getValueKindForType(Ty), TInfo, - CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc); + Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, + Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd()); } return Result; @@ -1728,7 +1740,9 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // - Otherwise, the new-initializer is interpreted according to the // initialization rules of 8.5 for direct-initialization. : initStyle == CXXNewExpr::ListInit - ? InitializationKind::CreateDirectList(TypeRange.getBegin()) + ? InitializationKind::CreateDirectList(TypeRange.getBegin(), + Initializer->getLocStart(), + Initializer->getLocEnd()) : InitializationKind::CreateDirect(TypeRange.getBegin(), DirectInitRange.getBegin(), DirectInitRange.getEnd()); diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 011051da58e..464a311ea9d 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3533,8 +3533,8 @@ static bool TryInitializerListConstruction(Sema &S, clang::ArrayType::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); - InitializationKind Kind = - InitializationKind::CreateDirectList(List->getExprLoc()); + InitializationKind Kind = InitializationKind::CreateDirectList( + List->getExprLoc(), List->getLocStart(), List->getLocEnd()); TryListInitialization(S, HiddenArray, Kind, List, Sequence, TreatUnavailableAsInvalid); if (Sequence) @@ -6031,10 +6031,7 @@ PerformConstructorInitialization(Sema &S, TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); if (!TSInfo) TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); - SourceRange ParenOrBraceRange = - (Kind.getKind() == InitializationKind::IK_DirectList) - ? SourceRange(LBraceLoc, RBraceLoc) - : Kind.getParenRange(); + SourceRange ParenOrBraceRange = Kind.getParenOrBraceRange(); if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>( Step.Function.FoundDecl.getDecl())) { @@ -6068,7 +6065,7 @@ PerformConstructorInitialization(Sema &S, if (IsListInitialization) ParenOrBraceRange = SourceRange(LBraceLoc, RBraceLoc); else if (Kind.getKind() == InitializationKind::IK_Direct) - ParenOrBraceRange = Kind.getParenRange(); + ParenOrBraceRange = Kind.getParenOrBraceRange(); // If the entity allows NRVO, mark the construction as elidable // unconditionally. @@ -6594,7 +6591,7 @@ InitializationSequence::Perform(Sema &S, if (Kind.getKind() == InitializationKind::IK_Direct && !Kind.isExplicitCast()) { // Rebuild the ParenListExpr. - SourceRange ParenRange = Kind.getParenRange(); + SourceRange ParenRange = Kind.getParenOrBraceRange(); return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(), Args); } @@ -7114,14 +7111,17 @@ InitializationSequence::Perform(Sema &S, bool IsStdInitListInit = Step->Kind == SK_StdInitializerListConstructorCall; Expr *Source = CurInit.get(); + SourceRange Range = Kind.hasParenOrBraceRange() + ? Kind.getParenOrBraceRange() + : SourceRange(); CurInit = PerformConstructorInitialization( S, UseTemporary ? TempEntity : Entity, Kind, Source ? MultiExprArg(Source) : Args, *Step, ConstructorInitRequiresZeroInit, /*IsListInitialization*/ IsStdInitListInit, /*IsStdInitListInitialization*/ IsStdInitListInit, - /*LBraceLoc*/ SourceLocation(), - /*RBraceLoc*/ SourceLocation()); + /*LBraceLoc*/ Range.getBegin(), + /*RBraceLoc*/ Range.getEnd()); break; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 809187f0aee..4eb45bc0c9a 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -2581,10 +2581,11 @@ public: ExprResult RebuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, SourceLocation LParenLoc, Expr *Sub, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + bool ListInitialization) { return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc, - MultiExprArg(&Sub, 1), - RParenLoc); + MultiExprArg(&Sub, 1), RParenLoc, + ListInitialization); } /// \brief Build a new C++ typeid(type) expression. @@ -2684,8 +2685,8 @@ public: ExprResult RebuildCXXScalarValueInitExpr(TypeSourceInfo *TSInfo, SourceLocation LParenLoc, SourceLocation RParenLoc) { - return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, - None, RParenLoc); + return getSema().BuildCXXTypeConstructExpr( + TSInfo, LParenLoc, None, RParenLoc, /*ListInitialization=*/false); } /// \brief Build a new C++ "new" expression. @@ -2842,13 +2843,12 @@ public: /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. ExprResult RebuildCXXTemporaryObjectExpr(TypeSourceInfo *TSInfo, - SourceLocation LParenLoc, + SourceLocation LParenOrBraceLoc, MultiExprArg Args, - SourceLocation RParenLoc) { - return getSema().BuildCXXTypeConstructExpr(TSInfo, - LParenLoc, - Args, - RParenLoc); + SourceLocation RParenOrBraceLoc, + bool ListInitialization) { + return getSema().BuildCXXTypeConstructExpr( + TSInfo, LParenOrBraceLoc, Args, RParenOrBraceLoc, ListInitialization); } /// \brief Build a new object-construction expression. @@ -2858,11 +2858,10 @@ public: ExprResult RebuildCXXUnresolvedConstructExpr(TypeSourceInfo *TSInfo, SourceLocation LParenLoc, MultiExprArg Args, - SourceLocation RParenLoc) { - return getSema().BuildCXXTypeConstructExpr(TSInfo, - LParenLoc, - Args, - RParenLoc); + SourceLocation RParenLoc, + bool ListInitialization) { + return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, Args, + RParenLoc, ListInitialization); } /// \brief Build a new member reference expression. @@ -9936,7 +9935,8 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr( return getDerived().RebuildCXXFunctionalCastExpr(Type, E->getLParenLoc(), SubExpr.get(), - E->getRParenLoc()); + E->getRParenLoc(), + E->isListInitialization()); } template<typename Derived> @@ -10852,11 +10852,12 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( return SemaRef.MaybeBindToTemporary(E); } - // FIXME: Pass in E->isListInitialization(). - return getDerived().RebuildCXXTemporaryObjectExpr(T, - /*FIXME:*/T->getTypeLoc().getEndLoc(), - Args, - E->getLocEnd()); + // FIXME: We should just pass E->isListInitialization(), but we're not + // prepared to handle list-initialization without a child InitListExpr. + SourceLocation LParenLoc = T->getTypeLoc().getEndLoc(); + return getDerived().RebuildCXXTemporaryObjectExpr( + T, LParenLoc, Args, E->getLocEnd(), + /*ListInitialization=*/LParenLoc.isInvalid()); } template<typename Derived> @@ -11142,10 +11143,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( return E; // FIXME: we're faking the locations of the commas - return getDerived().RebuildCXXUnresolvedConstructExpr(T, - E->getLParenLoc(), - Args, - E->getRParenLoc()); + return getDerived().RebuildCXXUnresolvedConstructExpr( + T, E->getLParenLoc(), Args, E->getRParenLoc(), E->isListInitialization()); } template<typename Derived> |