This revision was automatically updated to reflect the committed changes.
Closed by commit rL272128 (authored by danielmarjamaki).

Changed prior to commit:
  http://reviews.llvm.org/D20853?vs=59208&id=60013#toc

Repository:
  rL LLVM

http://reviews.llvm.org/D20853

Files:
  clang-tools-extra/trunk/clang-tidy/misc/MacroParenthesesCheck.cpp
  clang-tools-extra/trunk/test/clang-tidy/misc-macro-parentheses.cpp

Index: clang-tools-extra/trunk/clang-tidy/misc/MacroParenthesesCheck.cpp
===================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/MacroParenthesesCheck.cpp
+++ clang-tools-extra/trunk/clang-tidy/misc/MacroParenthesesCheck.cpp
@@ -19,8 +19,7 @@
 namespace {
 class MacroParenthesesPPCallbacks : public PPCallbacks {
 public:
-  MacroParenthesesPPCallbacks(Preprocessor *PP,
-                              MacroParenthesesCheck *Check)
+  MacroParenthesesPPCallbacks(Preprocessor *PP, MacroParenthesesCheck *Check)
       : PP(PP), Check(Check) {}
 
   void MacroDefined(const Token &MacroNameTok,
@@ -67,8 +66,46 @@
                    tok::amp, tok::pipe, tok::caret);
 }
 
+/// Is given Token a keyword that is used in variable declarations?
+static bool isVarDeclKeyword(const Token &T) {
+  return T.isOneOf(tok::kw_bool, tok::kw_char, tok::kw_short, tok::kw_int,
+                   tok::kw_long, tok::kw_float, tok::kw_double, tok::kw_const,
+                   tok::kw_enum, tok::kw_inline, tok::kw_static, tok::kw_struct,
+                   tok::kw_signed, tok::kw_unsigned);
+}
+
+/// Is there a possible variable declaration at Tok?
+static bool possibleVarDecl(const MacroInfo *MI, const Token *Tok) {
+  if (Tok == MI->tokens_end())
+    return false;
+
+  // If we see int/short/struct/etc., just assume this is a variable declaration.
+  if (isVarDeclKeyword(*Tok))
+    return true;
+
+  // Variable declarations start with identifier or coloncolon.
+  if (!Tok->isOneOf(tok::identifier, tok::raw_identifier, tok::coloncolon))
+    return false;
+
+  // Skip possible types, etc
+  while (
+      Tok != MI->tokens_end() &&
+      Tok->isOneOf(tok::identifier, tok::raw_identifier, tok::coloncolon,
+                    tok::star, tok::amp, tok::ampamp, tok::less, tok::greater))
+    Tok++;
+
+  // Return true for possible variable declarations.
+  return Tok == MI->tokens_end() ||
+         Tok->isOneOf(tok::equal, tok::semi, tok::l_square, tok::l_paren) ||
+         isVarDeclKeyword(*Tok);
+}
+
 void MacroParenthesesPPCallbacks::replacementList(const Token &MacroNameTok,
                                                   const MacroInfo *MI) {
+  // Make sure macro replacement isn't a variable declaration.
+  if (possibleVarDecl(MI, MI->tokens_begin()))
+    return;
+
   // Count how deep we are in parentheses/braces/squares.
   int Count = 0;
 
@@ -117,6 +154,9 @@
 
 void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok,
                                            const MacroInfo *MI) {
+  
+  // Skip variable declaration.
+  bool VarDecl = possibleVarDecl(MI, MI->tokens_begin());
 
   for (auto TI = MI->tokens_begin(), TE = MI->tokens_end(); TI != TE; ++TI) {
     // First token.
@@ -132,6 +172,13 @@
 
     const Token &Tok = *TI;
 
+    // There should not be extra parentheses in possible variable declaration.
+    if (VarDecl) {
+      if (Tok.isOneOf(tok::equal, tok::semi, tok::l_square, tok::l_paren))
+        VarDecl = false;
+      continue;
+    }
+
     // Only interested in identifiers.
     if (!Tok.isOneOf(tok::identifier, tok::raw_identifier))
       continue;
Index: clang-tools-extra/trunk/test/clang-tidy/misc-macro-parentheses.cpp
===================================================================
--- clang-tools-extra/trunk/test/clang-tidy/misc-macro-parentheses.cpp
+++ clang-tools-extra/trunk/test/clang-tidy/misc-macro-parentheses.cpp
@@ -8,6 +8,8 @@
 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: macro argument should be enclosed in parentheses [misc-macro-parentheses]
 #define BAD4(x)           ((unsigned char)(x & 0xff))
 // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: macro argument should be enclosed in parentheses [misc-macro-parentheses]
+#define BAD5(X)           A*B=(C*)X+2
+// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: macro argument should be enclosed in parentheses [misc-macro-parentheses]
 
 #define GOOD1             1
 #define GOOD2             (1+2)
@@ -39,6 +41,8 @@
 #define GOOD28(x)         namespace x {int b;}
 #define GOOD29(...)       std::cout << __VA_ARGS__;
 #define GOOD30(args...)   std::cout << args;
+#define GOOD31(X)         A*X=2
+#define GOOD32(X)         std::vector<X>
 
 // These are allowed for now..
 #define MAYBE1            *12.34
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to