From aa57a64ef69c774a37420c79a8d3b50d559c3661 Mon Sep 17 00:00:00 2001 From: Serge Pavlov Date: Tue, 8 Oct 2013 16:56:30 +0000 Subject: [PATCH] Add fixits suggesting parenthesis around type name in expressions like sizeof. This fixes PR16992 - Fixit missing when "sizeof type" found. llvm-svn: 192200 --- .../clang/Basic/DiagnosticParseKinds.td | 2 ++ clang/lib/Parse/ParseExpr.cpp | 22 +++++++++++++++++++ .../CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp | 4 ++++ .../CXX/expr/expr.unary/expr.sizeof/p1.cpp | 20 +++++++++++++++++ clang/test/Parser/expressions.c | 10 +++++++++ 5 files changed, 58 insertions(+) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 8f5ce698ce61..71463d53ef35 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -310,6 +310,8 @@ def err_unspecified_vla_size_with_static : Error< def warn_deprecated_register : Warning< "'register' storage class specifier is deprecated">, InGroup; +def err_missed_parenthesis_around_typename : Error< + "missed parenthesis around the type name in %0">; def err_expected_case_before_expression: Error< "expected 'case' keyword before expression">; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 847b074d5c81..582721cf40f1 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1589,6 +1589,28 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, // If the operand doesn't start with an '(', it must be an expression. if (Tok.isNot(tok::l_paren)) { + // If construct allows a form without parenthesis, user may forget to put + // pathenthesis around type name. + if (OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) || + OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) { + bool isAmbiguousTypeId; + if (isTypeIdInParens(isAmbiguousTypeId)) { + DeclSpec DS(AttrFactory); + ParseSpecifierQualifierList(DS); + Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + ParseDeclarator(DeclaratorInfo); + + SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation()); + SourceLocation RParenLoc = PP.getLocForEndOfToken(PrevTokLocation); + Diag(LParenLoc, diag::err_missed_parenthesis_around_typename) + << OpTok.getName() + << FixItHint::CreateInsertion(LParenLoc, "(") + << FixItHint::CreateInsertion(RParenLoc, ")"); + isCastExpr = true; + return ExprEmpty(); + } + } + isCastExpr = false; if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) { Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo(); diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp index 93b1c6461a43..05a392686786 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p7.cpp @@ -14,3 +14,7 @@ template struct Y { static_assert(alignof(Y) == alignof(int), ""); static_assert(alignof(Y) == alignof(int), ""); // expected-note {{in instantiation of}} + +void pr16992 () { + int x = alignof int; // expected-error{{missed parenthesis around the type name in alignof}} +} diff --git a/clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp b/clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp index 77d786568bdf..cd0747fce59b 100644 --- a/clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp +++ b/clang/test/CXX/expr/expr.unary/expr.sizeof/p1.cpp @@ -26,3 +26,23 @@ void test2() { x = sizeof(test2()); // expected-error {{invalid application of 'sizeof' to an incomplete type 'void'}} x = sizeof(test2); // expected-error {{invalid application of 'sizeof' to a function type}} } + +namespace pr16992 { + +template struct ABC { + int func () { + return sizeof T; //expected-error{{missed parenthesis around the type name in sizeof}} + } +}; + +ABC qq; + +template struct ABC2 { + int func () { + return sizeof T::A; + } +}; + +struct QQ { int A; }; +ABC2 qq2; +} diff --git a/clang/test/Parser/expressions.c b/clang/test/Parser/expressions.c index 0d1b6c945c5c..6c567f91baa1 100644 --- a/clang/test/Parser/expressions.c +++ b/clang/test/Parser/expressions.c @@ -57,3 +57,13 @@ void test7() { ({} // expected-note {{to match}} ; // expected-error {{expected ')'}} } + +// PR16992 +struct pr16992 { int x; }; + +void func_16992 () { + int x1 = sizeof int; // expected-error{{missed parenthesis around the type name in sizeof}} + int x2 = sizeof struct pr16992; // expected-error{{missed parenthesis around the type name in sizeof}} + int x3 = __alignof int; // expected-error{{missed parenthesis around the type name in __alignof}} + int x4 = _Alignof int; // expected-error{{missed parenthesis around the type name in _Alignof}} +}