aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2011-02-17 07:39:24 +0000
committerChris Lattner <sabre@nondot.org>2011-02-17 07:39:24 +0000
commitad8dcf4a9df0e24051dc31bf9e6f3cd138a34298 (patch)
treed937c0c2c2c7d6a5a9ed8efbd45903e4314cba94
parent1aa3d81c6e63959ef149489eca42b1520c521af4 (diff)
Step #1/N of implementing support for __label__: split labels into
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
-rw-r--r--include/clang/AST/Decl.h31
-rw-r--r--include/clang/AST/DeclBase.h2
-rw-r--r--include/clang/AST/Expr.h8
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h5
-rw-r--r--include/clang/AST/Stmt.h48
-rw-r--r--include/clang/Basic/DeclNodes.td1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--include/clang/Sema/ScopeInfo.h15
-rw-r--r--include/clang/Serialization/ASTBitCodes.h4
-rw-r--r--include/clang/Serialization/ASTReader.h39
-rw-r--r--include/clang/Serialization/ASTWriter.h8
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h2
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h9
-rw-r--r--lib/AST/Decl.cpp6
-rw-r--r--lib/AST/DeclBase.cpp3
-rw-r--r--lib/AST/Stmt.cpp4
-rw-r--r--lib/AST/StmtProfile.cpp6
-rw-r--r--lib/Analysis/CFG.cpp25
-rw-r--r--lib/CodeGen/CGDecl.cpp2
-rw-r--r--lib/CodeGen/CGStmt.cpp18
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp2
-rw-r--r--lib/CodeGen/CodeGenFunction.h11
-rw-r--r--lib/Sema/JumpDiagnostics.cpp42
-rw-r--r--lib/Sema/Sema.cpp48
-rw-r--r--lib/Sema/SemaDecl.cpp41
-rw-r--r--lib/Sema/SemaExpr.cpp34
-rw-r--r--lib/Sema/SemaStmt.cpp50
-rw-r--r--lib/Sema/TreeTransform.h51
-rw-r--r--lib/Serialization/ASTReader.cpp66
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp10
-rw-r--r--lib/Serialization/ASTReaderStmt.cpp11
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp8
-rw-r--r--lib/Serialization/ASTWriterStmt.cpp21
-rw-r--r--lib/StaticAnalyzer/Checkers/ExprEngine.cpp8
-rw-r--r--lib/StaticAnalyzer/Core/SVals.cpp2
-rw-r--r--test/CXX/stmt.stmt/stmt.label/p1.cpp2
-rw-r--r--test/Sema/warn-unused-label.c4
-rw-r--r--tools/libclang/CIndex.cpp17
39 files changed, 294 insertions, 384 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index cba71ae8cd..e0ffa627ac 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -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;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 3e92c4e651..1407dadd16 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -324,7 +324,7 @@ public:
bool hasAttrs() const { return HasAttrs; }
void setAttrs(const AttrVec& Attrs);
- AttrVec& getAttrs() {
+ AttrVec &getAttrs() {
return const_cast<AttrVec&>(const_cast<const Decl*>(this)->getAttrs());
}
const AttrVec &getAttrs() const;
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index c09394d9c0..b5724a6475 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -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;
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 8ddd5875ce..667b840889 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -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
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index 1254926fac..7ede9ce323 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -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();
}
diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td
index f6c31f4877..2ec7427cf7 100644
--- a/include/clang/Basic/DeclNodes.td
+++ b/include/clang/Basic/DeclNodes.td
@@ -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>;
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index eb8bf590c3..b815426f6c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index edd1432d8e..c9d38715ec 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -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();
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 391438248e..d1998c29a3 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -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,
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 94bfd16353..002f6be410 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -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
diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h
index f9a49973e1..d5f622a340 100644
--- a/include/clang/Serialization/ASTWriter.h
+++ b/include/clang/Serialization/ASTWriter.h
@@ -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; }
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
index d879ea13e7..800e63a4cd 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
@@ -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;
}
};
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 9c18711742..e7b39448ac 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -238,7 +238,7 @@ public:
return loc::MemRegionVal(R);
}
- Loc makeLoc(const AddrLabelExpr* E) {
+ Loc makeLoc(const AddrLabelExpr *E) {
return loc::GotoLabel(E->getLabel());
}
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 1d1cd0b8f9..0d430794e7 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -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) {
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index fded8ff38c..441444da9e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -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);
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 110de64d8c..dfc5a6ae5d 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -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;
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 66182957d6..7e73f02e67 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -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();
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index b96ffe8a48..2ffb807abc 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -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) {
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index d46b7e7830..6da4784405 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -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 (CompoundStmt* CS = 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) {
- Stmt* SI = *BI;
- if (LabelStmt* LS = dyn_cast<LabelStmt>(SI))
+ Stmt *SI = *BI;
+ if (LabelStmt *LS = dyn_cast<LabelStmt>(SI))
SI = LS->getSubStmt();
- if (DeclStmt* DS = 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 (LabelStmt* LS = dyn_cast<LabelStmt>(S))
+ if (LabelStmt *LS = dyn_cast<LabelStmt>(S))
S = LS->getSubStmt();
- if (DeclStmt* DS = 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(LabelStmt* L) {
+CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt *L) {
// Get the block of the labeled statement. Add it to our map.
addStmt(L->getSubStmt());
- CFGBlock* LabelBlock = Block;
+ CFGBlock *LabelBlock = Block;
if (!LabelBlock) // This can happen when the body is empty, i.e.<