]> granicus.if.org Git - clang/commitdiff
Step #1/N of implementing support for __label__: split labels into
authorChris Lattner <sabre@nondot.org>
Thu, 17 Feb 2011 07:39:24 +0000 (07:39 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 17 Feb 2011 07:39:24 +0000 (07:39 +0000)
LabelDecl and LabelStmt.  There is a 1-1 correspondence between the
two, but this simplifies a bunch of code by itself.  This is because
labels are the only place where we previously had references to random
other statements, causing grief for AST serialization and other stuff.

This does cause one regression (attr(unused) doesn't silence unused
label warnings) which I'll address next.

This does fix some minor bugs:
1. "The only valid attribute " diagnostic was capitalized.
2. Various diagnostics printed as ''labelname'' instead of 'labelname'
3. This reduces duplication of label checking between functions and blocks.

Review appreciated, particularly for the cindex and template bits.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125733 91177308-0d34-0410-b5e6-96231b3b80d8

39 files changed:
include/clang/AST/Decl.h
include/clang/AST/DeclBase.h
include/clang/AST/Expr.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/AST/Stmt.h
include/clang/Basic/DeclNodes.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/ScopeInfo.h
include/clang/Serialization/ASTBitCodes.h
include/clang/Serialization/ASTReader.h
include/clang/Serialization/ASTWriter.h
include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
lib/AST/Decl.cpp
lib/AST/DeclBase.cpp
lib/AST/Stmt.cpp
lib/AST/StmtProfile.cpp
lib/Analysis/CFG.cpp
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CGStmt.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/Sema/JumpDiagnostics.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/TreeTransform.h
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTReaderStmt.cpp
lib/Serialization/ASTWriterDecl.cpp
lib/Serialization/ASTWriterStmt.cpp
lib/StaticAnalyzer/Checkers/ExprEngine.cpp
lib/StaticAnalyzer/Core/SVals.cpp
test/CXX/stmt.stmt/stmt.label/p1.cpp
test/Sema/warn-unused-label.c
tools/libclang/CIndex.cpp

index cba71ae8cd69cb1a2ef338020d24fcd862e4484e..e0ffa627ac211d48dd3fa333072ed931f044700a 100644 (file)
@@ -36,6 +36,7 @@ class FunctionTemplateSpecializationInfo;
 class DependentFunctionTemplateSpecializationInfo;
 class TypeLoc;
 class UnresolvedSetImpl;
+class LabelStmt;
 
 /// \brief A container of type source information.
 ///
@@ -294,6 +295,36 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
   return OS;
 }
 
+/// LabelDecl - Represents the declaration of a label.  Labels also have a
+/// corresponding LabelStmt, which indicates the position that the label was
+/// defined at.  For normal labels, the location of the decl is the same as the
+/// location of the statement.  For GNU local labels (__label__), the decl
+/// location is where the __label__ is.
+class LabelDecl : public NamedDecl {
+  /// HasUnusedAttr - True if the label has __attribute__((unused)) on it.
+  /// FIXME: Just use attributes!
+  unsigned HasUnusedAttr : 1;
+
+  LabelStmt *TheStmt;
+  LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S)
+    : NamedDecl(Label, DC, L, II), TheStmt(S) {}
+  
+public:
+  static LabelDecl *Create(ASTContext &C, DeclContext *DC,
+                           SourceLocation L, IdentifierInfo *II);
+
+  LabelStmt *getStmt() const { return TheStmt; }
+  void setStmt(LabelStmt *T) { TheStmt = T; }
+  
+  bool hasUnusedAttribute() const { return HasUnusedAttr; }
+  void setHasUnusedAttribute() { HasUnusedAttr = true; }
+  
+  // Implement isa/cast/dyncast/etc.
+  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+  static bool classof(const LabelDecl *D) { return true; }
+  static bool classofKind(Kind K) { return K == Label; }
+};
+  
 /// NamespaceDecl - Represent a C++ namespace.
 class NamespaceDecl : public NamedDecl, public DeclContext {
   bool IsInline : 1;
index 3e92c4e65115d6dc2999edec3bc4391a26ea42f0..1407dadd16cfdb984de2e097e73e0dc4c2261f2e 100644 (file)
@@ -324,7 +324,7 @@ public:
 
   bool hasAttrs() const { return HasAttrs; }
   void setAttrs(const AttrVec& Attrs);
-  AttrVecgetAttrs() {
+  AttrVec &getAttrs() {
     return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
   }
   const AttrVec &getAttrs() const;
index c09394d9c0432336225fefbe4e4b9095612769cf..b5724a64754ba47332caa4cd59f80c409a304ddf 100644 (file)
@@ -2641,9 +2641,9 @@ public:
 /// AddrLabelExpr - The GNU address of label extension, representing &&label.
 class AddrLabelExpr : public Expr {
   SourceLocation AmpAmpLoc, LabelLoc;
-  LabelStmt *Label;
+  LabelDecl *Label;
 public:
-  AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelStmt *L,
+  AddrLabelExpr(SourceLocation AALoc, SourceLocation LLoc, LabelDecl *L,
                 QualType t)
     : Expr(AddrLabelExprClass, t, VK_RValue, OK_Ordinary, false, false, false),
       AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {}
@@ -2661,8 +2661,8 @@ public:
     return SourceRange(AmpAmpLoc, LabelLoc);
   }
 
-  LabelStmt *getLabel() const { return Label; }
-  void setLabel(LabelStmt *S) { Label = S; }
+  LabelDecl *getLabel() const { return Label; }
+  void setLabel(LabelDecl *L) { Label = L; }
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == AddrLabelExprClass;
index 8ddd5875ce4cd58324f086bb2defd67b733e9333..667b8408892f06872e06245b20b9eda4d2e41370 100644 (file)
@@ -1088,6 +1088,11 @@ DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
     return true;
   })
 
+DEF_TRAVERSE_DECL(LabelDecl, {
+  // There is no code in a LabelDecl.
+})
+  
+  
 DEF_TRAVERSE_DECL(NamespaceDecl, {
     // Code in an unnamed namespace shows up automatically in
     // decls_begin()/decls_end().  Thus we don't need to recurse on
index 1254926facde4ab9acc5baa47b5e382eb9ddf159..7ede9ce323f4ecc7e249525a1ca3bfcc03dbdf7a 100644 (file)
@@ -130,14 +130,6 @@ protected:
     unsigned NumStmts : 32 - NumStmtBits;
   };
 
-  class LabelStmtBitfields {
-    friend class LabelStmt;
-    unsigned : NumStmtBits;
-
-    unsigned Used : 1;
-    unsigned HasUnusedAttr : 1;
-  };
-
   class ExprBitfields {
     friend class Expr;
     friend class DeclRefExpr; // computeDependence
@@ -187,7 +179,6 @@ protected:
 
     StmtBitfields StmtBits;
     CompoundStmtBitfields CompoundStmtBits;
-    LabelStmtBitfields LabelStmtBits;
     ExprBitfields ExprBits;
     CastExprBitfields CastExprBits;
     CallExprBitfields CallExprBits;
@@ -633,40 +624,31 @@ public:
   child_range children() { return child_range(&SubStmt, &SubStmt+1); }
 };
 
+  
+/// LabelStmt - Represents a label, which has a substatement.  For example:
+///    foo: return;
+///
 class LabelStmt : public Stmt {
-  IdentifierInfo *Label;
+  LabelDecl *TheDecl;
   Stmt *SubStmt;
   SourceLocation IdentLoc;
 public:
-  LabelStmt(SourceLocation IL, IdentifierInfo *label, Stmt *substmt,
-            bool hasUnusedAttr = false)
-    : Stmt(LabelStmtClass), Label(label), SubStmt(substmt), IdentLoc(IL) {
-    LabelStmtBits.Used = false;
-    LabelStmtBits.HasUnusedAttr = hasUnusedAttr;
+  LabelStmt(SourceLocation IL, LabelDecl *D, Stmt *substmt)
+    : Stmt(LabelStmtClass), TheDecl(D), SubStmt(substmt), IdentLoc(IL) {
   }
 
   // \brief Build an empty label statement.
   explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) { }
 
   SourceLocation getIdentLoc() const { return IdentLoc; }
-  IdentifierInfo *getID() const { return Label; }
-  void setID(IdentifierInfo *II) { Label = II; }
+  LabelDecl *getDecl() const { return TheDecl; }
+  void setDecl(LabelDecl *D) { TheDecl = D; }
   const char *getName() const;
   Stmt *getSubStmt() { return SubStmt; }
   const Stmt *getSubStmt() const { return SubStmt; }
   void setIdentLoc(SourceLocation L) { IdentLoc = L; }
   void setSubStmt(Stmt *SS) { SubStmt = SS; }
 
-  /// \brief Whether this label was used.
-  bool isUsed(bool CheckUnusedAttr = true) const {
-    return LabelStmtBits.Used ||
-           (CheckUnusedAttr && LabelStmtBits.HasUnusedAttr);
-  }
-  void setUsed(bool U = true) { LabelStmtBits.Used = U; }
-
-  bool HasUnusedAttribute() const { return LabelStmtBits.HasUnusedAttr; }
-  void setUnusedAttribute(bool U) { LabelStmtBits.HasUnusedAttr = U; }
-
   SourceRange getSourceRange() const {
     return SourceRange(IdentLoc, SubStmt->getLocEnd());
   }
@@ -995,18 +977,18 @@ public:
 /// GotoStmt - This represents a direct goto.
 ///
 class GotoStmt : public Stmt {
-  LabelStmt *Label;
+  LabelDecl *Label;
   SourceLocation GotoLoc;
   SourceLocation LabelLoc;
 public:
-  GotoStmt(LabelStmt *label, SourceLocation GL, SourceLocation LL)
+  GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL)
     : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {}
 
   /// \brief Build an empty goto statement.
   explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) { }
 
-  LabelStmt *getLabel() const { return Label; }
-  void setLabel(LabelStmt *S) { Label = S; }
+  LabelDecl *getLabel() const { return Label; }
+  void setLabel(LabelDecl *D) { Label = D; }
 
   SourceLocation getGotoLoc() const { return GotoLoc; }
   void setGotoLoc(SourceLocation L) { GotoLoc = L; }
@@ -1052,8 +1034,8 @@ public:
 
   /// getConstantTarget - Returns the fixed target of this indirect
   /// goto, if one exists.
-  LabelStmt *getConstantTarget();
-  const LabelStmt *getConstantTarget() const {
+  LabelDecl *getConstantTarget();
+  const LabelDecl *getConstantTarget() const {
     return const_cast<IndirectGotoStmt*>(this)->getConstantTarget();
   }
 
index f6c31f4877dd338da242508eb18ce56ed690cdc9..2ec7427cf75807677ffa0b8c81509b4b03da32fc 100644 (file)
@@ -15,6 +15,7 @@ def Named : Decl<1>;
   def Namespace : DDecl<Named>, DeclContext;
   def UsingDirective : DDecl<Named>;
   def NamespaceAlias : DDecl<Named>;
+  def Label : DDecl<Named>;
   def Type : DDecl<Named, 1>;
     def Typedef : DDecl<Type>;
     def UnresolvedUsingTypename : DDecl<Type>;
index eb8bf590c3416dbd1fd7ff60d61e221f0da3f800..b815426f6c49054a61a126431fe004e61e469f24 100644 (file)
@@ -1095,7 +1095,7 @@ def err_regparm_mismatch : Error<"function declared with with regparm(%0) "
   "attribute was previously declared "
   "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">;
 def warn_label_attribute_not_unused : Warning<
-  "The only valid attribute for labels is 'unused'">;
+  "the only valid attribute for labels is 'unused'">;
 
 def warn_impcast_vector_scalar : Warning<
   "implicit conversion turns vector to scalar: %0 to %1">,
@@ -2157,9 +2157,9 @@ def warn_missing_braces : Warning<
   "suggest braces around initialization of subobject">,
   InGroup<DiagGroup<"missing-braces">>, DefaultIgnore;
 
-def err_redefinition_of_label : Error<"redefinition of label '%0'">;
-def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
-def warn_unused_label : Warning<"unused label '%0'">,
+def err_redefinition_of_label : Error<"redefinition of label %0">;
+def err_undeclared_label_use : Error<"use of undeclared label %0">;
+def warn_unused_label : Warning<"unused label %0">,
   InGroup<UnusedLabel>, DefaultIgnore;
 
 def err_goto_into_protected_scope : Error<"goto into protected scope">;
index edd1432d8e77e11f261ffef1cbeb4dfd4775cb3a..c9d38715ec82645e7c155c05ededdc140b97c836 100644 (file)
@@ -23,7 +23,7 @@ namespace clang {
 
 class BlockDecl;
 class IdentifierInfo;
-class LabelStmt;
+class LabelDecl;
 class ReturnStmt;
 class Scope;
 class SwitchStmt;
@@ -52,10 +52,10 @@ public:
   /// \brief Used to determine if errors occurred in this function or block.
   DiagnosticErrorTrap ErrorTrap;
 
-  /// 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.
-  llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
+  /// LabelMap - This is a mapping from label identifiers to the LabelDecl for
+  /// it.  Forward referenced labels have a LabelDecl created for them with a
+  /// null statement.
+  llvm::DenseMap<IdentifierInfo*, LabelDecl*> LabelMap;
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
@@ -92,6 +92,11 @@ public:
 
   virtual ~FunctionScopeInfo();
 
+  /// checkLabelUse - This checks to see if any labels are used without being
+  /// defined, emiting errors and returning true if any are found.  This also
+  /// warns about unused labels.
+  bool checkLabelUse(Stmt *Body, Sema &S);
+  
   /// \brief Clear out the information in this function scope, making it
   /// suitable for reuse.
   void Clear();
index 391438248e5268fe73af87ff5fa96b80f31aa805..d1998c29a3a5114330ddbb93fd2f973f2288fc26 100644 (file)
@@ -697,7 +697,9 @@ namespace clang {
       /// IDs. This data is used when performing qualified name lookup
       /// into a DeclContext via DeclContext::lookup.
       DECL_CONTEXT_VISIBLE,
-      /// \brief A NamespaceDecl rcord.
+      /// \brief A LabelDecl record.
+      DECL_LABEL,
+      /// \brief A NamespaceDecl record.
       DECL_NAMESPACE,
       /// \brief A NamespaceAliasDecl record.
       DECL_NAMESPACE_ALIAS,
index 94bfd16353086f499b585a07ab276dacebb5d3dc..002f6be41021c56811d89d2f349f51e184b36e84 100644 (file)
@@ -56,7 +56,6 @@ class NestedNameSpecifier;
 class CXXBaseSpecifier;
 class CXXCtorInitializer;
 class GotoStmt;
-class LabelStmt;
 class MacroDefinition;
 class NamedDecl;
 class Preprocessor;
@@ -646,22 +645,6 @@ private:
   /// switch statement can refer to them.
   std::map<unsigned, SwitchCase *> SwitchCaseStmts;
 
-  /// \brief Mapping from label statement IDs in the chain to label statements.
-  ///
-  /// Statements usually don't have IDs, but labeled statements need them, so
-  /// that goto statements and address-of-label expressions can refer to them.
-  std::map<unsigned, LabelStmt *> LabelStmts;
-
-  /// \brief Mapping from label IDs to the set of "goto" statements
-  /// that point to that label before the label itself has been
-  /// de-serialized.
-  std::multimap<unsigned, GotoStmt *> UnresolvedGotoStmts;
-
-  /// \brief Mapping from label IDs to the set of address label
-  /// expressions that point to that label before the label itself has
-  /// been de-serialized.
-  std::multimap<unsigned, AddrLabelExpr *> UnresolvedAddrLabelExprs;
-
   /// \brief The number of stat() calls that hit/missed the stat
   /// cache.
   unsigned NumStatHits, NumStatMisses;
@@ -1278,29 +1261,7 @@ public:
   /// \brief Retrieve the switch-case statement with the given ID.
   SwitchCase *getSwitchCaseWithID(unsigned ID);
 
-  /// \brief Record that the given label statement has been
-  /// deserialized and has the given ID.
-  void RecordLabelStmt(LabelStmt *S, unsigned ID);
-
   void ClearSwitchCaseIDs();
-
-  /// \brief Set the label of the given statement to the label
-  /// identified by ID.
-  ///
-  /// Depending on the order in which the label and other statements
-  /// referencing that label occur, this operation may complete
-  /// immediately (updating the statement) or it may queue the
-  /// statement to be back-patched later.
-  void SetLabelOf(GotoStmt *S, unsigned ID);
-
-  /// \brief Set the label of the given expression to the label
-  /// identified by ID.
-  ///
-  /// Depending on the order in which the label and other statements
-  /// referencing that label occur, this operation may complete
-  /// immediately (updating the statement) or it may queue the
-  /// statement to be back-patched later.
-  void SetLabelOf(AddrLabelExpr *S, unsigned ID);
 };
 
 /// \brief Helper class that saves the current stream position and
index f9a49973e14e885956f1f069101f87497538c01b..d5f622a3405b7d006131df640dd73a5b3e1671e4 100644 (file)
@@ -44,7 +44,6 @@ class CXXBaseSpecifier;
 class CXXCtorInitializer;
 class FPOptions;
 class HeaderSearch;
-class LabelStmt;
 class MacroDefinition;
 class MemorizeStatCalls;
 class OpenCLOptions;
@@ -261,9 +260,6 @@ private:
   /// \brief Mapping from SwitchCase statements to IDs.
   std::map<SwitchCase *, unsigned> SwitchCaseIDs;
 
-  /// \brief Mapping from LabelStmt statements to IDs.
-  std::map<LabelStmt *, unsigned> LabelIDs;
-
   /// \brief The number of statements written to the AST file.
   unsigned NumStatements;
 
@@ -553,10 +549,6 @@ public:
 
   void ClearSwitchCaseIDs();
 
-  /// \brief Retrieve the ID for the given label statement, which may
-  /// or may not have been emitted yet.
-  unsigned GetLabelID(LabelStmt *S);
-
   unsigned getParmVarDeclAbbrev() const { return ParmVarDeclAbbrev; }
 
   bool hasChain() const { return Chain; }
index d879ea13e71e3312fb5dbd51e9a6172bacdec612..800e63a4cdebbf74c26b66569994168084410f45 100644 (file)
@@ -331,11 +331,11 @@ public:
     iterator& operator++() { ++I; return *this; }
     bool operator!=(const iterator& X) const { return I != X.I; }
 
-    const LabelStmt* getLabel() const {
-      return llvm::cast<LabelStmt>((*I)->getLabel());
+    const LabelDecl *getLabel() const {
+      return llvm::cast<LabelStmt>((*I)->getLabel())->getDecl();
     }
 
-    const CFGBlock*  getBlock() const {
+    const CFGBlock *getBlock() const {
       return *I;
     }
   };
index 9c187117425b2ffb19534accd085a18f5c209735..e7b39448ac554d5054b281be1a148e2130f8cca0 100644 (file)
@@ -238,7 +238,7 @@ public:
     return loc::MemRegionVal(R);
   }
 
-  Loc makeLoc(const AddrLabelExprE) {
+  Loc makeLoc(const AddrLabelExpr *E) {
     return loc::GotoLabel(E->getLabel());
   }
 
index 1d1cd0b8f91db7a891fddec10fbc5b6dc2e367e2..0d430794e76cb4e924323ac79d435be0370c235e 100644 (file)
@@ -432,15 +432,14 @@ enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind, ObjCPropRefKind };
 
 class GotoLabel : public Loc {
 public:
-  explicit GotoLabel(LabelStmt* Label) : Loc(GotoLabelKind, Label) {}
+  explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
 
-  const LabelStmt* getLabel() const {
-    return static_cast<const LabelStmt*>(Data);
+  const LabelDecl *getLabel() const {
+    return static_cast<const LabelDecl*>(Data);
   }
 
   static inline bool classof(const SVal* V) {
-    return V->getBaseKind() == LocKind &&
-           V->getSubKind() == GotoLabelKind;
+    return V->getBaseKind() == LocKind && V->getSubKind() == GotoLabelKind;
   }
 
   static inline bool classof(const Loc* V) {
index fded8ff38c13083aca1139a0b6f1fba47b334a47..441444da9e55d1d31de555e797591fbd43ad2a21 100644 (file)
@@ -2182,6 +2182,12 @@ TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
   return new (C) TranslationUnitDecl(C);
 }
 
+LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
+                             SourceLocation L, IdentifierInfo *II) {
+  return new (C) LabelDecl(DC, L, II, 0);
+}
+
+
 NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
                                      SourceLocation L, IdentifierInfo *Id) {
   return new (C) NamespaceDecl(DC, L, Id);
index 110de64d8cdb047ad5daba2bb45294b033394c6c..dfc5a6ae5d314d4386d9e8dcc61647df9f859e4e 100644 (file)
@@ -269,7 +269,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
     case ObjCMethod:
     case ObjCProperty:
       return IDNS_Ordinary;
-
+    case Label:
+      return IDNS_Label;
     case IndirectField:
       return IDNS_Ordinary | IDNS_Member;
 
index 66182957d68850ecd6e19c42944bf2fe3cb5eb57..7e73f02e67e7d48d0239f806432767dcf5c73bf4 100644 (file)
@@ -161,7 +161,7 @@ void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
 }
 
 const char *LabelStmt::getName() const {
-  return getID()->getNameStart();
+  return getDecl()->getIdentifier()->getNameStart();
 }
 
 // This is defined here to avoid polluting Stmt.h with importing Expr.h
@@ -658,7 +658,7 @@ void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
 }
 
 // IndirectGotoStmt
-LabelStmt *IndirectGotoStmt::getConstantTarget() {
+LabelDecl *IndirectGotoStmt::getConstantTarget() {
   if (AddrLabelExpr *E =
         dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
     return E->getLabel();
index b96ffe8a48e81fda1f95fa2cc2428b1d33d6069e..2ffb807abcd2c84c0e0e3c45a5e9c17cff13f1f2 100644 (file)
@@ -101,7 +101,7 @@ void StmtProfiler::VisitDefaultStmt(DefaultStmt *S) {
 
 void StmtProfiler::VisitLabelStmt(LabelStmt *S) {
   VisitStmt(S);
-  VisitName(S->getID());
+  VisitDecl(S->getDecl());
 }
 
 void StmtProfiler::VisitIfStmt(IfStmt *S) {
@@ -129,7 +129,7 @@ void StmtProfiler::VisitForStmt(ForStmt *S) {
 
 void StmtProfiler::VisitGotoStmt(GotoStmt *S) {
   VisitStmt(S);
-  VisitName(S->getLabel()->getID());
+  VisitDecl(S->getLabel());
 }
 
 void StmtProfiler::VisitIndirectGotoStmt(IndirectGotoStmt *S) {
@@ -351,7 +351,7 @@ void StmtProfiler::VisitConditionalOperator(ConditionalOperator *S) {
 
 void StmtProfiler::VisitAddrLabelExpr(AddrLabelExpr *S) {
   VisitExpr(S);
-  VisitName(S->getLabel()->getID());
+  VisitDecl(S->getLabel());
 }
 
 void StmtProfiler::VisitStmtExpr(StmtExpr *S) {
index d46b7e7830ec51a3668240576e2a96e8c3286699..6da47844052b1207aa098a15c09bd9a31f04af35 100644 (file)
@@ -242,7 +242,7 @@ class CFGBuilder {
   LocalScope::const_iterator ScopePos;
 
   // LabelMap records the mapping from Label expressions to their jump targets.
-  typedef llvm::DenseMap<LabelStmt*, JumpTarget> LabelMapTy;
+  typedef llvm::DenseMap<LabelDecl*, JumpTarget> LabelMapTy;
   LabelMapTy LabelMap;
 
   // A list of blocks that end with a "goto" that must be backpatched to their
@@ -251,7 +251,7 @@ class CFGBuilder {
   BackpatchBlocksTy BackpatchBlocks;
 
   // A list of labels whose address has been taken (for indirect gotos).
-  typedef llvm::SmallPtrSet<LabelStmt*,5> LabelSetTy;
+  typedef llvm::SmallPtrSet<LabelDecl*, 5> LabelSetTy;
   LabelSetTy AddressTakenLabels;
 
   bool badCFG;
@@ -648,13 +648,13 @@ void CFGBuilder::addLocalScopeForStmt(Stmt* S) {
   LocalScope *Scope = 0;
 
   // For compound statement we will be creating explicit scope.
-  if (CompoundStmtCS = dyn_cast<CompoundStmt>(S)) {
+  if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
     for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end()
         ; BI != BE; ++BI) {
-      StmtSI = *BI;
-      if (LabelStmtLS = dyn_cast<LabelStmt>(SI))
+      Stmt *SI = *BI;
+      if (LabelStmt *LS = dyn_cast<LabelStmt>(SI))
         SI = LS->getSubStmt();
-      if (DeclStmtDS = dyn_cast<DeclStmt>(SI))
+      if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
         Scope = addLocalScopeForDeclStmt(DS, Scope);
     }
     return;
@@ -662,9 +662,9 @@ void CFGBuilder::addLocalScopeForStmt(Stmt* S) {
 
   // For any other statement scope will be implicit and as such will be
   // interesting only for DeclStmt.
-  if (LabelStmtLS = dyn_cast<LabelStmt>(S))
+  if (LabelStmt *LS = dyn_cast<LabelStmt>(S))
     S = LS->getSubStmt();
-  if (DeclStmtDS = dyn_cast<DeclStmt>(S))
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(S))
     addLocalScopeForDeclStmt(DS);
 }
 
@@ -1454,16 +1454,17 @@ CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
   return VisitStmt(R, AddStmtChoice::AlwaysAdd);
 }
 
-CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmtL) {
+CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt *L) {
   // Get the block of the labeled statement.  Add it to our map.
   addStmt(L->getSubStmt());
-  CFGBlockLabelBlock = Block;
+  CFGBlock *LabelBlock = Block;
 
   if (!LabelBlock)              // This can happen when the body is empty, i.e.
     LabelBlock = createBlock(); // scopes that only contains NullStmts.
 
-  assert(LabelMap.find(L) == LabelMap.end() && "label already in map");
-  LabelMap[ L ] = JumpTarget(LabelBlock, ScopePos);
+  assert(LabelMap.find(L->getDecl()) == LabelMap.end() &&
+         "label already in map");
+  LabelMap[L->getDecl()] = JumpTarget(LabelBlock, ScopePos);
 
   // Labels partition blocks, so this is the end of the basic block we were
   // processing (L is the block's label).  Because this is label (and we have
index 129416fa07f90565b1370f80f3f51086c54f11d0..97dbf0ba3161ca468b65efa8ac20ae01a3a29ddb 100644 (file)
@@ -70,7 +70,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
   case Decl::Friend:
   case Decl::FriendTemplate:
   case Decl::Block:
-    
+  case Decl::Label:
     assert(0 && "Declaration not should not be in declstmts!");
   case Decl::Function:  // void X();
   case Decl::Record:    // struct/union/class X;
index f782c8004a165fdf5eea2ef67d257558da63a2ce..f809c009ce11f286cb7298328a1fa8c28a7ad025 100644 (file)
@@ -208,7 +208,7 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
     // emitting them before we evaluate the subexpr.
     const Stmt *LastStmt = S.body_back();
     while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) {
-      EmitLabel(*LS);
+      EmitLabel(LS->getDecl());
       LastStmt = LS->getSubStmt();
     }
 
@@ -276,24 +276,24 @@ void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
 }
 
 CodeGenFunction::JumpDest
-CodeGenFunction::getJumpDestForLabel(const LabelStmt *S) {
-  JumpDest &Dest = LabelMap[S];
+CodeGenFunction::getJumpDestForLabel(const LabelDecl *D) {
+  JumpDest &Dest = LabelMap[D];
   if (Dest.isValid()) return Dest;
 
   // Create, but don't insert, the new block.
-  Dest = JumpDest(createBasicBlock(S->getName()),
+  Dest = JumpDest(createBasicBlock(D->getName()),
                   EHScopeStack::stable_iterator::invalid(),
                   NextCleanupDestIndex++);
   return Dest;
 }
 
-void CodeGenFunction::EmitLabel(const LabelStmt &S) {
-  JumpDest &Dest = LabelMap[&S];
+void CodeGenFunction::EmitLabel(const LabelDecl *D) {
+  JumpDest &Dest = LabelMap[D];
 
   // If we didn't need a forward reference to this label, just go
   // ahead and create a destination at the current scope.
   if (!Dest.isValid()) {
-    Dest = getJumpDestInCurrentScope(S.getName());
+    Dest = getJumpDestInCurrentScope(D->getName());
 
   // Otherwise, we need to give this label a target depth and remove
   // it from the branch-fixups list.
@@ -311,7 +311,7 @@ void CodeGenFunction::EmitLabel(const LabelStmt &S) {
 
 
 void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
-  EmitLabel(S);
+  EmitLabel(S.getDecl());
   EmitStmt(S.getSubStmt());
 }
 
@@ -327,7 +327,7 @@ void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
 
 
 void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
-  if (const LabelStmt *Target = S.getConstantTarget()) {
+  if (const LabelDecl *Target = S.getConstantTarget()) {
     EmitBranchThroughCleanup(getJumpDestForLabel(Target));
     return;
   }
index ee8b98cdd49544fe7a11874f33cc3233259f3810..b316fa86f1e68b8cefc3544d7686e6099cb257b7 100644 (file)
@@ -668,7 +668,7 @@ CodeGenFunction::EmitNullInitialization(llvm::Value *DestPtr, QualType Ty) {
   Builder.CreateMemSet(DestPtr, Builder.getInt8(0), SizeVal, Align, false);
 }
 
-llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelStmt *L) {
+llvm::BlockAddress *CodeGenFunction::GetAddrOfLabel(const LabelDecl *L) {
   // Make sure that there is a block for the indirect goto.
   if (IndirectBranch == 0)
     GetIndirectGotoBlock();
index c4971506c50b4ee639a2df8a393b3ef2f280781c..adbc223afc6842989287f9fc22be3a3625b2beb3 100644 (file)
@@ -45,6 +45,7 @@ namespace clang {
   class CXXDestructorDecl;
   class CXXTryStmt;
   class Decl;
+  class LabelDecl;
   class EnumConstantDecl;
   class FunctionDecl;
   class FunctionProtoType;
@@ -768,7 +769,7 @@ public:
   /// The given basic block lies in the current EH scope, but may be a
   /// target of a potentially scope-crossing jump; get a stable handle
   /// to which we can perform this jump later.
-  JumpDest getJumpDestInCurrentScope(const char *Name = 0) {
+  JumpDest getJumpDestInCurrentScope(llvm::StringRef Name = llvm::StringRef()) {
     return getJumpDestInCurrentScope(createBasicBlock(Name));
   }
 
@@ -887,7 +888,7 @@ private:
   DeclMapTy LocalDeclMap;
 
   /// LabelMap - This keeps track of the LLVM basic block for each C label.
-  llvm::DenseMap<const LabelStmt*, JumpDest> LabelMap;
+  llvm::DenseMap<const LabelDecl*, JumpDest> LabelMap;
 
   // BreakContinueStack - This keeps track of where break and continue
   // statements should jump to.
@@ -1168,7 +1169,7 @@ public:
 
   /// getBasicBlockForLabel - Return the LLVM basicblock that the specified
   /// label maps to.
-  JumpDest getJumpDestForLabel(const LabelStmt *S);
+  JumpDest getJumpDestForLabel(const LabelDecl *S);
 
   /// SimplifyForwardingBlocks - If the given basic block is only a branch to
   /// another basic block, simplify it. This assumes that no other code could
@@ -1321,7 +1322,7 @@ public:
   /// the input field number being accessed.
   static unsigned getAccessedFieldNo(unsigned Idx, const llvm::Constant *Elts);
 
-  llvm::BlockAddress *GetAddrOfLabel(const LabelStmt *L);
+  llvm::BlockAddress *GetAddrOfLabel(const LabelDecl *L);
   llvm::BasicBlock *GetIndirectGotoBlock();
 
   /// EmitNullInitialization - Generate code to set a value of the given type to
@@ -1504,7 +1505,7 @@ public:
 
   /// EmitLabel - Emit the block for the given label. It is legal to call this
   /// function even if there is no current insertion point.
-  void EmitLabel(const LabelStmt &S); // helper for EmitLabelStmt.
+  void EmitLabel(const LabelDecl *D); // helper for EmitLabelStmt.
 
   void EmitLabelStmt(const LabelStmt &S);
   void EmitGotoStmt(const GotoStmt &S);
index bd6b48a30ff2748d2a2debb7a83f00f84dbefc7a..b73f0e9f1452fbe22d8e1da57fe54b0be4776f06 100644 (file)
@@ -62,7 +62,7 @@ class JumpScopeChecker {
   llvm::SmallVector<Stmt*, 16> Jumps;
 
   llvm::SmallVector<IndirectGotoStmt*, 4> IndirectJumps;
-  llvm::SmallVector<LabelStmt*, 4> IndirectJumpTargets;
+  llvm::SmallVector<LabelDecl*, 4> IndirectJumpTargets;
 public:
   JumpScopeChecker(Stmt *Body, Sema &S);
 private:
@@ -71,7 +71,7 @@ private:
   void VerifyJumps();
   void VerifyIndirectJumps();
   void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope,
-                            LabelStmt *Target, unsigned TargetScope);
+                            LabelDecl *Target, unsigned TargetScope);
   void CheckJump(Stmt *From, Stmt *To,
                  SourceLocation DiagLoc, unsigned JumpDiag);
 
@@ -235,12 +235,12 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) {
     // order to avoid blowing out the stack.
     while (true) {
       Stmt *Next;
-      if (isa<CaseStmt>(SubStmt))
-        Next = cast<CaseStmt>(SubStmt)->getSubStmt();
-      else if (isa<DefaultStmt>(SubStmt))
-        Next = cast<DefaultStmt>(SubStmt)->getSubStmt();
-      else if (isa<LabelStmt>(SubStmt))
-        Next = cast<LabelStmt>(SubStmt)->getSubStmt();
+      if (CaseStmt *CS = dyn_cast<CaseStmt>(SubStmt))
+        Next = CS->getSubStmt();
+      else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SubStmt))
+        Next = DS->getSubStmt();
+      else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt))
+        Next = LS->getSubStmt();
       else
         break;
 
@@ -346,15 +346,15 @@ void JumpScopeChecker::VerifyJumps() {
 
     // With a goto,
     if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) {
-      CheckJump(GS, GS->getLabel(), GS->getGotoLoc(),
+      CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(),
                 diag::err_goto_into_protected_scope);
       continue;
     }
 
     // We only get indirect gotos here when they have a constant target.
     if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) {
-      LabelStmt *Target = IGS->getConstantTarget();
-      CheckJump(IGS, Target, IGS->getGotoLoc(),
+      LabelDecl *Target = IGS->getConstantTarget();
+      CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(),
                 diag::err_goto_into_protected_scope);
       continue;
     }
@@ -424,15 +424,15 @@ void JumpScopeChecker::VerifyIndirectJumps() {
   // Collect a single representative of every scope containing a
   // label whose address was taken somewhere in the function.
   // For most code bases, there will be only one such scope.
-  llvm::DenseMap<unsigned, LabelStmt*> TargetScopes;
-  for (llvm::SmallVectorImpl<LabelStmt*>::iterator
+  llvm::DenseMap<unsigned, LabelDecl*> TargetScopes;
+  for (llvm::SmallVectorImpl<LabelDecl*>::iterator
          I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end();
        I != E; ++I) {
-    LabelStmt *TheLabel = *I;
-    assert(LabelAndGotoScopes.count(TheLabel) &&
+    LabelDecl *TheLabel = *I;
+    assert(LabelAndGotoScopes.count(TheLabel->getStmt()) &&
            "Referenced label didn't get added to scopes?");
-    unsigned LabelScope = LabelAndGotoScopes[TheLabel];
-    LabelStmt *&Target = TargetScopes[LabelScope];
+    unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()];
+    LabelDecl *&Target = TargetScopes[LabelScope];
     if (!Target) Target = TheLabel;
   }
 
@@ -445,10 +445,10 @@ void JumpScopeChecker::VerifyIndirectJumps() {
   // entered, then verify that every jump scope can be trivially
   // exitted to reach a scope in S.
   llvm::BitVector Reachable(Scopes.size(), false);
-  for (llvm::DenseMap<unsigned,LabelStmt*>::iterator
+  for (llvm::DenseMap<unsigned,LabelDecl*>::iterator
          TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) {
     unsigned TargetScope = TI->first;
-    LabelStmt *TargetLabel = TI->second;
+    LabelDecl *TargetLabel = TI->second;
 
     Reachable.reset();
 
@@ -511,12 +511,12 @@ void JumpScopeChecker::VerifyIndirectJumps() {
 /// Diagnose an indirect jump which is known to cross scopes.
 void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump,
                                             unsigned JumpScope,
-                                            LabelStmt *Target,
+                                            LabelDecl *Target,
                                             unsigned TargetScope) {
   assert(JumpScope != TargetScope);
 
   S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope);
-  S.Diag(Target->getIdentLoc(), diag::note_indirect_goto_target);
+  S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target);
 
   unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope);
 
index 8fbbeb85e3edfcca17604425ad65b8f37289e67e..2e7f72f81c3d0b0d45f9629bf05073523101d156 100644 (file)
@@ -31,6 +31,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/StmtCXX.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/TargetInfo.h"
@@ -50,6 +51,53 @@ void FunctionScopeInfo::Clear() {
   ErrorTrap.reset();
 }
 
+bool FunctionScopeInfo::checkLabelUse(Stmt *Body, Sema &S) {
+  bool AnyErrors = false;
+  for (llvm::DenseMap<IdentifierInfo*, LabelDecl*>::iterator
+       I = LabelMap.begin(), E = LabelMap.end(); I != E; ++I) {
+    LabelDecl *L = I->second;
+    
+    // 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 (L->getStmt() != 0) {
+      if (!L->isUsed())
+        S.Diag(L->getLocation(), diag::warn_unused_label) << L->getDeclName();
+      continue;
+    }
+    
+    AnyErrors = true;
+    
+    // Emit error.
+    S.Diag(L->getLocation(), diag::err_undeclared_label_use) << L->getDeclName();
+    
+    // At this point, we have gotos that use the bogus label.  Stitch it into
+    // the function body so that the AST is well formed.
+    if (Body == 0) {
+      // The whole function wasn't parsed correctly.
+      continue;
+    }
+    
+    // Otherwise, the body is valid: we want to stitch the label decl into the
+    // function somewhere so that it is properly owned and so that the goto
+    // has a valid target.  Do this by creating LabelStmt and adding it to the
+    // end of the outer CompoundStmt.
+    LabelStmt *LS = new (S.Context) LabelStmt(L->getLocation(), L, 
+                                    new (S.Context) NullStmt(L->getLocation()));
+    
+    CompoundStmt *Compound = isa<CXXTryStmt>(Body) ?
+    cast<CXXTryStmt>(Body)->getTryBlock() :
+    cast<CompoundStmt>(Body);
+    llvm::SmallVector<Stmt*, 64> Elements(Compound->body_begin(),
+                                          Compound->body_end());
+    Elements.push_back(LS);
+    Compound->setStmts(S.Context, Elements.data(), Elements.size());
+  }
+  return AnyErrors;
+}
+
+
+
 BlockScopeInfo::~BlockScopeInfo() { }
 
 void Sema::ActOnTranslationUnitScope(Scope *S) {
index 2807e759b56d4bffb0b8245308a1247bfe34f121..bcec9d483938cb77084f34dfcdcd48b98ac866fb 100644 (file)
@@ -5477,46 +5477,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
 
   // Check goto/label use.
   FunctionScopeInfo *CurFn = getCurFunction();
-  for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
-         I = CurFn->LabelMap.begin(), E = CurFn->LabelMap.end(); I != E; ++I) {
-    LabelStmt *L = I->second;
-
-    // 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 (L->getSubStmt() != 0) {
-      if (!L->isUsed())
-        Diag(L->getIdentLoc(), diag::warn_unused_label) << L->getName();
-      continue;
-    }
-
-    // Emit error.
-    Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->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.
-    if (Body == 0) {
-      // The whole function wasn't parsed correctly.
-      continue;
-    }
-
-    // Otherwise, the body is valid: we want to stitch the label decl into the
-    // function somewhere so that it is properly owned and so that the goto
-    // has a valid target.  Do this by creating a new compound stmt with the
-    // label in it.
-
-    // Give the label a sub-statement.
-    L->setSubStmt(new (Context) NullStmt(L->getIdentLoc()));
-
-    CompoundStmt *Compound = isa<CXXTryStmt>(Body) ?
-                               cast<CXXTryStmt>(Body)->getTryBlock() :
-                               cast<CompoundStmt>(Body);
-    llvm::SmallVector<Stmt*, 64> Elements(Compound->body_begin(),
-                                          Compound->body_end());
-    Elements.push_back(L);
-    Compound->setStmts(Context, Elements.data(), Elements.size());
-  }
+  CurFn->checkLabelUse(Body, *this);
 
   if (Body) {
     // C++ constructors that have function-try-blocks can't have return
index 0a956079750e8fe05d1abc10a58c89a92457551c..94dd27d0c221afe6274734ed1ab77e431af181fa 100644 (file)
@@ -8321,20 +8321,19 @@ ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc,
 }
 
 /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo".
-ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
-                                            SourceLocation LabLoc,
-                                            IdentifierInfo *LabelII) {
+ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc,
+                                IdentifierInfo *LabelII) {
   // Look up the record for this label identifier.
-  LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII];
+  LabelDecl *&TheDecl = getCurFunction()->LabelMap[LabelII];
 
   // If we haven't seen this label yet, create a forward reference. It
   // will be validated and/or cleaned up in ActOnFinishFunctionBody.
-  if (LabelDecl == 0)
-    LabelDecl = new (Context) LabelStmt(LabLoc, LabelII, 0);
+  if (TheDecl == 0)
+    TheDecl = LabelDecl::Create(Context, CurContext, LabLoc, LabelII);
 
-  LabelDecl->setUsed();
+  TheDecl->setUsed();
   // Create the AST node.  The address of a label always has type 'void*'.
-  return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, LabelDecl,
+  return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl,
                                        Context.getPointerType(Context.VoidTy)));
 }
 
@@ -8833,25 +8832,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
 
   BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
 
-  bool Good = true;
   // Check goto/label use.
-  for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
-         I = BSI->LabelMap.begin(), E = BSI->LabelMap.end(); I != E; ++I) {
-    LabelStmt *L = I->second;
-
-    // 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.
-    if (L->getSubStmt() != 0) {
-      if (!L->isUsed())
-        Diag(L->getIdentLoc(), diag::warn_unused_label) << L->getName();
-      continue;
-    }
-
-    // Emit error.
-    Diag(L->getIdentLoc(), diag::err_undeclared_label_use) << L->getName();
-    Good = false;
-  }
-  if (!Good) {
+  if (BSI->checkLabelUse(0, *this)) {
     PopFunctionOrBlockScope();
     return ExprError();
   }
index e5fd01ab707f1dc2a61f8b72c7e1d69904518c3c..2b323ef4b446ff125d2c729a7efd308d2c06a524 100644 (file)
@@ -255,29 +255,31 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
                      SourceLocation ColonLoc, Stmt *SubStmt,
                      bool HasUnusedAttr) {
   // Look up the record for this label identifier.
-  LabelStmt *&LabelDecl = getCurFunction()->LabelMap[II];
+  LabelDecl *&TheDecl = getCurFunction()->LabelMap[II];
 
-  // If not forward referenced or defined already, just create a new LabelStmt.
-  if (LabelDecl == 0)
-    return Owned(LabelDecl = new (Context) LabelStmt(IdentLoc, II, SubStmt,
-                                                     HasUnusedAttr));
+  // If not forward referenced or defined already, create the backing decl.
+  if (TheDecl == 0)
+    TheDecl = LabelDecl::Create(Context, CurContext, IdentLoc, II);
 
-  assert(LabelDecl->getID() == II && "Label mismatch!");
+  assert(TheDecl->getIdentifier() == 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) << LabelDecl->getID();
-    Diag(LabelDecl->getIdentLoc(), diag::note_previous_definition);
+  // If the label was multiply defined, reject it now.
+  if (TheDecl->getStmt()) {
+    Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();
+    Diag(TheDecl->getLocation(), diag::note_previous_definition);
     return Owned(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(SubStmt);
-  LabelDecl->setUnusedAttribute(HasUnusedAttr);
-  return Owned(LabelDecl);
+  // Otherwise, things are good.  Fill in the declaration and return it.
+  TheDecl->setLocation(IdentLoc);
+  
+  // FIXME: Just use Decl ATTRIBUTES!
+  if (HasUnusedAttr)
+    TheDecl->setHasUnusedAttribute();
+  LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt);
+  TheDecl->setStmt(LS);
+  TheDecl->setLocation(IdentLoc);
+  return Owned(LS);
 }
 
 StmtResult
@@ -1036,17 +1038,17 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc,
 StmtResult
 Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
                     IdentifierInfo *LabelII) {
-  // Look up the record for this label identifier.
-  LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII];
-
   getCurFunction()->setHasBranchIntoScope();
+  
+  // Look up the record for this label identifier.
+  LabelDecl *&TheDecl = getCurFunction()->LabelMap[LabelII];
 
   // If we haven't seen this label yet, create a forward reference.
-  if (LabelDecl == 0)
-    LabelDecl = new (Context) LabelStmt(LabelLoc, LabelII, 0);
+  if (TheDecl == 0)
+    TheDecl = LabelDecl::Create(Context, CurContext, LabelLoc, LabelII);
 
-  LabelDecl->setUsed();
-  return Owned(new (Context) GotoStmt(LabelDecl, GotoLoc, LabelLoc));
+  TheDecl->setUsed();
+  return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc));
 }
 
 StmtResult
index ca5d1c1ea0f3348b8302eac5118eb464cadfc359..cb0d4250fca577175a769e142b3d4bfa941dbe41 100644 (file)
@@ -975,10 +975,9 @@ public:
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
-  StmtResult RebuildLabelStmt(SourceLocation IdentLoc,
-                                    IdentifierInfo *Id,
-                                    SourceLocation ColonLoc,
-                                    Stmt *SubStmt, bool HasUnusedAttr) {
+  StmtResult RebuildLabelStmt(SourceLocation IdentLoc, IdentifierInfo *Id,
+                              SourceLocation ColonLoc, Stmt *SubStmt,
+                              bool HasUnusedAttr) {
     return SemaRef.ActOnLabelStmt(IdentLoc, Id, ColonLoc, SubStmt,
                                   HasUnusedAttr);
   }
@@ -1028,10 +1027,8 @@ public:
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildDoStmt(SourceLocation DoLoc, Stmt *Body,
-                                 SourceLocation WhileLoc,
-                                 SourceLocation LParenLoc,
-                                 Expr *Cond,
-                                 SourceLocation RParenLoc) {
+                           SourceLocation WhileLoc, SourceLocation LParenLoc,
+                           Expr *Cond, SourceLocation RParenLoc) {
     return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc,
                                  Cond, RParenLoc);
   }
@@ -1040,24 +1037,21 @@ public:
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
-  StmtResult RebuildForStmt(SourceLocation ForLoc,
-                                  SourceLocation LParenLoc,
-                                  Stmt *Init, Sema::FullExprArg Cond, 
-                                  VarDecl *CondVar, Sema::FullExprArg Inc,
-                                  SourceLocation RParenLoc, Stmt *Body) {
+  StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
+                            Stmt *Init, Sema::FullExprArg Cond, 
+                            VarDecl *CondVar, Sema::FullExprArg Inc,
+                            SourceLocation RParenLoc, Stmt *Body) {
     return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond, 
-                                  CondVar,
-                                  Inc, RParenLoc, Body);
+                                  CondVar, Inc, RParenLoc, Body);
   }
 
   /// \brief Build a new goto statement.
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
-  StmtResult RebuildGotoStmt(SourceLocation GotoLoc,
-                                   SourceLocation LabelLoc,
-                                   LabelStmt *Label) {
-    return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label->getID());
+  StmtResult RebuildGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
+                             LabelDecl *Label) {
+    return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label->getIdentifier());
   }
 
   /// \brief Build a new indirect goto statement.
@@ -1065,8 +1059,8 @@ public:
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   StmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc,
-                                           SourceLocation StarLoc,
-                                           Expr *Target) {
+                                     SourceLocation StarLoc,
+                                     Expr *Target) {
     return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, Target);
   }
 
@@ -1074,9 +1068,7 @@ public:
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
-  StmtResult RebuildReturnStmt(SourceLocation ReturnLoc,
-                                     Expr *Result) {
-
+  StmtResult RebuildReturnStmt(SourceLocation ReturnLoc, Expr *Result) {
     return getSema().ActOnReturnStmt(ReturnLoc, Result);
   }
 
@@ -1550,9 +1542,8 @@ public:
   /// rather than attempting to map the label statement itself.
   /// Subclasses may override this routine to provide different behavior.
   ExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc,
-                                        SourceLocation LabelLoc,
-                                        LabelStmt *Label) {
-    return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label->getID());
+                                  SourceLocation LabelLoc, LabelDecl *Label) {
+    return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc,Label->getIdentifier());
   }
 
   /// \brief Build a new GNU statement expression.
@@ -4522,8 +4513,10 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
 
   // FIXME: Pass the real colon location in.
   SourceLocation ColonLoc = SemaRef.PP.getLocForEndOfToken(S->getIdentLoc());
-  return getDerived().RebuildLabelStmt(S->getIdentLoc(), S->getID(), ColonLoc,
-                                       SubStmt.get(), S->HasUnusedAttribute());
+  return getDerived().RebuildLabelStmt(S->getIdentLoc(),
+                                       S->getDecl()->getIdentifier(), ColonLoc,
+                                       SubStmt.get(),
+                                       S->getDecl()->hasUnusedAttribute());
 }
 
 template<typename Derived>
index fcf09b7bd566dee6d199297ed054e68880ca5c6c..83f8a84d6644c4124d88ac91656a6d27bc4b5148 100644 (file)
@@ -4814,72 +4814,6 @@ void ASTReader::ClearSwitchCaseIDs() {
   SwitchCaseStmts.clear();
 }
 
-/// \brief Record that the given label statement has been
-/// deserialized and has the given ID.
-void ASTReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
-  assert(LabelStmts.find(ID) == LabelStmts.end() &&
-         "Deserialized label twice");
-  LabelStmts[ID] = S;
-
-  // If we've already seen any goto statements that point to this
-  // label, resolve them now.
-  typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
-  std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
-  for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
-    Goto->second->setLabel(S);
-  UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
-
-  // If we've already seen any address-label statements that point to
-  // this label, resolve them now.
-  typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
-  std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
-    = UnresolvedAddrLabelExprs.equal_range(ID);
-  for (AddrLabelIter AddrLabel = AddrLabels.first;
-       AddrLabel != AddrLabels.second; ++AddrLabel)
-    AddrLabel->second->setLabel(S);
-  UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
-}
-
-/// \brief Set the label of the given statement to the label
-/// identified by ID.
-///
-/// Depending on the order in which the label and other statements
-/// referencing that label occur, this operation may complete
-/// immediately (updating the statement) or it may queue the
-/// statement to be back-patched later.
-void ASTReader::SetLabelOf(GotoStmt *S, unsigned ID) {
-  std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
-  if (Label != LabelStmts.end()) {
-    // We've already seen this label, so set the label of the goto and
-    // we're done.
-    S->setLabel(Label->second);
-  } else {
-    // We haven't seen this label yet, so add this goto to the set of
-    // unresolved goto statements.
-    UnresolvedGotoStmts.insert(std::make_pair(ID, S));
-  }
-}
-
-/// \brief Set the label of the given expression to the label
-/// identified by ID.
-///
-/// Depending on the order in which the label and other statements
-/// referencing that label occur, this operation may complete
-/// immediately (updating the statement) or it may queue the
-/// statement to be back-patched later.
-void ASTReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
-  std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
-  if (Label != LabelStmts.end()) {
-    // We've already seen this label, so set the label of the
-    // label-address expression and we're done.
-    S->setLabel(Label->second);
-  } else {
-    // We haven't seen this label yet, so add this label-address
-    // expression to the set of unresolved label-address expressions.
-    UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
-  }
-}
-
 void ASTReader::FinishedDeserializing() {
   assert(NumCurrentElementsDeserializing &&
          "FinishedDeserializing not paired with StartedDeserializing");
index 279d081098f56b5cc3685d8b7519eb3408a22ce8..27e771804c91570297d3e632eefffbdbe8c4f843 100644 (file)
@@ -84,6 +84,7 @@ namespace clang {
     void VisitDecl(Decl *D);
     void VisitTranslationUnitDecl(TranslationUnitDecl *TU);
     void VisitNamedDecl(NamedDecl *ND);
+    void VisitLabelDecl(LabelDecl *LD);
     void VisitNamespaceDecl(NamespaceDecl *D);
     void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
     void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
@@ -722,6 +723,12 @@ void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
   D->setHasBraces(Record[Idx++]);
 }
 
+void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
+  VisitNamedDecl(D);
+  if (Record[Idx++]) D->setHasUnusedAttribute();
+}
+
+
 void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
   VisitNamedDecl(D);
   D->IsInline = Record[Idx++];
@@ -1418,6 +1425,9 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
                                 (LinkageSpecDecl::LanguageIDs)0,
                                 false);
     break;
+  case DECL_LABEL:
+    D = LabelDecl::Create(*Context, 0, SourceLocation(), 0);
+    break;
   case DECL_NAMESPACE:
     D = NamespaceDecl::Create(*Context, 0, SourceLocation(), 0);
     break;
index 864c04283b0fc7dbc58f8c4e9d6f6fa90438fd65..bd59737825563e0c365476e26b592a3fdaf57564 100644 (file)
@@ -245,12 +245,11 @@ void ASTStmtReader::VisitDefaultStmt(DefaultStmt *S) {
 
 void ASTStmtReader::VisitLabelStmt(LabelStmt *S) {
   VisitStmt(S);
-  S->setID(Reader.GetIdentifierInfo(Record, Idx));
+  LabelDecl *LD = cast<LabelDecl>(Reader.GetDecl(Record[Idx++]));
+  LD->setStmt(S);
+  S->setDecl(LD);
   S->setSubStmt(Reader.ReadSubStmt());
   S->setIdentLoc(ReadSourceLocation(Record, Idx));
-  S->setUsed(Record[Idx++]);
-  S->setUnusedAttribute(Record[Idx++]);
-  Reader.RecordLabelStmt(S, Record[Idx++]);
 }
 
 void ASTStmtReader::VisitIfStmt(IfStmt *S) {
@@ -319,7 +318,7 @@ void ASTStmtReader::VisitForStmt(ForStmt *S) {
 
 void ASTStmtReader::VisitGotoStmt(GotoStmt *S) {
   VisitStmt(S);
-  Reader.SetLabelOf(S, Record[Idx++]);
+  S->setLabel(cast<LabelDecl>(Reader.GetDecl(Record[Idx++])));
   S->setGotoLoc(ReadSourceLocation(Record, Idx));
   S->setLabelLoc(ReadSourceLocation(Record, Idx));
 }
@@ -759,7 +758,7 @@ void ASTStmtReader::VisitAddrLabelExpr(AddrLabelExpr *E) {
   VisitExpr(E);
   E->setAmpAmpLoc(ReadSourceLocation(Record, Idx));
   E->setLabelLoc(ReadSourceLocation(Record, Idx));
-  Reader.SetLabelOf(E, Record[Idx++]);
+  E->setLabel(cast<LabelDecl>(Reader.GetDecl(Record[Idx++])));
 }
 
 void ASTStmtReader::VisitStmtExpr(StmtExpr *E) {
index 17ee85ad279d84c7a68bd01fd5daa4cffe8b8b72..dd43e1a05dbfa9668b0b3626e27b70e14f4d8009 100644 (file)
@@ -47,6 +47,7 @@ namespace clang {
     void VisitDecl(Decl *D);
     void VisitTranslationUnitDecl(TranslationUnitDecl *D);
     void VisitNamedDecl(NamedDecl *D);
+    void VisitLabelDecl(LabelDecl *LD);
     void VisitNamespaceDecl(NamespaceDecl *D);
     void VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
     void VisitNamespaceAliasDecl(NamespaceAliasDecl *D);
@@ -651,6 +652,13 @@ void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
   Code = serialization::DECL_LINKAGE_SPEC;
 }
 
+void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) {
+  VisitNamedDecl(D);
+  Record.push_back(D->hasUnusedAttribute());
+  Code = serialization::DECL_LABEL;
+}
+
+
 void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
   VisitNamedDecl(D);
   Record.push_back(D->isInline());
index 8a90ef16c30d51b683facb87fe1dc42af7f550a8..b043f2ee2c24913a27620c6d1e76739eda141f55 100644 (file)
@@ -217,12 +217,9 @@ void ASTStmtWriter::VisitDefaultStmt(DefaultStmt *S) {
 
 void ASTStmtWriter::VisitLabelStmt(LabelStmt *S) {
   VisitStmt(S);
-  Writer.AddIdentifierRef(S->getID(), Record);
+  Writer.AddDeclRef(S->getDecl(), Record);
   Writer.AddStmt(S->getSubStmt());
   Writer.AddSourceLocation(S->getIdentLoc(), Record);
-  Record.push_back(S->isUsed());
-  Record.push_back(S->HasUnusedAttribute());
-  Record.push_back(Writer.GetLabelID(S));
   Code = serialization::STMT_LABEL;
 }
 
@@ -284,7 +281,7 @@ void ASTStmtWriter::VisitForStmt(ForStmt *S) {
 
 void ASTStmtWriter::VisitGotoStmt(GotoStmt *S) {
   VisitStmt(S);
-  Record.push_back(Writer.GetLabelID(S->getLabel()));
+  Writer.AddDeclRef(S->getLabel(), Record);
   Writer.AddSourceLocation(S->getGotoLoc(), Record);
   Writer.AddSourceLocation(S->getLabelLoc(), Record);
   Code = serialization::STMT_GOTO;
@@ -722,7 +719,7 @@ void ASTStmtWriter::VisitAddrLabelExpr(AddrLabelExpr *E) {
   VisitExpr(E);
   Writer.AddSourceLocation(E->getAmpAmpLoc(), Record);
   Writer.AddSourceLocation(E->getLabelLoc(), Record);
-  Record.push_back(Writer.GetLabelID(E->getLabel()));
+  Writer.AddDeclRef(E->getLabel(), Record);
   Code = serialization::EXPR_ADDR_LABEL;
 }
 
@@ -1359,18 +1356,6 @@ void ASTWriter::ClearSwitchCaseIDs() {
   SwitchCaseIDs.clear();
 }
 
-/// \brief Retrieve the ID for the given label statement, which may
-/// or may not have been emitted yet.
-unsigned ASTWriter::GetLabelID(LabelStmt *S) {
-  std::map<LabelStmt *, unsigned>::iterator Pos = LabelIDs.find(S);
-  if (Pos != LabelIDs.end())
-    return Pos->second;
-
-  unsigned NextID = LabelIDs.size();
-  LabelIDs[S] = NextID;
-  return NextID;
-}
-
 /// \brief Write the given substatement or subexpression to the
 /// bitstream.
 void ASTWriter::WriteSubStmt(Stmt *S) {
index 99e120d303a55441fb2e5dcfa1bc8cd5c88818ed..50b1e37c132b5867b42b023cf3b299ee115d0991 100644 (file)
@@ -1344,7 +1344,7 @@ void ExprEngine::processBranch(const Stmt* Condition, const Stmt* Term,
 
 /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
 ///  nodes by processing the 'effects' of a computed goto jump.
-void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilderbuilder) {
+void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
 
   const GRState *state = builder.getState();
   SVal V = state->getSVal(builder.getTarget());
@@ -1359,16 +1359,16 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder& builder) {
   typedef IndirectGotoNodeBuilder::iterator iterator;
 
   if (isa<loc::GotoLabel>(V)) {
-    const LabelStmt* L = cast<loc::GotoLabel>(V).getLabel();
+    const LabelDecl *L = cast<loc::GotoLabel>(V).getLabel();
 
-    for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) {
+    for (iterator I = builder.begin(), E = builder.end(); I != E; ++I) {
       if (I.getLabel() == L) {
         builder.generateNode(I, state);
         return;
       }
     }
 
-    assert (false && "No block with label.");
+    assert(false && "No block with label.");
     return;
   }
 
index cc866d0127d86c1b9293aba9926f0fe2ab254d60..4614e349dece4275a4668813a6e49dabca437e6c 100644 (file)
@@ -350,7 +350,7 @@ void Loc::dumpToStream(llvm::raw_ostream& os) const {
       os << cast<loc::ConcreteInt>(this)->getValue().getZExtValue() << " (Loc)";
       break;
     case loc::GotoLabelKind:
-      os << "&&" << cast<loc::GotoLabel>(this)->getLabel()->getID()->getName();
+      os << "&&" << cast<loc::GotoLabel>(this)->getLabel()->getName();
       break;
     case loc::MemRegionKind:
       os << '&' << cast<loc::MemRegionVal>(this)->getRegion()->getString();
index f2ace35584c275e8acc1b7e51c38f1b358a20d39..90367f829566c3a75a5f682a68472cf4871c9179 100644 (file)
@@ -9,7 +9,7 @@ label1: // expected-note{{previous definition is here}}
   x = 1;
   goto label2; // expected-error{{use of undeclared label 'label2'}}
 
-label1: // expected-error{{redefinition of label ''label1''}}
+label1: // expected-error{{redefinition of label 'label1'}}
   x = 2;
 }
 
index 163446002e6043e5e18727d980bdda973862cc51..03be7da2fc9914f864468788e052e3db696cca7b 100644 (file)
@@ -4,8 +4,8 @@ void f() {
   a:
   goto a;
   b: // expected-warning{{unused}}
-  c: __attribute__((unused));
-  d: __attribute__((noreturn)); // expected-warning {{The only valid attribute for labels is 'unused'}}
+  c: __attribute__((unused));    // expected-warning {{unused label 'c'}}
+  d: __attribute__((noreturn)); // expected-warning {{the only valid attribute for labels is 'unused'}}
   goto d;
   return;
 }
index 88091006a81c8172d5432da81b7b209d2a2d0bfe..bcd6397a5844f149ef338dc1ef9e93ade8a58b06 100644 (file)
@@ -1529,14 +1529,14 @@ public:
 
 class LabelRefVisit : public VisitorJob {
 public:
-  LabelRefVisit(LabelStmt *LS, SourceLocation labelLoc, CXCursor parent)
-    : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LS,
+  LabelRefVisit(LabelDecl *LD, SourceLocation labelLoc, CXCursor parent)
+    : VisitorJob(parent, VisitorJob::LabelRefVisitKind, LD,
                  labelLoc.getPtrEncoding()) {}
   
   static bool classof(const VisitorJob *VJ) {
     return VJ->getKind() == VisitorJob::LabelRefVisitKind;
   }
-  LabelStmt *get() const { return static_cast<LabelStmt*>(data[0]); }
+  LabelDecl *get() const { return static_cast<LabelDecl*>(data[0]); }
   SourceLocation getLoc() const { 
     return SourceLocation::getFromPtrEncoding(data[1]); }
 };
@@ -1985,8 +1985,8 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) {
         continue;
       }
       case VisitorJob::LabelRefVisitKind: {
-        LabelStmt *LS = cast<LabelRefVisit>(&LI)->get();
-        if (Visit(MakeCursorLabelRef(LS,
+        LabelDecl *LS = cast<LabelRefVisit>(&LI)->get();
+        if (Visit(MakeCursorLabelRef(LS->getStmt(),
                                      cast<LabelRefVisit>(&LI)->getLoc(),
                                      TU)))
           return true;
@@ -2851,7 +2851,7 @@ CXString clang_getCursorSpelling(CXCursor C) {
       LabelStmt *Label = getCursorLabelRef(C).first;
       assert(Label && "Missing label");
       
-      return createCXString(Label->getID()->getName());
+      return createCXString(Label->getName());
     }
 
     case CXCursor_OverloadedDeclRef: {
@@ -2885,7 +2885,7 @@ CXString clang_getCursorSpelling(CXCursor C) {
   if (clang_isStatement(C.kind)) {
     Stmt *S = getCursorStmt(C);
     if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
-      return createCXString(Label->getID()->getName());
+      return createCXString(Label->getName());
 
     return createCXString("");
   }
@@ -3569,7 +3569,7 @@ CXCursor clang_getCursorReferenced(CXCursor C) {
   if (clang_isStatement(C.kind)) {
     Stmt *S = getCursorStmt(C);
     if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
-      return MakeCXCursor(Goto->getLabel(), getCursorDecl(C), tu);
+      return MakeCXCursor(Goto->getLabel()->getStmt(), getCursorDecl(C), tu);
 
     return clang_getNullCursor();
   }
@@ -3676,6 +3676,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
   case Decl::FileScopeAsm:
   case Decl::StaticAssert:
   case Decl::Block:
+  case Decl::Label:  // FIXME: Is this right??
     return C;
 
   // Declaration kinds that don't make any sense here, but are