2011-05-02 06:35:37 +08:00
|
|
|
//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2011-05-02 06:35:37 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Scope class, which is used for recording
|
|
|
|
// information about a lexical scope.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/Sema/Scope.h"
|
2014-05-03 08:41:18 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
2014-03-05 16:57:59 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2011-05-02 06:35:37 +08:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2016-04-29 10:24:14 +08:00
|
|
|
void Scope::setFlags(Scope *parent, unsigned flags) {
|
2011-05-02 06:35:37 +08:00
|
|
|
AnyParent = parent;
|
|
|
|
Flags = flags;
|
2012-02-17 09:35:32 +08:00
|
|
|
|
|
|
|
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.
|
2014-05-26 14:22:03 +08:00
|
|
|
BreakParent = ContinueParent = nullptr;
|
2012-02-17 09:35:32 +08:00
|
|
|
}
|
|
|
|
|
2011-05-02 06:35:37 +08:00
|
|
|
if (parent) {
|
|
|
|
Depth = parent->Depth + 1;
|
|
|
|
PrototypeDepth = parent->PrototypeDepth;
|
|
|
|
PrototypeIndex = 0;
|
|
|
|
FnParent = parent->FnParent;
|
|
|
|
BlockParent = parent->BlockParent;
|
|
|
|
TemplateParamParent = parent->TemplateParamParent;
|
2015-03-20 05:54:30 +08:00
|
|
|
MSLastManglingParent = parent->MSLastManglingParent;
|
|
|
|
MSCurManglingNumber = getMSLastManglingNumber();
|
2014-06-03 18:16:47 +08:00
|
|
|
if ((Flags & (FnScope | ClassScope | BlockScope | TemplateParamScope |
|
|
|
|
FunctionPrototypeScope | AtCatchScope | ObjCMethodScope)) ==
|
|
|
|
0)
|
|
|
|
Flags |= parent->getFlags() & OpenMPSimdDirectiveScope;
|
2011-05-02 06:35:37 +08:00
|
|
|
} else {
|
|
|
|
Depth = 0;
|
|
|
|
PrototypeDepth = 0;
|
|
|
|
PrototypeIndex = 0;
|
2015-03-20 05:54:30 +08:00
|
|
|
MSLastManglingParent = FnParent = BlockParent = nullptr;
|
2014-05-26 14:22:03 +08:00
|
|
|
TemplateParamParent = nullptr;
|
2015-03-20 05:54:30 +08:00
|
|
|
MSLastManglingNumber = 1;
|
|
|
|
MSCurManglingNumber = 1;
|
2011-05-02 06:35:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If this scope is a function or contains breaks/continues, remember it.
|
|
|
|
if (flags & FnScope) FnParent = this;
|
2014-03-05 16:57:59 +08:00
|
|
|
// The MS mangler uses the number of scopes that can hold declarations as
|
|
|
|
// part of an external name.
|
|
|
|
if (Flags & (ClassScope | FnScope)) {
|
2015-03-20 05:54:30 +08:00
|
|
|
MSLastManglingNumber = getMSLastManglingNumber();
|
|
|
|
MSLastManglingParent = this;
|
|
|
|
MSCurManglingNumber = 1;
|
2014-03-05 16:57:59 +08:00
|
|
|
}
|
2011-05-02 06:35:37 +08:00
|
|
|
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++;
|
2014-06-17 08:00:18 +08:00
|
|
|
|
2014-03-05 16:57:59 +08:00
|
|
|
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.
|
2014-06-17 08:00:18 +08:00
|
|
|
else if ((flags & EnumScope))
|
|
|
|
; // Don't increment for enum scopes.
|
2014-03-05 16:57:59 +08:00
|
|
|
else
|
2015-03-20 05:54:30 +08:00
|
|
|
incrementMSManglingNumber();
|
2014-03-05 16:57:59 +08:00
|
|
|
}
|
2016-04-29 10:24:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void Scope::Init(Scope *parent, unsigned flags) {
|
|
|
|
setFlags(parent, flags);
|
2011-05-02 06:35:37 +08:00
|
|
|
|
|
|
|
DeclsInScope.clear();
|
|
|
|
UsingDirectives.clear();
|
2014-05-26 14:22:03 +08:00
|
|
|
Entity = nullptr;
|
2011-05-02 06:35:37 +08:00
|
|
|
ErrorTrap.reset();
|
2018-06-19 13:35:30 +08:00
|
|
|
NRVO.setPointerAndInt(nullptr, 0);
|
2011-05-02 06:35:37 +08:00
|
|
|
}
|
2012-02-29 18:24:19 +08:00
|
|
|
|
|
|
|
bool Scope::containedInPrototypeScope() const {
|
|
|
|
const Scope *S = this;
|
|
|
|
while (S) {
|
|
|
|
if (S->isFunctionPrototypeScope())
|
|
|
|
return true;
|
|
|
|
S = S->getParent();
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2014-01-23 23:05:00 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-06-19 13:35:30 +08:00
|
|
|
void Scope::mergeNRVOIntoParent() {
|
|
|
|
if (VarDecl *Candidate = NRVO.getPointer()) {
|
|
|
|
if (isDeclScope(Candidate))
|
|
|
|
Candidate->setNRVOVariable(true);
|
2014-05-03 08:41:18 +08:00
|
|
|
}
|
|
|
|
|
2018-06-19 13:35:30 +08:00
|
|
|
if (getEntity())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (NRVO.getInt())
|
|
|
|
getParent()->setNoNRVO();
|
|
|
|
else if (NRVO.getPointer())
|
|
|
|
getParent()->addNRVOCandidate(NRVO.getPointer());
|
2014-05-03 08:41:18 +08:00
|
|
|
}
|
|
|
|
|
2016-01-30 03:38:18 +08:00
|
|
|
LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); }
|
2014-03-05 16:57:59 +08:00
|
|
|
|
|
|
|
void Scope::dumpImpl(raw_ostream &OS) const {
|
|
|
|
unsigned Flags = getFlags();
|
|
|
|
bool HasFlags = Flags != 0;
|
|
|
|
|
|
|
|
if (HasFlags)
|
|
|
|
OS << "Flags: ";
|
|
|
|
|
2018-01-18 12:28:56 +08:00
|
|
|
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"},
|
Un-revert "[coroutines][PR40978] Emit error for co_yield within catch block"
Summary:
https://reviews.llvm.org/D59076 added a new coroutine error that
prevented users from using 'co_await' or 'co_yield' within a exception
handler. However, it was reverted in https://reviews.llvm.org/rC356774
because it caused a regression in nested scopes in C++ catch statements,
as documented by https://bugs.llvm.org/show_bug.cgi?id=41171.
The issue was due to an incorrect use of a `clang::ParseScope`. To fix:
1. Add a regression test for catch statement parsing that mimics the bug
report from https://bugs.llvm.org/show_bug.cgi?id=41171.
2. Re-apply the coroutines error patch from
https://reviews.llvm.org/D59076, but this time with the correct
ParseScope behavior.
Reviewers: GorNishanov, tks2103, rsmith, riccibruno, jbulow
Reviewed By: riccibruno
Subscribers: EricWF, jdoerfert, lewissbaker, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59752
llvm-svn: 356865
2019-03-25 08:53:10 +08:00
|
|
|
{ClassInheritanceScope, "ClassInheritanceScope"},
|
|
|
|
{CatchScope, "CatchScope"},
|
|
|
|
};
|
2018-01-18 12:28:56 +08:00
|
|
|
|
|
|
|
for (auto Info : FlagInfo) {
|
|
|
|
if (Flags & Info.first) {
|
|
|
|
OS << Info.second;
|
|
|
|
Flags &= ~Info.first;
|
|
|
|
if (Flags)
|
|
|
|
OS << " | ";
|
2014-03-05 16:57:59 +08:00
|
|
|
}
|
|
|
|
}
|
2018-01-18 12:28:56 +08:00
|
|
|
|
|
|
|
assert(Flags == 0 && "Unknown scope flags");
|
|
|
|
|
2014-03-05 16:57:59 +08:00
|
|
|
if (HasFlags)
|
|
|
|
OS << '\n';
|
|
|
|
|
|
|
|
if (const Scope *Parent = getParent())
|
|
|
|
OS << "Parent: (clang::Scope*)" << Parent << '\n';
|
|
|
|
|
|
|
|
OS << "Depth: " << Depth << '\n';
|
2015-03-20 05:54:30 +08:00
|
|
|
OS << "MSLastManglingNumber: " << getMSLastManglingNumber() << '\n';
|
|
|
|
OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n';
|
2014-03-05 16:57:59 +08:00
|
|
|
if (const DeclContext *DC = getEntity())
|
|
|
|
OS << "Entity : (clang::DeclContext*)" << DC << '\n';
|
2018-06-19 13:35:30 +08:00
|
|
|
|
|
|
|
if (NRVO.getInt())
|
|
|
|
OS << "NRVO not allowed\n";
|
|
|
|
else if (NRVO.getPointer())
|
|
|
|
OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n';
|
2014-03-05 16:57:59 +08:00
|
|
|
}
|