From: Richard Smith Date: Mon, 30 Jul 2012 21:42:05 +0000 (+0000) Subject: Extend the ',' versus ';' diagnostic for -Wvexing-parse to cover the with-arguments... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d64effc4e31044c05d6e4400150edb26e914983a;p=clang Extend the ',' versus ';' diagnostic for -Wvexing-parse to cover the with-arguments case as well as the no-arguments case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160999 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index fcea5a75a9..e018a5bb37 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2076,13 +2076,34 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc); - // Declaration with parameters, eg. "T var(T());". - if (FTI.NumArgs > 0 && - D.getContext() != Declarator::ConditionContext) { - S.Diag(DeclType.Loc, - diag::warn_parens_disambiguated_as_function_declaration) - << ParenRange; + S.Diag(DeclType.Loc, + FTI.NumArgs ? diag::warn_parens_disambiguated_as_function_declaration + : 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(), S.SourceMgr); + FullSourceLoc Name(D.getIdentifierLoc(), S.SourceMgr); + if (Comma.getFileID() != Name.getFileID() || + Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) { + LookupResult Result(S, D.getIdentifier(), SourceLocation(), + Sema::LookupOrdinaryName); + if (S.LookupName(Result, S.getCurScope())) + S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call) + << FixItHint::CreateReplacement(D.getCommaLoc(), ";") + << D.getIdentifier(); + } + } + if (FTI.NumArgs > 0) { + // For a declaration with parameters, eg. "T var(T());", suggest adding parens + // around the first parameter to turn the declaration into a variable + // declaration. SourceRange Range = FTI.ArgInfo[0].Param->getSourceRange(); SourceLocation B = Range.getBegin(); SourceLocation E = S.PP.getLocForEndOfToken(Range.getEnd()); @@ -2091,32 +2112,12 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, S.Diag(B, diag::note_additional_parens_for_variable_declaration) << FixItHint::CreateInsertion(B, "(") << FixItHint::CreateInsertion(E, ")"); - } - - // Declaration without parameters, eg. "T var();". - if (FTI.NumArgs == 0) { - S.Diag(DeclType.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(), S.SourceMgr); - FullSourceLoc Name(D.getIdentifierLoc(), S.SourceMgr); - if (Comma.getFileID() != Name.getFileID() || - Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) { - LookupResult Result(S, D.getIdentifier(), SourceLocation(), - Sema::LookupOrdinaryName); - if (S.LookupName(Result, S.getCurScope())) - S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call) - << FixItHint::CreateReplacement(D.getCommaLoc(), ";") - << D.getIdentifier(); - } - } + } else { + // For a declaration without parameters, eg. "T var();", suggest replacing the + // parens with an initializer to turn the declaration into a variable + // declaration. const CXXRecordDecl *RD = RT->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 diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp index 7ee699c1a8..0980c40cbf 100644 --- a/test/SemaCXX/decl-expr-ambiguity.cpp +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -49,6 +49,7 @@ struct RAII { }; void func(); +void func2(short); namespace N { struct S; @@ -59,6 +60,10 @@ namespace N { S s(); // expected-warning {{function declaration}} } + void nonEmptyParens() { + int f = 0, // g = 0; expected-note {{change this ',' to a ';' to call 'func2'}} + func2(short(f)); // expected-warning {{function declaration}} expected-note {{add a pair of parentheses}} + } } class C { };