[cfe-commits] r89717 - in /cfe/trunk: include/clang/AST/Stmt.h lib/CodeGen/CGStmt.cpp lib/Frontend/PCHReaderStmt.cpp lib/Frontend/PCHWriterStmt.cpp lib/Sema/Sema.h lib/Sema/SemaExprCXX.cpp lib/Sema/SemaStmt.cpp lib/Sema/TreeTransform.h

Douglas Gregor dgregor at apple.com
Mon Nov 23 15:44:05 PST 2009


Author: dgregor
Date: Mon Nov 23 17:44:04 2009
New Revision: 89717

URL: http://llvm.org/viewvc/llvm-project?rev=89717&view=rev
Log:
Explicitly track the condition variable within an "if" statement,
rather than burying it in a CXXConditionDeclExpr (that occassionally
hides behind implicit conversions). Similar changes for
switch, while, and do-while will follow, then the removal of
CXXConditionDeclExpr. This commit is the canary.

Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/Frontend/PCHReaderStmt.cpp
    cfe/trunk/lib/Frontend/PCHWriterStmt.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/TreeTransform.h

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Mon Nov 23 17:44:04 2009
@@ -604,22 +604,36 @@
 class IfStmt : public Stmt {
   enum { COND, THEN, ELSE, END_EXPR };
   Stmt* SubExprs[END_EXPR];
+
+  /// \brief If non-NULL, the declaration in the "if" statement.
+  VarDecl *Var;
+  
   SourceLocation IfLoc;
   SourceLocation ElseLoc;
+  
 public:
-  IfStmt(SourceLocation IL, Expr *cond, Stmt *then,
+  IfStmt(SourceLocation IL, VarDecl *Var, Expr *cond, Stmt *then,
          SourceLocation EL = SourceLocation(), Stmt *elsev = 0)
-    : Stmt(IfStmtClass)  {
+    : Stmt(IfStmtClass), Var(Var), IfLoc(IL), ElseLoc(EL)  {
     SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
     SubExprs[THEN] = then;
     SubExprs[ELSE] = elsev;
-    IfLoc = IL;
-    ElseLoc = EL;
   }
 
   /// \brief Build an empty if/then/else statement
   explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { }
 
+  /// \brief Retrieve the variable declared in this "if" statement, if any.
+  ///
+  /// In the following example, "x" is the condition variable.
+  /// \code
+  /// if (int x = foo()) {
+  ///   printf("x is %d", x);
+  /// }
+  /// \endcode
+  VarDecl *getConditionVariable() const { return Var; }
+  void setConditionVariable(VarDecl *V) { Var = V; }
+  
   const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);}
   void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); }
   const Stmt *getThen() const { return SubExprs[THEN]; }

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Mon Nov 23 17:44:04 2009
@@ -294,6 +294,8 @@
 void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
   // C99 6.8.4.1: The first substatement is executed if the expression compares
   // unequal to 0.  The condition must be a scalar type.
+  if (S.getConditionVariable())
+    EmitDecl(*S.getConditionVariable());
 
   // If the condition constant folds and can be elided, try to avoid emitting
   // the condition and the dead arm of the if/else.

Modified: cfe/trunk/lib/Frontend/PCHReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderStmt.cpp?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderStmt.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderStmt.cpp Mon Nov 23 17:44:04 2009
@@ -177,6 +177,7 @@
 
 unsigned PCHStmtReader::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
+  S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
   S->setCond(cast<Expr>(StmtStack[StmtStack.size() - 3]));
   S->setThen(StmtStack[StmtStack.size() - 2]);
   S->setElse(StmtStack[StmtStack.size() - 1]);

Modified: cfe/trunk/lib/Frontend/PCHWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterStmt.cpp?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterStmt.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterStmt.cpp Mon Nov 23 17:44:04 2009
@@ -170,6 +170,7 @@
 
 void PCHStmtWriter::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
+  Writer.AddDeclRef(S->getConditionVariable(), Record);
   Writer.WriteSubStmt(S->getCond());
   Writer.WriteSubStmt(S->getThen());
   Writer.WriteSubStmt(S->getElse());

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Nov 23 17:44:04 2009
@@ -1879,7 +1879,8 @@
                                                       Declarator &D,
                                                       SourceLocation EqualLoc,
                                                       ExprArg AssignExprVal);
-
+  OwningExprResult CheckConditionVariable(VarDecl *ConditionVar);
+                                          
   /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
   /// pseudo-functions.
   virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Nov 23 17:44:04 2009
@@ -1002,6 +1002,27 @@
   return Owned(new (Context) CXXConditionDeclExpr(StartLoc, EqualLoc, VD));
 }
 
+/// \brief Check the use of the given variable as a C++ condition in an if,
+/// while, do-while, or switch statement.
+Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar) {
+  QualType T = ConditionVar->getType();
+  
+  // C++ [stmt.select]p2:
+  //   The declarator shall not specify a function or an array.
+  if (T->isFunctionType())
+    return ExprError(Diag(ConditionVar->getLocation(), 
+                          diag::err_invalid_use_of_function_type)
+                       << ConditionVar->getSourceRange());
+  else if (T->isArrayType())
+    return ExprError(Diag(ConditionVar->getLocation(), 
+                          diag::err_invalid_use_of_array_type)
+                     << ConditionVar->getSourceRange());
+  
+  return Owned(DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
+                                   ConditionVar->getLocation(), 
+                                ConditionVar->getType().getNonReferenceType()));
+}
+
 /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
 bool Sema::CheckCXXBooleanCondition(Expr *&CondExpr) {
   // C++ 6.4p4:

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Nov 23 17:44:04 2009
@@ -242,8 +242,17 @@
   OwningExprResult CondResult(CondVal.release());
 
   Expr *condExpr = CondResult.takeAs<Expr>();
-
   assert(condExpr && "ActOnIfStmt(): missing expression");
+  
+  VarDecl *ConditionVar = 0;
+  if (CXXConditionDeclExpr *Cond = dyn_cast<CXXConditionDeclExpr>(condExpr)) {
+    ConditionVar = Cond->getVarDecl();
+    condExpr = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
+                                   ConditionVar->getLocation(), 
+                                 ConditionVar->getType().getNonReferenceType());
+    // FIXME: Leaks the old condExpr
+  }
+  
   if (CheckBooleanCondition(condExpr, IfLoc)) {
     CondResult = condExpr;
     return StmtError();
@@ -265,7 +274,7 @@
   DiagnoseUnusedExprResult(elseStmt);
 
   CondResult.release();
-  return Owned(new (Context) IfStmt(IfLoc, condExpr, thenStmt,
+  return Owned(new (Context) IfStmt(IfLoc, ConditionVar, condExpr, thenStmt,
                                     ElseLoc, elseStmt));
 }
 

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=89717&r1=89716&r2=89717&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Mon Nov 23 17:44:04 2009
@@ -3084,10 +3084,22 @@
 Sema::OwningStmtResult
 TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
   // Transform the condition
-  OwningExprResult Cond = getDerived().TransformExpr(S->getCond());
+  OwningExprResult Cond(SemaRef);
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(S->getConditionVariable()));
+    if (!ConditionVar)
+      return SemaRef.StmtError();
+    
+    Cond = getSema().CheckConditionVariable(ConditionVar);
+  } else
+    Cond = getDerived().TransformExpr(S->getCond());
+  
   if (Cond.isInvalid())
     return SemaRef.StmtError();
-
+  
   Sema::FullExprArg FullCond(getSema().FullExpr(Cond));
 
   // Transform the "then" branch.





More information about the cfe-commits mailing list