Introduce a representation for types that we referred to via a
qualified name, e.g.,
foo::x
so that we retain the nested-name-specifier as written in the source
code and can reproduce that qualified name when printing the types
back (e.g., in diagnostics). This is PR3493, which won't be complete
until finished the other tasks mentioned near the end of this commit.
The parser's representation of nested-name-specifiers, CXXScopeSpec,
is now a bit fatter, because it needs to contain the scopes that
precede each '::' and keep track of whether the global scoping
operator '::' was at the beginning. For example, we need to keep track
of the leading '::', 'foo', and 'bar' in
::foo::bar::x
The Action's CXXScopeTy * is no longer a DeclContext *. It's now the
opaque version of the new NestedNameSpecifier, which contains a single
component of a nested-name-specifier (either a DeclContext * or a Type
*, bitmangled).
The new sugar type QualifiedNameType composes a sequence of
NestedNameSpecifiers with a representation of the type we're actually
referring to. At present, we only build QualifiedNameType nodes within
Sema::getTypeName. This will be extended to other type-constructing
actions (e.g., ActOnClassTemplateId).
Also on the way: QualifiedDeclRefExprs will also store a sequence of
NestedNameSpecifiers, so that we can print out the property
nested-name-specifier. I expect to also use this for handling
dependent names like Fibonacci<I - 1>::value.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67265 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index a498182..72ac311 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
+#include <cstring>
using namespace clang;
@@ -23,6 +24,66 @@
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.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 25565e6..0dddfdf 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -491,7 +491,7 @@
goto DoneWithDeclSpec;
CXXScopeSpec SS;
- SS.setScopeRep(Tok.getAnnotationValue());
+ SS.setFromAnnotationData(Tok.getAnnotationValue());
SS.setRange(Tok.getAnnotationRange());
// If the next token is the name of the class type that the C++ scope
@@ -508,7 +508,8 @@
if (TypeRep == 0)
goto DoneWithDeclSpec;
-
+
+ CXXScopeSpec::freeAnnotationData(Tok.getAnnotationValue());
ConsumeToken(); // The C++ scope.
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index e1b5db9..731f4c7 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -36,7 +36,8 @@
"Call sites of this function should be guarded by checking for C++");
if (Tok.is(tok::annot_cxxscope)) {
- SS.setScopeRep(Tok.getAnnotationValue());
+ SS.setFromAnnotationData(Tok.getAnnotationValue());
+ CXXScopeSpec::freeAnnotationData(Tok.getAnnotationValue());
SS.setRange(Tok.getAnnotationRange());
ConsumeToken();
return true;
@@ -53,7 +54,7 @@
// '::' - Global scope qualifier.
SourceLocation CCLoc = ConsumeToken();
SS.setBeginLoc(CCLoc);
- SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
+ SS.addScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
SS.setEndLoc(CCLoc);
HasScopeSpecifier = true;
}
@@ -79,7 +80,7 @@
if (SS.isInvalid())
continue;
- SS.setScopeRep(
+ SS.addScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
SS.setEndLoc(CCLoc);
continue;
@@ -149,7 +150,7 @@
if (TemplateId->Kind == TNK_Class_template) {
if (AnnotateTemplateIdTokenAsType(&SS))
- SS.setScopeRep(0);
+ SS.clear();
assert(Tok.is(tok::annot_typename) &&
"AnnotateTemplateIdTokenAsType isn't working");
@@ -164,7 +165,7 @@
HasScopeSpecifier = true;
}
- SS.setScopeRep(
+ SS.addScopeRep(
Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
TypeToken.getAnnotationValue(),
TypeToken.getAnnotationRange(),
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 5666051..8c3ff44 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -856,7 +856,7 @@
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
- Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationValue(SS.buildAnnotationData());
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them with the
@@ -888,7 +888,7 @@
else
PP.EnterToken(Tok);
Tok.setKind(tok::annot_cxxscope);
- Tok.setAnnotationValue(SS.getScopeRep());
+ Tok.setAnnotationValue(SS.buildAnnotationData());
Tok.setAnnotationRange(SS.getRange());
// In case the tokens were cached, have Preprocessor replace them with the