[cfe-commits] r39509 - in /cfe/cfe/trunk: AST/StmtPrinter.cpp Sema/Sema.h Sema/SemaDecl.cpp Sema/SemaStmt.cpp include/clang/AST/Stmt.h include/clang/Basic/DiagnosticKinds.def

clattner at cs.uiuc.edu clattner at cs.uiuc.edu
Wed Jul 11 09:45:07 PDT 2007


Author: clattner
Date: Wed Jul 11 11:45:07 2007
New Revision: 39509

URL: http://llvm.org/viewvc/llvm-project?rev=39509&view=rev
Log:
Change GotoStmt's to have a pointer to the LabelStmt instead of a pointer to
the label identifier.  Handle fwd references etc.  This allows us to detect
uses of undefined labels and label redefinitions, such as:

t.c:2:12: error: redefinition of label 'abc'
  abc: ;   abc:
           ^
t.c:2:3: error: previous definition is here
  abc: ;   abc:
  ^
t.c:12:12: error: use of undeclared label 'hijl'
      goto hijl;
           ^

Modified:
    cfe/cfe/trunk/AST/StmtPrinter.cpp
    cfe/cfe/trunk/Sema/Sema.h
    cfe/cfe/trunk/Sema/SemaDecl.cpp
    cfe/cfe/trunk/Sema/SemaStmt.cpp
    cfe/cfe/trunk/include/clang/AST/Stmt.h
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/cfe/trunk/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/StmtPrinter.cpp?rev=39509&r1=39508&r2=39509&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/StmtPrinter.cpp (original)
+++ cfe/cfe/trunk/AST/StmtPrinter.cpp Wed Jul 11 11:45:07 2007
@@ -211,7 +211,7 @@
 }
 
 void StmtPrinter::VisitGotoStmt(GotoStmt *Node) {
-  Indent() << "goto " << Node->getLabel()->getName() << "\n";
+  Indent() << "goto " << Node->getLabel()->getLabel()->getName() << ";\n";
 }
 
 void StmtPrinter::VisitIndirectGotoStmt(IndirectGotoStmt *Node) {

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

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:45:07 2007
@@ -16,6 +16,7 @@
 #define LLVM_CLANG_AST_SEMA_H
 
 #include "clang/Parse/Action.h"
+#include "llvm/ADT/DenseMap.h"
 #include <vector>
 #include <string>
 
@@ -34,6 +35,7 @@
   class LexerToken;
   class IntegerLiteral;
   class ArrayType;
+  class LabelStmt;
   
 /// Sema - This implements semantic analysis and AST building for C.
 class Sema : public Action {
@@ -50,6 +52,11 @@
   /// all but the last decl will be entered into this.  This is used by the
   /// ASTStreamer.
   std::vector<Decl*> &LastInGroupList;
+  
+  /// LabelMap - This is a mapping from label identifiers to the LabelStmt for
+  /// it (which acts like the label decl in some ways).  Forward referenced
+  /// labels have a LabelStmt created for them with a null location & SubStmt.
+  DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
 public:
   Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup);
   

Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39509&r1=39508&r2=39509&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:45:07 2007
@@ -472,6 +472,30 @@
   
   assert(FD == CurFunctionDecl && "Function parsing confused");
   CurFunctionDecl = 0;
+  
+  // Verify and clean out per-function state.
+  
+  // Check goto/label use.
+  for (DenseMap<IdentifierInfo*, LabelStmt*>::iterator I = LabelMap.begin(),
+       E = LabelMap.end(); I != E; ++I) {
+    // Verify that we have no forward references left.  If so, there was a goto
+    // or address of a label taken, but no definition of it.  Label fwd
+    // definitions are indicated with a null substmt.
+    if (I->second->getSubStmt() == 0) {
+      LabelStmt *L = I->second;
+      // Emit error.
+      Diag(L->getIdentLoc(), diag::err_undeclared_label_use,
+           L->getLabel()->getName());
+      
+      // At this point, we have gotos that use the bogus label.  Stitch it into
+      // the function body so that they aren't leaked and that the AST is well
+      // formed.
+      L->setSubStmt(new NullStmt(L->getIdentLoc()));
+      cast<CompoundStmt>((Stmt*)Body)->push_back(L);
+    }
+  }
+  LabelMap.clear();
+  
   return FD;
 }
 

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

==============================================================================
--- cfe/cfe/trunk/Sema/SemaStmt.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaStmt.cpp Wed Jul 11 11:45:07 2007
@@ -15,6 +15,7 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/Expr.h"
 #include "clang/Parse/Scope.h"
+#include "clang/Lex/IdentifierTable.h"
 #include "clang/Basic/Diagnostic.h"
 using namespace llvm;
 using namespace clang;
@@ -53,7 +54,28 @@
 Action::StmtResult
 Sema::ParseLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
                      SourceLocation ColonLoc, StmtTy *SubStmt) {
-  return new LabelStmt(II, (Stmt*)SubStmt);
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = LabelMap[II];
+  
+  // If not forward referenced or defined already, just create a new LabelStmt.
+  if (LabelDecl == 0)
+    return LabelDecl = new LabelStmt(IdentLoc, II, (Stmt*)SubStmt);
+  
+  assert(LabelDecl->getLabel() == II && "Label mismatch!");
+  
+  // Otherwise, this label was either forward reference or multiply defined.  If
+  // multiply defined, reject it now.
+  if (LabelDecl->getSubStmt()) {
+    Diag(IdentLoc, diag::err_redefinition_of_label, II->getName());
+    Diag(LabelDecl->getIdentLoc(), diag::err_previous_definition);
+    return (Stmt*)SubStmt;
+  }
+  
+  // Otherwise, this label was forward declared, and we just found its real
+  // definition.  Fill in the forward definition and return it.
+  LabelDecl->setIdentLoc(IdentLoc);
+  LabelDecl->setSubStmt((Stmt*)SubStmt);
+  return LabelDecl;
 }
 
 Action::StmtResult 
@@ -89,7 +111,14 @@
 Action::StmtResult 
 Sema::ParseGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
                     IdentifierInfo *LabelII) {
-  return new GotoStmt(LabelII);
+  // Look up the record for this label identifier.
+  LabelStmt *&LabelDecl = LabelMap[LabelII];
+
+  // If we haven't seen this label yet, create a forward reference.
+  if (LabelDecl == 0)
+    LabelDecl = new LabelStmt(LabelLoc, LabelII, 0);
+  
+  return new GotoStmt(LabelDecl);
 }
 Action::StmtResult 
 Sema::ParseIndirectGotoStmt(SourceLocation GotoLoc,SourceLocation StarLoc,

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

==============================================================================
--- cfe/cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/cfe/trunk/include/clang/AST/Stmt.h Wed Jul 11 11:45:07 2007
@@ -90,6 +90,8 @@
   body_iterator body_begin() { return Body.begin(); }
   body_iterator body_end() { return Body.end(); }
   
+  void push_back(Stmt *S) { Body.push_back(S); }
+    
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == CompoundStmtClass; 
@@ -131,15 +133,20 @@
 };
 
 class LabelStmt : public Stmt {
+  SourceLocation IdentLoc;
   IdentifierInfo *Label;
   Stmt *SubStmt;
 public:
-  LabelStmt(IdentifierInfo *label, Stmt *substmt)
-    : Stmt(LabelStmtClass), Label(label), SubStmt(substmt) {}
+  LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt)
+    : Stmt(LabelStmtClass), IdentLoc(IL), Label(label), SubStmt(substmt) {}
   
+  SourceLocation getIdentLoc() const { return IdentLoc; }
   IdentifierInfo *getLabel() { return Label; }
   Stmt *getSubStmt() { return SubStmt; }
 
+  void setIdentLoc(SourceLocation L) { IdentLoc = L; }
+  void setSubStmt(Stmt *SS) { SubStmt = SS; }
+  
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 
     return T->getStmtClass() == LabelStmtClass; 
@@ -257,11 +264,11 @@
 /// GotoStmt - This represents a direct goto.
 ///
 class GotoStmt : public Stmt {
-  IdentifierInfo *Label;
+  LabelStmt *Label;
 public:
-  GotoStmt(IdentifierInfo *label) : Stmt(GotoStmtClass), Label(label) {}
+  GotoStmt(LabelStmt *label) : Stmt(GotoStmtClass), Label(label) {}
   
-  IdentifierInfo *getLabel() { return Label; }
+  LabelStmt *getLabel() { return Label; }
   
   virtual void visit(StmtVisitor &Visitor);
   static bool classof(const Stmt *T) { 

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39509&r1=39508&r2=39509&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:45:07 2007
@@ -470,6 +470,11 @@
 DIAG(err_array_size_non_int, ERROR,
      "size of array has non-integer type '%0'")
 
+DIAG(err_redefinition_of_label, ERROR,
+     "redefinition of label '%0'")
+DIAG(err_undeclared_label_use, ERROR,
+     "use of undeclared label '%0'")
+
 DIAG(warn_implicit_function_decl, WARNING,
      "implicit declaration of function '%0'")
 DIAG(ext_implicit_function_decl, EXTENSION,





More information about the cfe-commits mailing list