Index: clang-tidy/misc/MacroParenthesesCheck.cpp =================================================================== --- clang-tidy/misc/MacroParenthesesCheck.cpp +++ 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,31 @@ tok::amp, tok::pipe, tok::caret); } +static bool possibleVarDecl(const MacroInfo *MI) { + if (MI->tokens_empty()) + return false; + + const Token *Tok = MI->tokens_begin(); + + // Skip possible unknown types + while (Tok != MI->tokens_end() && !isKeyword(*Tok) && + Tok->isOneOf(tok::identifier, tok::raw_identifier) && + MI->getArgumentNum(Tok->getIdentifierInfo()) < 0) { + Tok++; + } + + // Return true for 'UNKNOWN_ID*X', 'UNKNOWN_ID X' etc. + return Tok != MI->tokens_begin() && Tok != MI->tokens_end() && !isKeyword(*Tok) && + Tok->isOneOf(tok::star, tok::identifier, tok::raw_identifier); +} + void MacroParenthesesPPCallbacks::replacementList(const Token &MacroNameTok, const MacroInfo *MI) { + // Make sure macro replacement isn't a variable declaration, that begins + // with unknown identifier(s). + if (possibleVarDecl(MI)) + return; + // Count how deep we are in parentheses/braces/squares. int Count = 0; @@ -117,6 +139,7 @@ void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, const MacroInfo *MI) { + bool VarDecl = possibleVarDecl(MI); for (auto TI = MI->tokens_begin(), TE = MI->tokens_end(); TI != TE; ++TI) { // First token. @@ -132,6 +155,13 @@ const Token &Tok = *TI; + // Don't warn in possible variable declaration. + if (VarDecl) { + if (Tok.is(tok::equal)) + VarDecl = false; + continue; + } + // Only interested in identifiers. if (!Tok.isOneOf(tok::identifier, tok::raw_identifier)) continue; Index: test/clang-tidy/misc-macro-parentheses.cpp =================================================================== --- test/clang-tidy/misc-macro-parentheses.cpp +++ 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,7 @@ #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 // These are allowed for now.. #define MAYBE1 *12.34