/// location of the statement. For GNU local labels (__label__), the decl
/// location is where the __label__ is.
class LabelDecl : public NamedDecl {
- llvm::PointerIntPair<LabelStmt *, 1, bool> StmtAndGnuLocal;
- LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II,
- LabelStmt *S, bool isGnuLocal)
- : NamedDecl(Label, DC, L, II), StmtAndGnuLocal(S, isGnuLocal) {}
-
+ LabelStmt *TheStmt;
+ /// LocStart - For normal labels, this is the same as the main declaration
+ /// label, i.e., the location of the identifier; for GNU local labels,
+ /// this is the location of the __label__ keyword.
+ SourceLocation LocStart;
+
+ LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
+ LabelStmt *S, SourceLocation StartL)
+ : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {}
+
public:
static LabelDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *II,
- bool isGnuLocal = false);
+ SourceLocation IdentL, IdentifierInfo *II);
+ static LabelDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdentL, IdentifierInfo *II,
+ SourceLocation GnuLabelL);
- LabelStmt *getStmt() const { return StmtAndGnuLocal.getPointer(); }
- void setStmt(LabelStmt *T) { StmtAndGnuLocal.setPointer(T); }
-
- bool isGnuLocal() const { return StmtAndGnuLocal.getInt(); }
- void setGnuLocal(bool V = true) { StmtAndGnuLocal.setInt(V); }
+ LabelStmt *getStmt() const { return TheStmt; }
+ void setStmt(LabelStmt *T) { TheStmt = T; }
+
+ bool isGnuLocal() const { return LocStart != getLocation(); }
+ void setLocStart(SourceLocation L) { LocStart = L; }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(LocStart, getLocation());
+ }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
QualType T1, QualType T2,
UnresolvedSetImpl &Functions);
- LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- bool isLocalLabel = false);
-
+ LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
+ SourceLocation GnuLabelLoc = SourceLocation());
+
DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class);
CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class);
}
LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, IdentifierInfo *II,
- bool isGnuLocal) {
- return new (C) LabelDecl(DC, L, II, 0, isGnuLocal);
+ SourceLocation IdentL, IdentifierInfo *II) {
+ return new (C) LabelDecl(DC, IdentL, II, 0, IdentL);
+}
+
+LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
+ SourceLocation IdentL, IdentifierInfo *II,
+ SourceLocation GnuLabelL) {
+ assert(GnuLabelL != IdentL && "Use this only for GNU local labels");
+ return new (C) LabelDecl(DC, IdentL, II, 0, GnuLabelL);
}
IdentifierInfo *II = Tok.getIdentifierInfo();
SourceLocation IdLoc = ConsumeToken();
- DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, true));
+ DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
if (!Tok.is(tok::comma))
break;
}
/// LookupOrCreateLabel - Do a name lookup of a label with the specified name.
-/// If isLocalLabel is true, then this is a definition of an __label__ label
-/// name, otherwise it is a normal label definition or use.
+/// If GnuLabelLoc is a valid source location, then this is a definition
+/// of an __label__ label name, otherwise it is a normal label definition
+/// or use.
LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- bool isLocalLabel) {
+ SourceLocation GnuLabelLoc) {
// Do a lookup to see if we have a label with this name already.
NamedDecl *Res = 0;
-
- // Local label definitions always shadow existing labels.
- if (!isLocalLabel)
- Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration);
-
- // If we found a label, check to see if it is in the same context as us. When
- // in a Block, we don't want to reuse a label in an enclosing function.
+
+ if (GnuLabelLoc.isValid()) {
+ // Local label definitions always shadow existing labels.
+ Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc);
+ Scope *S = CurScope;
+ PushOnScopeChains(Res, S, true);
+ return cast<LabelDecl>(Res);
+ }
+
+ // Not a GNU local label.
+ Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration);
+ // If we found a label, check to see if it is in the same context as us.
+ // When in a Block, we don't want to reuse a label in an enclosing function.
if (Res && Res->getDeclContext() != CurContext)
Res = 0;
-
if (Res == 0) {
// If not forward referenced or defined already, create the backing decl.
- Res = LabelDecl::Create(Context, CurContext, Loc, II, isLocalLabel);
- Scope *S = isLocalLabel ? CurScope : CurScope->getFnParent();
+ Res = LabelDecl::Create(Context, CurContext, Loc, II);
+ Scope *S = CurScope->getFnParent();
assert(S && "Not in a function?");
PushOnScopeChains(Res, S, true);
}
-
return cast<LabelDecl>(Res);
}
void ASTDeclReader::VisitLabelDecl(LabelDecl *D) {
VisitNamedDecl(D);
- bool IsGnuLocal = Record[Idx++];
- D->setGnuLocal(IsGnuLocal);
+ D->setLocStart(ReadSourceLocation(Record, Idx));
}
void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) {
VisitNamedDecl(D);
- Record.push_back(D->isGnuLocal());
+ Writer.AddSourceLocation(D->getLocStart(), Record);
Code = serialization::DECL_LABEL;
}