[cfe-commits] r39397 - in /cfe/cfe/trunk: Lex/PPExpressions.cpp clang.xcodeproj/project.pbxproj
clattner at cs.uiuc.edu
clattner at cs.uiuc.edu
Wed Jul 11 09:43:57 PDT 2007
Author: clattner
Date: Wed Jul 11 11:43:56 2007
New Revision: 39397
URL: http://llvm.org/viewvc/llvm-project?rev=39397&view=rev
Log:
Diagnostics relating to computation of values should only be produced if an
expression is live. For example:
#if 0 ? 124/0 : 42
should cause no error.
This implements test/Preprocessor/expr_liveness.c
Modified:
cfe/cfe/trunk/Lex/PPExpressions.cpp
cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
Modified: cfe/cfe/trunk/Lex/PPExpressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/PPExpressions.cpp?rev=39397&r1=39396&r2=39397&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/PPExpressions.cpp (original)
+++ cfe/cfe/trunk/Lex/PPExpressions.cpp Wed Jul 11 11:43:56 2007
@@ -29,7 +29,8 @@
using namespace clang;
static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec,
- LexerToken &PeekTok, Preprocessor &PP);
+ LexerToken &PeekTok, bool ValueLive,
+ Preprocessor &PP);
/// DefinedTracker - This struct is used while parsing expressions to keep track
/// of whether !defined(X) has been seen.
@@ -57,8 +58,13 @@
/// return the computed value in Result. Return true if there was an error
/// parsing. This function also returns information about the form of the
/// expression in DT. See above for information on what DT means.
+///
+/// If ValueLive is false, then this value is being evaluated in a context where
+/// the result is not used. As such, avoid diagnostics that relate to
+/// evaluation.
static bool EvaluateValue(APSInt &Result, LexerToken &PeekTok,
- DefinedTracker &DT, Preprocessor &PP) {
+ DefinedTracker &DT, bool ValueLive,
+ Preprocessor &PP) {
Result = 0;
DT.State = DefinedTracker::Unknown;
@@ -99,7 +105,7 @@
Result.setIsUnsigned(false); // Result is signed intmax_t.
// If there is a macro, mark it used.
- if (Result != 0) {
+ if (Result != 0 && ValueLive) {
II->getMacroInfo()->setIsUsed(true);
// If this is the first use of a target-specific macro, warn about it.
@@ -109,7 +115,7 @@
PP.getTargetInfo().DiagnoseNonPortability(PeekTok.getLocation(),
diag::port_target_macro_use);
}
- } else {
+ } else if (ValueLive) {
// Use of a target-specific macro for some other target? If so, warn.
if (II->isOtherTargetMacro()) {
II->setIsOtherTargetMacro(false); // Don't warn on second use.
@@ -165,7 +171,7 @@
// Parse the integer literal into Result.
if (Literal.GetIntegerValue(Result)) {
// Overflow parsing integer literal.
- PP.Diag(PeekTok, diag::warn_integer_too_large);
+ if (ValueLive) PP.Diag(PeekTok, diag::warn_integer_too_large);
Result.setIsUnsigned(true);
} else {
// Set the signedness of the result to match whether there was a U suffix
@@ -177,7 +183,7 @@
// large that it is unsigned" e.g. on 12345678901234567890 where intmax_t
// is 64-bits.
if (!Literal.isUnsigned && Result.isNegative()) {
- PP.Diag(PeekTok, diag::warn_integer_too_large_for_signed);
+ if (ValueLive)PP.Diag(PeekTok, diag::warn_integer_too_large_for_signed);
Result.setIsUnsigned(true);
}
}
@@ -231,14 +237,15 @@
PP.LexNonComment(PeekTok); // Eat the (.
// Parse the value and if there are any binary operators involved, parse
// them.
- if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
// If this is a silly value like (X), which doesn't need parens, check for
// !(defined X).
if (PeekTok.getKind() == tok::r_paren) {
// Just use DT unmodified as our result.
} else {
- if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, PP)) return true;
+ if (EvaluateDirectiveSubExpr(Result, 1, PeekTok, ValueLive, PP))
+ return true;
if (PeekTok.getKind() != tok::r_paren) {
PP.Diag(PeekTok, diag::err_pp_expected_rparen);
@@ -252,10 +259,10 @@
case tok::plus:
// Unary plus doesn't modify the value.
PP.LexNonComment(PeekTok);
- return EvaluateValue(Result, PeekTok, DT, PP);
+ return EvaluateValue(Result, PeekTok, DT, ValueLive, PP);
case tok::minus:
PP.LexNonComment(PeekTok);
- if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
// C99 6.5.3.3p3: The sign of the result matches the sign of the operand.
Result = -Result;
DT.State = DefinedTracker::Unknown;
@@ -263,7 +270,7 @@
case tok::tilde:
PP.LexNonComment(PeekTok);
- if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
// C99 6.5.3.3p4: The sign of the result matches the sign of the operand.
Result = ~Result;
DT.State = DefinedTracker::Unknown;
@@ -271,7 +278,7 @@
case tok::exclaim:
PP.LexNonComment(PeekTok);
- if (EvaluateValue(Result, PeekTok, DT, PP)) return true;
+ if (EvaluateValue(Result, PeekTok, DT, ValueLive, PP)) return true;
Result = !Result;
// C99 6.5.3.3p5: The sign of the result is 'int', aka it is signed.
Result.setIsUnsigned(false);
@@ -336,8 +343,13 @@
/// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is
/// PeekTok, and whose precedence is PeekPrec.
+///
+/// If ValueLive is false, then this value is being evaluated in a context where
+/// the result is not used. As such, avoid diagnostics that relate to
+/// evaluation.
static bool EvaluateDirectiveSubExpr(APSInt &LHS, unsigned MinPrec,
- LexerToken &PeekTok, Preprocessor &PP) {
+ LexerToken &PeekTok, bool ValueLive,
+ Preprocessor &PP) {
unsigned PeekPrec = getPrecedence(PeekTok.getKind());
// If this token isn't valid, report the error.
if (PeekPrec == ~0U) {
@@ -352,6 +364,21 @@
return false;
tok::TokenKind Operator = PeekTok.getKind();
+
+ // If this is a short-circuiting operator, see if the RHS of the operator is
+ // dead. Note that this cannot just clobber ValueLive. Consider
+ // "0 && 1 ? 4 : 1 / 0", which is parsed as "(0 && 1) ? 4 : (1 / 0)". In
+ // this example, the RHS of the && being dead does not make the rest of the
+ // expr dead.
+ bool RHSIsLive;
+ if (Operator == tok::ampamp && LHS == 0)
+ RHSIsLive = false; // RHS of "0 && x" is dead.
+ else if (Operator == tok::pipepipe && LHS != 0)
+ RHSIsLive = false; // RHS of "1 || x" is dead.
+ else if (Operator == tok::question && LHS == 0)
+ RHSIsLive = false; // RHS (x) of "0 ? x : y" is dead.
+ else
+ RHSIsLive = ValueLive;
// Consume the operator, saving the operator token for error reporting.
LexerToken OpToken = PeekTok;
@@ -360,7 +387,7 @@
APSInt RHS(LHS.getBitWidth());
// Parse the RHS of the operator.
DefinedTracker DT;
- if (EvaluateValue(RHS, PeekTok, DT, PP)) return true;
+ if (EvaluateValue(RHS, PeekTok, DT, RHSIsLive, PP)) return true;
// Remember the precedence of this operator and get the precedence of the
// operator immediately to the right of the RHS.
@@ -379,7 +406,7 @@
// more tightly with RHS than we do, evaluate it completely first.
if (ThisPrec < PeekPrec ||
(ThisPrec == PeekPrec && isRightAssoc)) {
- if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok, PP))
+ if (EvaluateDirectiveSubExpr(RHS, ThisPrec+1, PeekTok, RHSIsLive, PP))
return true;
PeekPrec = getPrecedence(PeekTok.getKind());
}
@@ -397,14 +424,14 @@
default: assert(0 && "Unknown operator token!");
case tok::percent:
if (RHS == 0) {
- PP.Diag(OpToken, diag::err_pp_remainder_by_zero);
+ if (ValueLive) PP.Diag(OpToken, diag::err_pp_remainder_by_zero);
return true;
}
LHS %= RHS;
break;
case tok::slash:
if (RHS == 0) {
- PP.Diag(OpToken, diag::err_pp_division_by_zero);
+ if (ValueLive) PP.Diag(OpToken, diag::err_pp_division_by_zero);
return true;
}
LHS /= RHS;
@@ -477,13 +504,15 @@
PP.LexNonComment(PeekTok);
// Evaluate the value after the :.
+ bool AfterColonLive = ValueLive && LHS == 0;
APSInt AfterColonVal(LHS.getBitWidth());
DefinedTracker DT;
- if (EvaluateValue(AfterColonVal, PeekTok, DT, PP)) return true;
+ if (EvaluateValue(AfterColonVal, PeekTok, DT, AfterColonLive, PP))
+ return true;
// Parse anything after the : RHS that has a higher precedence than ?.
if (EvaluateDirectiveSubExpr(AfterColonVal, ThisPrec+1,
- PeekTok, PP))
+ PeekTok, AfterColonLive, PP))
return true;
// Now that we have the condition, the LHS and the RHS of the :, evaluate.
@@ -520,7 +549,7 @@
unsigned BitWidth = getTargetInfo().getIntMaxTWidth(Tok.getLocation());
APSInt ResVal(BitWidth);
DefinedTracker DT;
- if (EvaluateValue(ResVal, Tok, DT, *this)) {
+ if (EvaluateValue(ResVal, Tok, DT, true, *this)) {
// Parse error, skip the rest of the macro line.
if (Tok.getKind() != tok::eom)
DiscardUntilEndOfDirective();
@@ -541,7 +570,7 @@
// Otherwise, we must have a binary operator (e.g. "#if 1 < 2"), so parse the
// operator and the stuff after it.
- if (EvaluateDirectiveSubExpr(ResVal, 1, Tok, *this)) {
+ if (EvaluateDirectiveSubExpr(ResVal, 1, Tok, true, *this)) {
// Parse error, skip the rest of the macro line.
if (Tok.getKind() != tok::eom)
DiscardUntilEndOfDirective();
Modified: cfe/cfe/trunk/clang.xcodeproj/project.pbxproj
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/clang.xcodeproj/project.pbxproj?rev=39397&r1=39396&r2=39397&view=diff
==============================================================================
--- cfe/cfe/trunk/clang.xcodeproj/project.pbxproj (original)
+++ cfe/cfe/trunk/clang.xcodeproj/project.pbxproj Wed Jul 11 11:43:56 2007
@@ -483,12 +483,10 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
projectRoot = "";
- shouldCheckCompatibility = 1;
targets = (
8DD76F620486A84900D96B5E /* clang */,
);
More information about the cfe-commits
mailing list