diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 5 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 39 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 35 | ||||
-rw-r--r-- | lib/Sema/SemaFixItUtils.cpp | 28 |
6 files changed, 75 insertions, 38 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index be5d5ae54c..032326cea7 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1138,6 +1138,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // Parse the next declarator. D.clear(); + D.setCommaLoc(CommaLoc); // Accept attributes in an init-declarator. In the first declarator in a // declaration, these would be part of the declspec. In subsequent @@ -2665,9 +2666,11 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { // Read struct-declarators until we find the semicolon. bool FirstDeclarator = true; + SourceLocation CommaLoc; while (1) { ParsingDeclRAIIObject PD(*this); FieldDeclarator DeclaratorInfo(DS); + DeclaratorInfo.D.setCommaLoc(CommaLoc); // Attributes are only allowed here on successive declarators. if (!FirstDeclarator) @@ -2703,7 +2706,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { return; // Consume the comma. - ConsumeToken(); + CommaLoc = ConsumeToken(); FirstDeclarator = false; } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 285dbbbe07..c31c55ba5b 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2044,6 +2044,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, BitfieldSize = true; Init = true; HasInitializer = false; + DeclaratorInfo.setCommaLoc(CommaLoc); // Attributes are only allowed on the second declarator. MaybeParseGNUAttributes(DeclaratorInfo); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index d14b9adce2..e09ee79c8c 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1067,11 +1067,12 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { if (Tok.isNot(tok::comma)) break; + ParmDeclarator.clear(); + // Consume the comma. - ConsumeToken(); + ParmDeclarator.setCommaLoc(ConsumeToken()); // Parse the next declarator. - ParmDeclarator.clear(); ParseDeclarator(ParmDeclarator); } diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 3567b6bbe0..9b3191b027 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -415,42 +415,15 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { return false; // Suggest possible initialization (if any). - const char *initialization = 0; QualType VariableTy = VD->getType().getCanonicalType(); - - if (VariableTy->isObjCObjectPointerType() || - VariableTy->isBlockPointerType()) { - // Check if 'nil' is defined. - if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) - initialization = " = nil"; - else - initialization = " = 0"; - } - else if (VariableTy->isRealFloatingType()) - initialization = " = 0.0"; - else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) - initialization = " = false"; - else if (VariableTy->isEnumeralType()) + const char *Init = S.getFixItZeroInitializerForType(VariableTy); + if (!Init) return false; - else if (VariableTy->isPointerType() || VariableTy->isMemberPointerType()) { - if (S.Context.getLangOptions().CPlusPlus0x) - initialization = " = nullptr"; - // Check if 'NULL' is defined. - else if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("NULL"))) - initialization = " = NULL"; - else - initialization = " = 0"; - } - else if (VariableTy->isScalarType()) - initialization = " = 0"; - if (initialization) { - SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); - S.Diag(loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() - << FixItHint::CreateInsertion(loc, initialization); - return true; - } - return false; + SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); + S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() + << FixItHint::CreateInsertion(Loc, Init); + return true; } /// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index dc8d6ec8cf..4dcf1db2cf 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4921,8 +4921,39 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!T->isVoidType() && C.Fun.NumArgs == 0 && !C.Fun.isVariadic && !C.Fun.TrailingReturnType && C.Fun.getExceptionSpecType() == EST_None) { - Diag(C.Loc, diag::warn_empty_parens_are_function_decl) - << SourceRange(C.Loc, C.EndLoc); + SourceRange ParenRange(C.Loc, C.EndLoc); + Diag(C.Loc, diag::warn_empty_parens_are_function_decl) << ParenRange; + + // If the declaration looks like: + // T var1, + // f(); + // and name lookup finds a function named 'f', then the ',' was + // probably intended to be a ';'. + if (!D.isFirstDeclarator() && D.getIdentifier()) { + FullSourceLoc Comma(D.getCommaLoc(), SourceMgr); + FullSourceLoc Name(D.getIdentifierLoc(), SourceMgr); + if (Comma.getFileID() != Name.getFileID() || + Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) { + LookupResult Result(*this, D.getIdentifier(), SourceLocation(), + LookupOrdinaryName); + if (LookupName(Result, S)) + Diag(D.getCommaLoc(), diag::note_empty_parens_function_call) + << FixItHint::CreateReplacement(D.getCommaLoc(), ";") << NewFD; + } + } + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + // Empty parens mean value-initialization, and no parens mean default + // initialization. These are equivalent if the default constructor is + // user-provided, or if zero-initialization is a no-op. + if (RD && (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor())) + Diag(C.Loc, diag::note_empty_parens_default_ctor) + << FixItHint::CreateRemoval(ParenRange); + else if (const char *Init = getFixItZeroInitializerForType(T)) + Diag(C.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, Init); + else if (LangOpts.CPlusPlus0x) + Diag(C.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, "{}"); } } diff --git a/lib/Sema/SemaFixItUtils.cpp b/lib/Sema/SemaFixItUtils.cpp index 8e8a46da73..1f17a9e83e 100644 --- a/lib/Sema/SemaFixItUtils.cpp +++ b/lib/Sema/SemaFixItUtils.cpp @@ -158,3 +158,31 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, return false; } + +const char *Sema::getFixItZeroInitializerForType(QualType T) const { + // Suggest 'nil' if it's defined and appropriate. + if ((T->isObjCObjectPointerType() || T->isBlockPointerType()) && + PP.getMacroInfo(&getASTContext().Idents.get("nil"))) + return " = nil"; + if (T->isRealFloatingType()) + return " = 0.0"; + if (T->isBooleanType() && LangOpts.CPlusPlus) + return " = false"; + if (T->isPointerType() || T->isMemberPointerType()) { + if (LangOpts.CPlusPlus0x) + return " = nullptr"; + // Check if 'NULL' is defined. + else if (PP.getMacroInfo(&getASTContext().Idents.get("NULL"))) + return " = NULL"; + } + if (T->isEnumeralType()) + return 0; + if (T->isScalarType()) + return " = 0"; + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + if (LangOpts.CPlusPlus0x && RD && !RD->hasUserProvidedDefaultConstructor()) + return "{}"; + if (T->isAggregateType()) + return " = {}"; + return 0; +} |