diff options
author | dim <dim@FreeBSD.org> | 2011-02-27 01:32:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2011-02-27 01:32:10 +0000 |
commit | b951d621be1d00a520871c689c1cd687b6aa3ae6 (patch) | |
tree | 5c342f2374324ffec4626f558d9aa49f323f90b4 /contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp | |
parent | 4004d6a3076e94bd23e681411c43682267a202fe (diff) | |
parent | a0fb00f9837bd0d2e5948f16f6a6b82a7a628f51 (diff) | |
download | FreeBSD-src-b951d621be1d00a520871c689c1cd687b6aa3ae6.zip FreeBSD-src-b951d621be1d00a520871c689c1cd687b6aa3ae6.tar.gz |
Update llvm/clang to trunk r126547.
There are several bugfixes in this update, but the most important one is
to ensure __start_ and __stop_ symbols for linker sets and kernel module
metadata are always emitted in object files:
http://llvm.org/bugs/show_bug.cgi?id=9292
Before this fix, if you compiled kernel modules with clang, they would
not be properly processed by kldxref, and if they had any dependencies,
the kernel would fail to load those. Another problem occurred when
attempting to mount a tmpfs filesystem, which would result in 'operation
not supported by device'.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp index bc289ec..037594a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -14,6 +14,9 @@ #include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TypeLoc.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/LangOptions.h" #include "llvm/ADT/STLExtras.h" @@ -44,6 +47,239 @@ void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { EndLocation = TemplateId->RAngleLoc; } +CXXScopeSpec::CXXScopeSpec(const CXXScopeSpec &Other) + : Range(Other.Range), ScopeRep(Other.ScopeRep), Buffer(0), + BufferSize(Other.BufferSize), BufferCapacity(Other.BufferSize) +{ + if (BufferSize) { + Buffer = static_cast<char *>(malloc(BufferSize)); + memcpy(Buffer, Other.Buffer, BufferSize); + } +} + +CXXScopeSpec &CXXScopeSpec::operator=(const CXXScopeSpec &Other) { + Range = Other.Range; + ScopeRep = Other.ScopeRep; + if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { + // Re-use our storage. + BufferSize = Other.BufferSize; + memcpy(Buffer, Other.Buffer, BufferSize); + return *this; + } + + if (BufferCapacity) + free(Buffer); + if (Other.Buffer) { + BufferSize = Other.BufferSize; + BufferCapacity = BufferSize; + Buffer = static_cast<char *>(malloc(BufferSize)); + memcpy(Buffer, Other.Buffer, BufferSize); + } else { + Buffer = 0; + BufferSize = 0; + BufferCapacity = 0; + } + return *this; +} + +CXXScopeSpec::~CXXScopeSpec() { + if (BufferCapacity) + free(Buffer); +} + +namespace { + void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, + unsigned &BufferCapacity) { + if (BufferSize + (End - Start) > BufferCapacity) { + // Reallocate the buffer. + unsigned NewCapacity + = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 + : sizeof(void*) * 2), + (unsigned)(BufferSize + (End - Start))); + char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); + memcpy(NewBuffer, Buffer, BufferSize); + + if (BufferCapacity) + free(Buffer); + Buffer = NewBuffer; + BufferCapacity = NewCapacity; + } + + memcpy(Buffer + BufferSize, Start, End - Start); + BufferSize += End-Start; + } + + /// \brief Save a source location to the given buffer. + void SaveSourceLocation(SourceLocation Loc, char *&Buffer, + unsigned &BufferSize, unsigned &BufferCapacity) { + unsigned Raw = Loc.getRawEncoding(); + Append(reinterpret_cast<char *>(&Raw), + reinterpret_cast<char *>(&Raw) + sizeof(unsigned), + Buffer, BufferSize, BufferCapacity); + } + + /// \brief Save a pointer to the given buffer. + void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, + unsigned &BufferCapacity) { + Append(reinterpret_cast<char *>(&Ptr), + reinterpret_cast<char *>(&Ptr) + sizeof(void *), + Buffer, BufferSize, BufferCapacity); + } +} +void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, + TypeLoc TL, SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, + TemplateKWLoc.isValid(), + TL.getTypePtr()); + if (Range.getBegin().isInvalid()) + Range.setBegin(TL.getBeginLoc()); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Identifier); + if (Range.getBegin().isInvalid()) + Range.setBegin(IdentifierLoc); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, + SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Namespace); + if (Range.getBegin().isInvalid()) + Range.setBegin(NamespaceLoc); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, + SourceLocation ColonColonLoc) { + ScopeRep = NestedNameSpecifier::Create(Context, ScopeRep, Alias); + if (Range.getBegin().isInvalid()) + Range.setBegin(AliasLoc); + Range.setEnd(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeGlobal(ASTContext &Context, + SourceLocation ColonColonLoc) { + assert(!ScopeRep && "Already have a nested-name-specifier!?"); + ScopeRep = NestedNameSpecifier::GlobalSpecifier(Context); + Range = SourceRange(ColonColonLoc); + + // Push source-location info into the buffer. + SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); + + assert(Range == NestedNameSpecifierLoc(ScopeRep, Buffer).getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeTrivial(ASTContext &Context, + NestedNameSpecifier *Qualifier, SourceRange R) { + ScopeRep = Qualifier; + Range = R; + + // Construct bogus (but well-formed) source information for the + // nested-name-specifier. + BufferSize = 0; + llvm::SmallVector<NestedNameSpecifier *, 4> Stack; + for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) + Stack.push_back(NNS); + while (!Stack.empty()) { + NestedNameSpecifier *NNS = Stack.back(); + Stack.pop_back(); + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + TypeSourceInfo *TSInfo + = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), + R.getBegin()); + SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, + BufferCapacity); + break; + } + + case NestedNameSpecifier::Global: + break; + } + + // Save the location of the '::'. + SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), + Buffer, BufferSize, BufferCapacity); + } +} + +void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { + if (!Other) { + Range = SourceRange(); + ScopeRep = 0; + return; + } + + if (BufferCapacity) + free(Buffer); + + // Rather than copying the data (which is wasteful), "adopt" the + // pointer (which points into the ASTContext) but set the capacity to zero to + // indicate that we don't own it. + Range = Other.getSourceRange(); + ScopeRep = Other.getNestedNameSpecifier(); + Buffer = static_cast<char *>(Other.getOpaqueData()); + BufferSize = Other.getDataLength(); + BufferCapacity = 0; +} + +NestedNameSpecifierLoc +CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { + if (isEmpty() || isInvalid()) + return NestedNameSpecifierLoc(); + + // If we adopted our data pointer from elsewhere in the AST context, there's + // no need to copy the memory. + if (BufferCapacity == 0) + return NestedNameSpecifierLoc(ScopeRep, Buffer); + + void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); + memcpy(Mem, Buffer, BufferSize); + return NestedNameSpecifierLoc(ScopeRep, Mem); +} + /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. DeclaratorChunk DeclaratorChunk::getFunction(const ParsedAttributes &attrs, |