Simplify CXXScopeSpec a lot. No more weird SmallVector-like hacks here

llvm-svn: 67800
This commit is contained in:
Douglas Gregor 2009-03-26 23:56:24 +00:00
parent f21eb49a04
commit c23500ebb3
8 changed files with 21 additions and 171 deletions

View File

@ -397,36 +397,10 @@ private:
/// specifier.
class CXXScopeSpec {
SourceRange Range;
/// Storage containing the scope representations for up to four
/// levels of nested-name-specifier. NumScopeReps specifiers how
/// many levels there are. If there are more than four, we use
/// ManyScopeReps.
Action::CXXScopeTy *InlineScopeReps[4];
/// The number of scope representations we've stored.
unsigned NumScopeReps;
/// The number of scope representations we can store without
/// allocating new memory.
unsigned Capacity;
// If there are > 4 scope representations, a pointer to those scope
// representations.
Action::CXXScopeTy **ManyScopeReps;
void reallocate();
void *ScopeRep;
public:
CXXScopeSpec() : Range(), NumScopeReps(0), Capacity(4) { }
CXXScopeSpec(const CXXScopeSpec &SS);
CXXScopeSpec &operator=(const CXXScopeSpec &SS);
~CXXScopeSpec() {
clear();
}
CXXScopeSpec() : Range(), ScopeRep() { }
const SourceRange &getRange() const { return Range; }
void setRange(const SourceRange &R) { Range = R; }
@ -435,82 +409,21 @@ public:
SourceLocation getBeginLoc() const { return Range.getBegin(); }
SourceLocation getEndLoc() const { return Range.getEnd(); }
typedef Action::CXXScopeTy * const * iterator;
iterator begin() const {
if (NumScopeReps > 4)
return ManyScopeReps;
else
return &InlineScopeReps[0];
}
iterator end() const {
return begin() + NumScopeReps;
}
Action::CXXScopeTy *getScopeRep(unsigned I) const {
assert(I < size() && "Out-of-range scope index");
return begin()[I];
}
unsigned size() const { return NumScopeReps; }
void addScopeRep(Action::CXXScopeTy *S) {
if (!S)
return;
if (NumScopeReps >= Capacity)
reallocate();
if (Capacity == 4)
InlineScopeReps[NumScopeReps++] = S;
else
ManyScopeReps[NumScopeReps++] = S;
}
Action::CXXScopeTy *getCurrentScopeRep() const {
if (size() == 0)
return 0;
return begin()[size() - 1];
}
void setScopeRep(Action::CXXScopeTy *S) {
if (Capacity > 4)
delete [] ManyScopeReps;
Capacity = 4;
NumScopeReps = 0;
addScopeRep(S);
}
Action::CXXScopeTy *getScopeRep() const { return ScopeRep; }
void setScopeRep(Action::CXXScopeTy *S) { ScopeRep = S; }
bool isEmpty() const { return !Range.isValid(); }
bool isNotEmpty() const { return !isEmpty(); }
/// isInvalid - An error occured during parsing of the scope specifier.
bool isInvalid() const { return isNotEmpty() && NumScopeReps == 0; }
bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; }
/// isSet - A scope specifier was resolved to a valid C++ scope.
bool isSet() const { return getCurrentScopeRep() != 0; }
bool isSet() const { return ScopeRep != 0; }
void clear() {
Range = SourceRange();
if (NumScopeReps > 4)
delete [] ManyScopeReps;
NumScopeReps = 0;
Capacity = 4;
}
/// \brief Allocate and build the information that will be attached
/// to a scope-annotation token.
void *buildAnnotationData() const;
/// \brief Reconstruct a scope specifier from the annotation data.
///
/// This routine does not free the annotation data; call
/// freeAnnotationData for that.
void setFromAnnotationData(void *Data);
/// Frees the annotation data.
static void freeAnnotationData(void *Data) {
delete [] (uintptr_t *) Data;
ScopeRep = 0;
}
};

View File

@ -24,67 +24,6 @@ static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc,
return D.Report(FullSourceLoc(Loc, SrcMgr), DiagID);
}
/// \brief Double the capacity of this scope specifier.
void CXXScopeSpec::reallocate() {
Action::CXXScopeTy **Data = new Action::CXXScopeTy *[Capacity * 2];
Action::CXXScopeTy **From
= Capacity == 4? &InlineScopeReps[0] : ManyScopeReps;
std::memcpy(Data, From, Capacity * sizeof(Action::CXXScopeTy *));
if (Capacity > 4)
delete [] ManyScopeReps;
ManyScopeReps = Data;
Capacity *= 2;
}
CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &SS)
: Range(SS.Range), NumScopeReps(SS.NumScopeReps), Capacity(SS.Capacity) {
if (Capacity > 4) {
ManyScopeReps = new Action::CXXScopeTy *[Capacity];
memcpy(ManyScopeReps, SS.ManyScopeReps,
Capacity * sizeof(Action::CXXScopeTy *));
} else {
memcpy(InlineScopeReps, SS.InlineScopeReps,
Capacity * sizeof(Action::CXXScopeTy *));
}
}
CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &SS) {
// FIXME: Does not provide the strong exception safety guarantee.
this->~CXXScopeSpec();
new (this) CXXScopeSpec(SS);
return *this;
}
void *CXXScopeSpec::buildAnnotationData() const {
uintptr_t *Data = (uintptr_t *)malloc(sizeof(uintptr_t) * (size() + 1));
Data[0] = size();
for (unsigned I = 0; I < size(); ++I)
Data[I + 1] = reinterpret_cast<uintptr_t>(getScopeRep(I));
return Data;
}
void CXXScopeSpec::setFromAnnotationData(void *DataIn) {
uintptr_t *Data = static_cast<uintptr_t *>(DataIn);
NumScopeReps = *Data;
// Allocate enough space for the annotation data.
if (NumScopeReps > Capacity) {
if (Capacity > 4)
delete [] ManyScopeReps;
Capacity = NumScopeReps;
ManyScopeReps = new Action::CXXScopeTy *[Capacity];
}
if (Capacity > 4)
std::memcpy(ManyScopeReps, Data + 1, sizeof(uintptr_t) * NumScopeReps);
else
std::memcpy(InlineScopeReps, Data + 1, sizeof(uintptr_t) * NumScopeReps);
}
/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function.
/// "TheDeclarator" is the declarator that this will be added to.
DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,

View File

@ -515,7 +515,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
goto DoneWithDeclSpec;
CXXScopeSpec SS;
SS.setFromAnnotationData(Tok.getAnnotationValue());
SS.setScopeRep(Tok.getAnnotationValue());
SS.setRange(Tok.getAnnotationRange());
// If the next token is the name of the class type that the C++ scope
@ -532,7 +532,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
if (TypeRep == 0)
goto DoneWithDeclSpec;
CXXScopeSpec::freeAnnotationData(Tok.getAnnotationValue());
ConsumeToken(); // The C++ scope.
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,

View File

@ -36,8 +36,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
"Call sites of this function should be guarded by checking for C++");
if (Tok.is(tok::annot_cxxscope)) {
SS.setFromAnnotationData(Tok.getAnnotationValue());
CXXScopeSpec::freeAnnotationData(Tok.getAnnotationValue());
SS.setScopeRep(Tok.getAnnotationValue());
SS.setRange(Tok.getAnnotationRange());
ConsumeToken();
return true;
@ -54,7 +53,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
// '::' - Global scope qualifier.
SourceLocation CCLoc = ConsumeToken();
SS.setBeginLoc(CCLoc);
SS.addScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
SS.setEndLoc(CCLoc);
HasScopeSpecifier = true;
}
@ -80,7 +79,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
if (SS.isInvalid())
continue;
SS.addScopeRep(
SS.setScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
SS.setEndLoc(CCLoc);
continue;
@ -165,7 +164,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
HasScopeSpecifier = true;
}
SS.addScopeRep(
SS.setScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
TypeToken.getAnnotationValue(),
TypeToken.getAnnotationRange(),

View File

@ -866,7 +866,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
Tok.setAnnotationValue(SS.buildAnnotationData());
Tok.setAnnotationValue(SS.getScopeRep());
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them with the
@ -898,7 +898,7 @@ bool Parser::TryAnnotateCXXScopeToken() {
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
Tok.setAnnotationValue(SS.buildAnnotationData());
Tok.setAnnotationValue(SS.getScopeRep());
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them with the

View File

@ -25,7 +25,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS) {
return 0;
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
if (NNS->isDependent())
return 0;
@ -57,7 +57,7 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) {
return false;
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
return NNS->isDependent();
}
@ -111,7 +111,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
SourceLocation CCLoc,
IdentifierInfo &II) {
NestedNameSpecifier *Prefix
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
// If the prefix is already dependent, there is no name lookup to
// perform. Just build the resulting nested-name-specifier.
@ -173,7 +173,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
SourceRange TypeRange,
SourceLocation CCLoc) {
NestedNameSpecifier *Prefix
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false,
QualType::getFromOpaquePtr(Ty).getTypePtr());
}

View File

@ -442,7 +442,7 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
if (SS && !SS->isEmpty()) {
return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
ValueDependent, SS->getRange(),
static_cast<NestedNameSpecifier *>(SS->getCurrentScopeRep()));
static_cast<NestedNameSpecifier *>(SS->getScopeRep()));
} else
return new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
}
@ -617,7 +617,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
if (SS && isDependentScopeSpecifier(*SS)) {
return Owned(new (Context) UnresolvedDeclRefExpr(Name, Context.DependentTy,
Loc, SS->getRange(),
static_cast<NestedNameSpecifier *>(SS->getCurrentScopeRep())));
static_cast<NestedNameSpecifier *>(SS->getScopeRep())));
}
LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName,

View File

@ -1102,6 +1102,6 @@ QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) {
return T;
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep());
= static_cast<NestedNameSpecifier *>(SS.getScopeRep());
return Context.getQualifiedNameType(NNS, T);
}