201 lines
6.2 KiB
C++
201 lines
6.2 KiB
C++
|
//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// This file implements the Scope class, which is used for recording
|
||
|
// information about a lexical scope.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#include "clang/Sema/Scope.h"
|
||
|
#include "clang/AST/Decl.h"
|
||
|
#include "llvm/Support/raw_ostream.h"
|
||
|
|
||
|
using namespace clang;
|
||
|
|
||
|
void Scope::setFlags(Scope *parent, unsigned flags) {
|
||
|
AnyParent = parent;
|
||
|
Flags = flags;
|
||
|
|
||
|
if (parent && !(flags & FnScope)) {
|
||
|
BreakParent = parent->BreakParent;
|
||
|
ContinueParent = parent->ContinueParent;
|
||
|
} else {
|
||
|
// Control scopes do not contain the contents of nested function scopes for
|
||
|
// control flow purposes.
|
||
|
BreakParent = ContinueParent = nullptr;
|
||
|
}
|
||
|
|
||
|
if (parent) {
|
||
|
Depth = parent->Depth + 1;
|
||
|
PrototypeDepth = parent->PrototypeDepth;
|
||
|
PrototypeIndex = 0;
|
||
|
FnParent = parent->FnParent;
|
||
|
BlockParent = parent->BlockParent;
|
||
|
TemplateParamParent = parent->TemplateParamParent;
|
||
|
MSLastManglingParent = parent->MSLastManglingParent;
|
||
|
MSCurManglingNumber = getMSLastManglingNumber();
|
||
|
if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
|
||
|
FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
|
||
|
0)
|
||
|
Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
|
||
|
} else {
|
||
|
Depth = 0;
|
||
|
PrototypeDepth = 0;
|
||
|
PrototypeIndex = 0;
|
||
|
MSLastManglingParent = FnParent = BlockParent = nullptr;
|
||
|
TemplateParamParent = nullptr;
|
||
|
MSLastManglingNumber = 1;
|
||
|
MSCurManglingNumber = 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)) {
|
||
|
MSLastManglingNumber = getMSLastManglingNumber();
|
||
|
MSLastManglingParent = this;
|
||
|
MSCurManglingNumber = 1;
|
||
|
}
|
||
|
if (flags & BreakScope) BreakParent = this;
|
||
|
if (flags & ContinueScope) ContinueParent = this;
|
||
|
if (flags & BlockScope) BlockParent = this;
|
||
|
if (flags & TemplateParamScope) TemplateParamParent = this;
|
||
|
|
||
|
// 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 if ((flags & EnumScope))
|
||
|
; // Don't increment for enum scopes.
|
||
|
else
|
||
|
incrementMSManglingNumber();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Scope::Init(Scope *parent, unsigned flags) {
|
||
|
setFlags(parent, flags);
|
||
|
|
||
|
DeclsInScope.clear();
|
||
|
UsingDirectives.clear();
|
||
|
Entity = nullptr;
|
||
|
ErrorTrap.reset();
|
||
|
NRVO.setPointerAndInt(nullptr, 0);
|
||
|
}
|
||
|
|
||
|
bool Scope::containedInPrototypeScope() const {
|
||
|
const Scope *S = this;
|
||
|
while (S) {
|
||
|
if (S->isFunctionPrototypeScope())
|
||
|
return true;
|
||
|
S = S->getParent();
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void Scope::AddFlags(unsigned FlagsToSet) {
|
||
|
assert((FlagsToSet & ~(BreakScope | ContinueScope)) == 0 &&
|
||
|
"Unsupported scope flags");
|
||
|
if (FlagsToSet & BreakScope) {
|
||
|
assert((Flags & BreakScope) == 0 && "Already set");
|
||
|
BreakParent = this;
|
||
|
}
|
||
|
if (FlagsToSet & ContinueScope) {
|
||
|
assert((Flags & ContinueScope) == 0 && "Already set");
|
||
|
ContinueParent = this;
|
||
|
}
|
||
|
Flags |= FlagsToSet;
|
||
|
}
|
||
|
|
||
|
void Scope::mergeNRVOIntoParent() {
|
||
|
if (VarDecl *Candidate = NRVO.getPointer()) {
|
||
|
if (isDeclScope(Candidate))
|
||
|
Candidate->setNRVOVariable(true);
|
||
|
}
|
||
|
|
||
|
if (getEntity())
|
||
|
return;
|
||
|
|
||
|
if (NRVO.getInt())
|
||
|
getParent()->setNoNRVO();
|
||
|
else if (NRVO.getPointer())
|
||
|
getParent()->addNRVOCandidate(NRVO.getPointer());
|
||
|
}
|
||
|
|
||
|
LLVM_DUMP_METHOD 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: ";
|
||
|
|
||
|
std::pair<unsigned, const char *> FlagInfo[] = {
|
||
|
{FnScope, "FnScope"},
|
||
|
{BreakScope, "BreakScope"},
|
||
|
{ContinueScope, "ContinueScope"},
|
||
|
{DeclScope, "DeclScope"},
|
||
|
{ControlScope, "ControlScope"},
|
||
|
{ClassScope, "ClassScope"},
|
||
|
{BlockScope, "BlockScope"},
|
||
|
{TemplateParamScope, "TemplateParamScope"},
|
||
|
{FunctionPrototypeScope, "FunctionPrototypeScope"},
|
||
|
{FunctionDeclarationScope, "FunctionDeclarationScope"},
|
||
|
{AtCatchScope, "AtCatchScope"},
|
||
|
{ObjCMethodScope, "ObjCMethodScope"},
|
||
|
{SwitchScope, "SwitchScope"},
|
||
|
{TryScope, "TryScope"},
|
||
|
{FnTryCatchScope, "FnTryCatchScope"},
|
||
|
{OpenMPDirectiveScope, "OpenMPDirectiveScope"},
|
||
|
{OpenMPLoopDirectiveScope, "OpenMPLoopDirectiveScope"},
|
||
|
{OpenMPSimdDirectiveScope, "OpenMPSimdDirectiveScope"},
|
||
|
{EnumScope, "EnumScope"},
|
||
|
{SEHTryScope, "SEHTryScope"},
|
||
|
{SEHExceptScope, "SEHExceptScope"},
|
||
|
{SEHFilterScope, "SEHFilterScope"},
|
||
|
{CompoundStmtScope, "CompoundStmtScope"},
|
||
|
{ClassInheritanceScope, "ClassInheritanceScope"},
|
||
|
{CatchScope, "CatchScope"},
|
||
|
};
|
||
|
|
||
|
for (auto Info : FlagInfo) {
|
||
|
if (Flags & Info.first) {
|
||
|
OS << Info.second;
|
||
|
Flags &= ~Info.first;
|
||
|
if (Flags)
|
||
|
OS << " | ";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
assert(Flags == 0 && "Unknown scope flags");
|
||
|
|
||
|
if (HasFlags)
|
||
|
OS << '\n';
|
||
|
|
||
|
if (const Scope *Parent = getParent())
|
||
|
OS << "Parent: (clang::Scope*)" << Parent << '\n';
|
||
|
|
||
|
OS << "Depth: " << Depth << '\n';
|
||
|
OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
|
||
|
OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
|
||
|
if (const DeclContext *DC = getEntity())
|
||
|
OS << "Entity : (clang::DeclContext*)" << DC << '\n';
|
||
|
|
||
|
if (NRVO.getInt())
|
||
|
OS << "NRVO not allowed\n";
|
||
|
else if (NRVO.getPointer())
|
||
|
OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
|
||
|
}
|