summaryrefslogtreecommitdiffstats
path: root/lib/Sema/Scope.cpp
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-03-05 08:57:59 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-03-05 08:57:59 +0000
commitadb19e62bb227aa5ba8eac89731f54f3007ab8fb (patch)
tree6feb3afef5cdb2b0c006d6a8488adfe1c26f7207 /lib/Sema/Scope.cpp
parent9d33e30aba42a968017b1bfe51951337322f06eb (diff)
[-cxx-abi microsoft] Implement local manglings accurately
Summary: The MSVC ABI appears to mangle the lexical scope into the names of statics. Specifically, a counter is incremented whenever a scope is entered where things can be declared in such a way that an ambiguity can arise. For example, a class scope inside of a class scope doesn't do anything interesting because the nested class cannot collide with another nested class. There are problems with this scheme: - It is unreliable. The counter is only incremented when a previously never encountered scope is entered. There are cases where this will cause ambiguity amongst declarations that have the same name where one was introduced in a deep scope while the other was introduced right after in the previous lexical scope. - It is wasteful. Statements like: {{{{{{{ static int foo = a; }}}}}}} will make the mangling of "foo" larger than it need be because the scope counter has been incremented many times. Because of these problems, and practical implementation concerns. We choose not to implement this scheme if the local static or local type isn't visible. The mangling of these declarations will look very similar but the numbering will make far more sense, this scheme is lifted from the Itanium ABI implementation. Reviewers: rsmith, doug.gregor, rnk, eli.friedman, cdavis5x Reviewed By: rnk CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D2953 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@202951 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/Scope.cpp')
-rw-r--r--lib/Sema/Scope.cpp95
1 files changed, 94 insertions, 1 deletions
diff --git a/lib/Sema/Scope.cpp b/lib/Sema/Scope.cpp
index eef55d3194..494768d66a 100644
--- a/lib/Sema/Scope.cpp
+++ b/lib/Sema/Scope.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/Scope.h"
+#include "llvm/Support/raw_ostream.h"
using namespace clang;
@@ -36,16 +37,24 @@ void Scope::Init(Scope *parent, unsigned flags) {
FnParent = parent->FnParent;
BlockParent = parent->BlockParent;
TemplateParamParent = parent->TemplateParamParent;
+ MSLocalManglingParent = parent->MSLocalManglingParent;
} else {
Depth = 0;
PrototypeDepth = 0;
PrototypeIndex = 0;
- FnParent = BlockParent = 0;
+ MSLocalManglingParent = FnParent = BlockParent = 0;
TemplateParamParent = 0;
+ MSLocalManglingNumber = 1;
}
// If this scope is a function or contains breaks/continues, remember it.
if (flags & FnScope) FnParent = this;
+ // The MS mangler uses the number of scopes that can hold declarations as
+ // part of an external name.
+ if (Flags & (ClassScope | FnScope)) {
+ MSLocalManglingNumber = getMSLocalManglingNumber();
+ MSLocalManglingParent = this;
+ }
if (flags & BreakScope) BreakParent = this;
if (flags & ContinueScope) ContinueParent = this;
if (flags & BlockScope) BlockParent = this;
@@ -53,6 +62,16 @@ void Scope::Init(Scope *parent, unsigned flags) {
// If this is a prototype scope, record that.
if (flags & FunctionPrototypeScope) PrototypeDepth++;
+ if (flags & DeclScope) {
+ if (flags & FunctionPrototypeScope)
+ ; // Prototype scopes are uninteresting.
+ else if ((flags & ClassScope) && getParent()->isClassScope())
+ ; // Nested class scopes aren't ambiguous.
+ else if ((flags & ClassScope) && getParent()->getFlags() == DeclScope)
+ ; // Classes inside of namespaces aren't ambiguous.
+ else
+ incrementMSLocalManglingNumber();
+ }
DeclsInScope.clear();
UsingDirectives.clear();
@@ -84,3 +103,77 @@ void Scope::AddFlags(unsigned FlagsToSet) {
Flags |= FlagsToSet;
}
+void Scope::dump() const { dumpImpl(llvm::errs()); }
+
+void Scope::dumpImpl(raw_ostream &OS) const {
+ unsigned Flags = getFlags();
+ bool HasFlags = Flags != 0;
+
+ if (HasFlags)
+ OS << "Flags: ";
+
+ while (Flags) {
+ if (Flags & FnScope) {
+ OS << "FnScope";
+ Flags &= ~FnScope;
+ } else if (Flags & BreakScope) {
+ OS << "BreakScope";
+ Flags &= ~BreakScope;
+ } else if (Flags & ContinueScope) {
+ OS << "ContinueScope";
+ Flags &= ~ContinueScope;
+ } else if (Flags & DeclScope) {
+ OS << "DeclScope";
+ Flags &= ~DeclScope;
+ } else if (Flags & ControlScope) {
+ OS << "ControlScope";
+ Flags &= ~ControlScope;
+ } else if (Flags & ClassScope) {
+ OS << "ClassScope";
+ Flags &= ~ClassScope;
+ } else if (Flags & BlockScope) {
+ OS << "BlockScope";
+ Flags &= ~BlockScope;
+ } else if (Flags & TemplateParamScope) {
+ OS << "TemplateParamScope";
+ Flags &= ~TemplateParamScope;
+ } else if (Flags & FunctionPrototypeScope) {
+ OS << "FunctionPrototypeScope";
+ Flags &= ~FunctionPrototypeScope;
+ } else if (Flags & FunctionDeclarationScope) {
+ OS << "FunctionDeclarationScope";
+ Flags &= ~FunctionDeclarationScope;
+ } else if (Flags & AtCatchScope) {
+ OS << "AtCatchScope";
+ Flags &= ~AtCatchScope;
+ } else if (Flags & ObjCMethodScope) {
+ OS << "ObjCMethodScope";
+ Flags &= ~ObjCMethodScope;
+ } else if (Flags & SwitchScope) {
+ OS << "SwitchScope";
+ Flags &= ~SwitchScope;
+ } else if (Flags & TryScope) {
+ OS << "TryScope";
+ Flags &= ~TryScope;
+ } else if (Flags & FnTryCatchScope) {
+ OS << "FnTryCatchScope";
+ Flags &= ~FnTryCatchScope;
+ } else if (Flags & OpenMPDirectiveScope) {
+ OS << "OpenMPDirectiveScope";
+ Flags &= ~OpenMPDirectiveScope;
+ }
+
+ if (Flags)
+ OS << " | ";
+ }
+ if (HasFlags)
+ OS << '\n';
+
+ if (const Scope *Parent = getParent())
+ OS << "Parent: (clang::Scope*)" << Parent << '\n';
+
+ OS << "Depth: " << Depth << '\n';
+ OS << "MSLocalManglingNumber: " << getMSLocalManglingNumber() << '\n';
+ if (const DeclContext *DC = getEntity())
+ OS << "Entity : (clang::DeclContext*)" << DC << '\n';
+}