diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2016-11-12 15:38:55 +0000 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2016-11-12 15:38:55 +0000 |
commit | 3852637005b1528aac2d2e12ac7c03cb6f300e26 (patch) | |
tree | f4b28d3d5541f27d3f6ab31547ed5315a85a0749 /clang/lib/Sema | |
parent | a583be4e52d9f7d0fd36e1d44836d8297cedda2a (diff) | |
download | bcm5719-llvm-3852637005b1528aac2d2e12ac7c03cb6f300e26.tar.gz bcm5719-llvm-3852637005b1528aac2d2e12ac7c03cb6f300e26.zip |
Use descriptive message if list initializer is incorrectly parenthesized.
If initializer contains parentheses around braced list where it is not allowed,
as in construct int({0}), clang issued message like `functional-style cast
from 'void' to 'int' is not allowed`, which does not help much. Both gcc and
msvc issue message `list-initializer for non-class type must not be
parenthesized`, which is more descriptive. This change implements similar
message for clang.
Differential Revision: https://reviews.llvm.org/D25816
llvm-svn: 286721
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 25 |
2 files changed, 48 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7f443b3d3ff..fb2468f9ab9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9865,6 +9865,18 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // Perform the initialization. ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); if (!VDecl->isInvalidDecl()) { + // Handle errors like: int a({0}) + if (CXXDirectInit && CXXDirectInit->getNumExprs() == 1 && + !canInitializeWithParenthesizedList(VDecl->getType())) + if (auto IList = dyn_cast<InitListExpr>(CXXDirectInit->getExpr(0))) { + Diag(VDecl->getLocation(), diag::err_list_init_in_parens) + << VDecl->getType() << CXXDirectInit->getSourceRange() + << FixItHint::CreateRemoval(CXXDirectInit->getLocStart()) + << FixItHint::CreateRemoval(CXXDirectInit->getLocEnd()); + Init = IList; + CXXDirectInit = nullptr; + } + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); InitializationKind Kind = DirectInit @@ -10171,6 +10183,18 @@ void Sema::ActOnInitializerError(Decl *D) { // though. } +/// Checks if an object of the given type can be initialized with parenthesized +/// init-list. +/// +/// \param TargetType Type of object being initialized. +/// +/// The function is used to detect wrong initializations, such as 'int({0})'. +/// +bool Sema::canInitializeWithParenthesizedList(QualType TargetType) { + return TargetType->isDependentType() || TargetType->isRecordType() || + TargetType->getContainedAutoType(); +} + void Sema::ActOnUninitializedDecl(Decl *RealDecl, bool TypeMayContainAuto) { // If there is no declaration, there was an error parsing it. Just ignore it. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 634954c3e85..a87d5efaf08 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1221,6 +1221,17 @@ Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); + // Handle errors like: int({0}) + if (exprs.size() == 1 && !canInitializeWithParenthesizedList(Ty) && + LParenLoc.isValid() && RParenLoc.isValid()) + if (auto IList = dyn_cast<InitListExpr>(exprs[0])) { + Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens) + << Ty << IList->getSourceRange() + << FixItHint::CreateRemoval(LParenLoc) + << FixItHint::CreateRemoval(RParenLoc); + LParenLoc = RParenLoc = SourceLocation(); + } + auto Result = BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); // Avoid creating a non-type-dependent expression that contains typos. // Non-type-dependent expressions are liable to be discarded without @@ -1562,8 +1573,20 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, return ExprError(); SourceRange DirectInitRange; - if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) + if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) { DirectInitRange = List->getSourceRange(); + // Handle errors like: new int a({0}) + if (List->getNumExprs() == 1 && + !canInitializeWithParenthesizedList(AllocType)) + if (auto IList = dyn_cast<InitListExpr>(List->getExpr(0))) { + Diag(TInfo->getTypeLoc().getLocStart(), diag::err_list_init_in_parens) + << AllocType << List->getSourceRange() + << FixItHint::CreateRemoval(List->getLocStart()) + << FixItHint::CreateRemoval(List->getLocEnd()); + DirectInitRange = SourceRange(); + Initializer = IList; + } + } return BuildCXXNew(SourceRange(StartLoc, D.getLocEnd()), UseGlobal, PlacementLParen, |