[cfe-commits] r119838 - in /cfe/trunk: include/clang/AST/Stmt.h include/clang/Lex/Preprocessor.h include/clang/Parse/Parser.h include/clang/Sema/Sema.h lib/AST/Stmt.cpp lib/Lex/PPMacroExpansion.cpp lib/Parse/ParseStmt.cpp lib/Sema/SemaStmt.cpp lib/Sema/TreeTransform.h lib/Serialization/ASTReaderStmt.cpp lib/Serialization/ASTWriterStmt.cpp test/Sema/if-empty-body.c test/SemaCXX/if-empty-body.cpp
Argyrios Kyrtzidis
akyrtzi at gmail.com
Fri Nov 19 12:54:26 PST 2010
Author: akirtzidis
Date: Fri Nov 19 14:54:25 2010
New Revision: 119838
URL: http://llvm.org/viewvc/llvm-project?rev=119838&view=rev
Log:
Don't warn for empty 'if' body if there is a macro that expands to nothing, e.g:
if (condition)
CALL(0); // empty macro but don't warn for empty body.
Fixes rdar://8436021.
Added:
cfe/trunk/test/SemaCXX/if-empty-body.cpp
- copied, changed from r119817, cfe/trunk/test/Sema/if-empty-body.c
Removed:
cfe/trunk/test/Sema/if-empty-body.c
Modified:
cfe/trunk/include/clang/AST/Stmt.h
cfe/trunk/include/clang/Lex/Preprocessor.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/Stmt.cpp
cfe/trunk/lib/Lex/PPMacroExpansion.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Sema/SemaStmt.cpp
cfe/trunk/lib/Sema/TreeTransform.h
cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri Nov 19 14:54:25 2010
@@ -651,10 +651,19 @@
SourceLocation IfLoc;
SourceLocation ElseLoc;
-
+
+ /// \brief True if we have code like:
+ /// @code
+ /// #define CALL(x)
+ /// if (condition)
+ /// CALL(0);
+ /// @endcode
+ bool MacroExpandedInThenStmt;
+
public:
IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
- Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0);
+ Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0,
+ bool macroExpandedInThenStmt = false);
/// \brief Build an empty if/then/else statement
explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
@@ -686,6 +695,8 @@
SourceLocation getElseLoc() const { return ElseLoc; }
void setElseLoc(SourceLocation L) { ElseLoc = L; }
+ bool hasMacroExpandedInThenStmt() const { return MacroExpandedInThenStmt; }
+
virtual SourceRange getSourceRange() const {
if (SubExprs[ELSE])
return SourceRange(IfLoc, SubExprs[ELSE]->getLocEnd());
@@ -702,6 +713,9 @@
// over the initialization expression referenced by the condition variable.
virtual child_iterator child_begin();
virtual child_iterator child_end();
+
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
};
/// SwitchStmt - This represents a 'switch' stmt.
Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Fri Nov 19 14:54:25 2010
@@ -47,6 +47,7 @@
class CodeCompletionHandler;
class DirectoryLookup;
class PreprocessingRecord;
+class PPMacroExpansionTrap;
/// Preprocessor - This object engages in a tight little dance with the lexer to
/// efficiently preprocess tokens. Lexers know only about tokens within a
@@ -110,6 +111,11 @@
/// DisableMacroExpansion - True if macro expansion is disabled.
bool DisableMacroExpansion : 1;
+ /// \brief This is set to true when a macro is expanded.
+ /// Used by PPMacroExpansionTrap.
+ bool MacroExpansionFlag : 1;
+ friend class PPMacroExpansionTrap;
+
/// \brief Whether we have already loaded macros from the external source.
mutable bool ReadMacrosFromExternalSource : 1;
@@ -1029,6 +1035,17 @@
virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0;
};
+/// \brief RAII class that determines when any macro expansion has occurred
+/// between the time the instance was created and the time it was
+/// queried.
+class PPMacroExpansionTrap {
+ Preprocessor &PP;
+public:
+ PPMacroExpansionTrap(Preprocessor &PP) : PP(PP) { reset(); }
+ bool hasMacroExpansionOccured() const { return PP.MacroExpansionFlag; }
+ void reset() { PP.MacroExpansionFlag = false; }
+};
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Nov 19 14:54:25 2010
@@ -1199,7 +1199,8 @@
bool ParseParenExprOrCondition(ExprResult &ExprResult,
Decl *&DeclResult,
SourceLocation Loc,
- bool ConvertToBoolean);
+ bool ConvertToBoolean,
+ bool *MacroExpandedAfterRParen = 0);
StmtResult ParseIfStatement(AttributeList *Attr);
StmtResult ParseSwitchStatement(AttributeList *Attr);
StmtResult ParseWhileStatement(AttributeList *Attr);
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Nov 19 14:54:25 2010
@@ -1590,7 +1590,7 @@
bool HasUnusedAttr);
StmtResult ActOnIfStmt(SourceLocation IfLoc,
FullExprArg CondVal, Decl *CondVar,
- Stmt *ThenVal,
+ Stmt *ThenVal, bool MacroExpandedInThenStmt,
SourceLocation ElseLoc, Stmt *ElseVal);
StmtResult ActOnStartOfSwitchStmt(SourceLocation SwitchLoc,
Expr *Cond,
Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Fri Nov 19 14:54:25 2010
@@ -470,8 +470,10 @@
}
IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
- Stmt *then, SourceLocation EL, Stmt *elsev)
- : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL)
+ Stmt *then, SourceLocation EL, Stmt *elsev,
+ bool macroExpandedInThenStmt)
+ : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL),
+ MacroExpandedInThenStmt(macroExpandedInThenStmt)
{
setConditionVariable(C, var);
SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Fri Nov 19 14:54:25 2010
@@ -176,6 +176,7 @@
/// expanded as a macro, handle it and return the next token as 'Identifier'.
bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier,
MacroInfo *MI) {
+ MacroExpansionFlag = true;
if (Callbacks) Callbacks->MacroExpands(Identifier, MI);
// If this is a macro expansion in the "#if !defined(x)" line for the file,
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Fri Nov 19 14:54:25 2010
@@ -538,7 +538,8 @@
bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult,
Decl *&DeclResult,
SourceLocation Loc,
- bool ConvertToBoolean) {
+ bool ConvertToBoolean,
+ bool *MacroExpandedAfterRParen) {
bool ParseError = false;
SourceLocation LParenLoc = ConsumeParen();
@@ -567,7 +568,14 @@
}
// Otherwise the condition is valid or the rparen is present.
+
+ // Catch a macro expansion after ')'. This is used to know that there is a
+ // macro for 'if' body and not warn for empty body if the macro is empty.
+ PPMacroExpansionTrap MacroExpansionTrap(PP);
MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ if (MacroExpandedAfterRParen)
+ *MacroExpandedAfterRParen = MacroExpansionTrap.hasMacroExpansionOccured();
+
return false;
}
@@ -610,7 +618,9 @@
// Parse the condition.
ExprResult CondExp;
Decl *CondVar = 0;
- if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true))
+ bool MacroExpandedInThenStmt;
+ if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true,
+ &MacroExpandedInThenStmt))
return StmtError();
FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get()));
@@ -694,7 +704,7 @@
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(),
- ElseLoc, ElseStmt.get());
+ MacroExpandedInThenStmt, ElseLoc, ElseStmt.get());
}
/// ParseSwitchStatement
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Fri Nov 19 14:54:25 2010
@@ -282,8 +282,8 @@
StmtResult
Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
- Stmt *thenStmt, SourceLocation ElseLoc,
- Stmt *elseStmt) {
+ Stmt *thenStmt, bool MacroExpandedInThenStmt,
+ SourceLocation ElseLoc, Stmt *elseStmt) {
ExprResult CondResult(CondVal.release());
VarDecl *ConditionVar = 0;
@@ -304,17 +304,23 @@
// if (condition);
// do_stuff();
//
- // NOTE: Do not emit this warning if the body is expanded from a macro.
if (!elseStmt) {
if (NullStmt* stmt = dyn_cast<NullStmt>(thenStmt))
- if (!stmt->getLocStart().isMacroID())
+ // But do not warn if the body is a macro that expands to nothing, e.g:
+ //
+ // #define CALL(x)
+ // if (condition)
+ // CALL(0);
+ //
+ if (!MacroExpandedInThenStmt)
Diag(stmt->getSemiLoc(), diag::warn_empty_if_body);
}
DiagnoseUnusedExprResult(elseStmt);
return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr,
- thenStmt, ElseLoc, elseStmt));
+ thenStmt, ElseLoc, elseStmt,
+ MacroExpandedInThenStmt));
}
/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Nov 19 14:54:25 2010
@@ -772,9 +772,11 @@
/// By default, performs semantic analysis to build the new statement.
/// Subclasses may override this routine to provide different behavior.
StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,
- VarDecl *CondVar, Stmt *Then,
+ VarDecl *CondVar, Stmt *Then,
+ bool MacroExpandedInThenStmt,
SourceLocation ElseLoc, Stmt *Else) {
- return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else);
+ return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then,
+ MacroExpandedInThenStmt, ElseLoc, Else);
}
/// \brief Start building a new switch statement.
@@ -3692,7 +3694,7 @@
return SemaRef.Owned(S);
return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,
- Then.get(),
+ Then.get(), S->hasMacroExpandedInThenStmt(),
S->getElseLoc(), Else.get());
}
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Fri Nov 19 14:54:25 2010
@@ -256,6 +256,7 @@
S->setElse(Reader.ReadSubStmt());
S->setIfLoc(ReadSourceLocation(Record, Idx));
S->setElseLoc(ReadSourceLocation(Record, Idx));
+ S->MacroExpandedInThenStmt = Record[Idx++];
}
void ASTStmtReader::VisitSwitchStmt(SwitchStmt *S) {
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=119838&r1=119837&r2=119838&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Fri Nov 19 14:54:25 2010
@@ -228,6 +228,7 @@
Writer.AddStmt(S->getElse());
Writer.AddSourceLocation(S->getIfLoc(), Record);
Writer.AddSourceLocation(S->getElseLoc(), Record);
+ Record.push_back(S->MacroExpandedInThenStmt);
Code = serialization::STMT_IF;
}
Removed: cfe/trunk/test/Sema/if-empty-body.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/if-empty-body.c?rev=119837&view=auto
==============================================================================
--- cfe/trunk/test/Sema/if-empty-body.c (original)
+++ cfe/trunk/test/Sema/if-empty-body.c (removed)
@@ -1,24 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-
-void f1(int a) {
- if (a); // expected-warning {{if statement has empty body}}
-}
-
-void f2(int a) {
- if (a) {}
-}
-
-void f3() {
- if (1)
- xx; // expected-error {{use of undeclared identifier}}
- return; // no empty body warning.
-}
-
-// Don't warn about an empty body if is expanded from a macro.
-void f4(int i) {
- #define BODY ;
- if (i == i) // expected-warning{{self-comparison always evaluates to true}}
- BODY
- #undef BODY
-}
-
Copied: cfe/trunk/test/SemaCXX/if-empty-body.cpp (from r119817, cfe/trunk/test/Sema/if-empty-body.c)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/if-empty-body.cpp?p2=cfe/trunk/test/SemaCXX/if-empty-body.cpp&p1=cfe/trunk/test/Sema/if-empty-body.c&r1=119817&r2=119838&rev=119838&view=diff
==============================================================================
--- cfe/trunk/test/Sema/if-empty-body.c (original)
+++ cfe/trunk/test/SemaCXX/if-empty-body.cpp Fri Nov 19 14:54:25 2010
@@ -16,9 +16,20 @@
// Don't warn about an empty body if is expanded from a macro.
void f4(int i) {
- #define BODY ;
+ #define BODY(x)
if (i == i) // expected-warning{{self-comparison always evaluates to true}}
- BODY
+ BODY(0);
#undef BODY
}
+template <typename T>
+void tf() {
+ #define BODY(x)
+ if (0)
+ BODY(0);
+ #undef BODY
+}
+
+void f5() {
+ tf<int>();
+}
More information about the cfe-commits
mailing list