forked from OSchip/llvm-project
Split FunctionScopeInfo and BlockScopeInfo into their own header.
llvm-svn: 112038
This commit is contained in:
parent
cfe41db403
commit
aab3e41eb2
|
@ -0,0 +1,137 @@
|
|||
//===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines FunctionScopeInfo and BlockScopeInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H
|
||||
#define LLVM_CLANG_SEMA_SCOPE_INFO_H
|
||||
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class BlockDecl;
|
||||
class IdentifierInfo;
|
||||
class LabelStmt;
|
||||
class ReturnStmt;
|
||||
class Scope;
|
||||
class SwitchStmt;
|
||||
|
||||
namespace sema {
|
||||
|
||||
/// \brief Retains information about a function, method, or block that is
|
||||
/// currently being parsed.
|
||||
class FunctionScopeInfo {
|
||||
public:
|
||||
|
||||
/// \brief Whether this scope information structure defined information for
|
||||
/// a block.
|
||||
bool IsBlockInfo;
|
||||
|
||||
/// \brief Whether this function contains a VLA, @try, try, C++
|
||||
/// initializer, or anything else that can't be jumped past.
|
||||
bool HasBranchProtectedScope;
|
||||
|
||||
/// \brief Whether this function contains any switches or direct gotos.
|
||||
bool HasBranchIntoScope;
|
||||
|
||||
/// \brief Whether this function contains any indirect gotos.
|
||||
bool HasIndirectGoto;
|
||||
|
||||
/// \brief The number of errors that had occurred before starting this
|
||||
/// function or block.
|
||||
unsigned NumErrorsAtStartOfFunction;
|
||||
|
||||
/// LabelMap - This is a mapping from label identifiers to the LabelStmt for
|
||||
/// it (which acts like the label decl in some ways). Forward referenced
|
||||
/// labels have a LabelStmt created for them with a null location & SubStmt.
|
||||
llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
|
||||
|
||||
/// SwitchStack - This is the current set of active switch statements in the
|
||||
/// block.
|
||||
llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
|
||||
|
||||
/// \brief The list of return statements that occur within the function or
|
||||
/// block, if there is any chance of applying the named return value
|
||||
/// optimization.
|
||||
llvm::SmallVector<ReturnStmt *, 4> Returns;
|
||||
|
||||
void setHasBranchIntoScope() {
|
||||
HasBranchIntoScope = true;
|
||||
}
|
||||
|
||||
void setHasBranchProtectedScope() {
|
||||
HasBranchProtectedScope = true;
|
||||
}
|
||||
|
||||
void setHasIndirectGoto() {
|
||||
HasIndirectGoto = true;
|
||||
}
|
||||
|
||||
bool NeedsScopeChecking() const {
|
||||
return HasIndirectGoto ||
|
||||
(HasBranchProtectedScope && HasBranchIntoScope);
|
||||
}
|
||||
|
||||
FunctionScopeInfo(unsigned NumErrors)
|
||||
: IsBlockInfo(false),
|
||||
HasBranchProtectedScope(false),
|
||||
HasBranchIntoScope(false),
|
||||
HasIndirectGoto(false),
|
||||
NumErrorsAtStartOfFunction(NumErrors) { }
|
||||
|
||||
virtual ~FunctionScopeInfo();
|
||||
|
||||
/// \brief Clear out the information in this function scope, making it
|
||||
/// suitable for reuse.
|
||||
void Clear(unsigned NumErrors);
|
||||
|
||||
static bool classof(const FunctionScopeInfo *FSI) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Retains information about a block that is currently being parsed.
|
||||
class BlockScopeInfo : public FunctionScopeInfo {
|
||||
public:
|
||||
bool hasBlockDeclRefExprs;
|
||||
|
||||
BlockDecl *TheDecl;
|
||||
|
||||
/// TheScope - This is the scope for the block itself, which contains
|
||||
/// arguments etc.
|
||||
Scope *TheScope;
|
||||
|
||||
/// ReturnType - The return type of the block, or null if the block
|
||||
/// signature didn't provide an explicit return type.
|
||||
QualType ReturnType;
|
||||
|
||||
/// BlockType - The function type of the block, if one was given.
|
||||
/// Its return type may be BuiltinType::Dependent.
|
||||
QualType FunctionType;
|
||||
|
||||
BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block)
|
||||
: FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false),
|
||||
TheDecl(Block), TheScope(BlockScope)
|
||||
{
|
||||
IsBlockInfo = true;
|
||||
}
|
||||
|
||||
virtual ~BlockScopeInfo();
|
||||
|
||||
static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
|
||||
static bool classof(const BlockScopeInfo *BSI) { return true; }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -121,97 +121,11 @@ namespace clang {
|
|||
|
||||
namespace sema {
|
||||
class AccessedEntity;
|
||||
class BlockScopeInfo;
|
||||
class FunctionScopeInfo;
|
||||
class TemplateDeductionInfo;
|
||||
}
|
||||
|
||||
/// \brief Retains information about a function, method, or block that is
|
||||
/// currently being parsed.
|
||||
struct FunctionScopeInfo {
|
||||
/// \brief Whether this scope information structure defined information for
|
||||
/// a block.
|
||||
bool IsBlockInfo;
|
||||
|
||||
/// \brief Whether this function contains a VLA, @try, try, C++
|
||||
/// initializer, or anything else that can't be jumped past.
|
||||
bool HasBranchProtectedScope;
|
||||
|
||||
/// \brief Whether this function contains any switches or direct gotos.
|
||||
bool HasBranchIntoScope;
|
||||
|
||||
/// \brief Whether this function contains any indirect gotos.
|
||||
bool HasIndirectGoto;
|
||||
|
||||
/// \brief The number of errors that had occurred before starting this
|
||||
/// function or block.
|
||||
unsigned NumErrorsAtStartOfFunction;
|
||||
|
||||
/// LabelMap - This is a mapping from label identifiers to the LabelStmt for
|
||||
/// it (which acts like the label decl in some ways). Forward referenced
|
||||
/// labels have a LabelStmt created for them with a null location & SubStmt.
|
||||
llvm::DenseMap<IdentifierInfo*, LabelStmt*> LabelMap;
|
||||
|
||||
/// SwitchStack - This is the current set of active switch statements in the
|
||||
/// block.
|
||||
llvm::SmallVector<SwitchStmt*, 8> SwitchStack;
|
||||
|
||||
/// \brief The list of return statements that occur within the function or
|
||||
/// block, if there is any chance of applying the named return value
|
||||
/// optimization.
|
||||
llvm::SmallVector<ReturnStmt *, 4> Returns;
|
||||
|
||||
bool NeedsScopeChecking() const {
|
||||
return HasIndirectGoto ||
|
||||
(HasBranchProtectedScope && HasBranchIntoScope);
|
||||
}
|
||||
|
||||
FunctionScopeInfo(unsigned NumErrors)
|
||||
: IsBlockInfo(false),
|
||||
HasBranchProtectedScope(false),
|
||||
HasBranchIntoScope(false),
|
||||
HasIndirectGoto(false),
|
||||
NumErrorsAtStartOfFunction(NumErrors) { }
|
||||
|
||||
virtual ~FunctionScopeInfo();
|
||||
|
||||
/// \brief Clear out the information in this function scope, making it
|
||||
/// suitable for reuse.
|
||||
void Clear(unsigned NumErrors);
|
||||
|
||||
static bool classof(const FunctionScopeInfo *FSI) { return true; }
|
||||
};
|
||||
|
||||
|
||||
/// \brief Retains information about a block that is currently being parsed.
|
||||
struct BlockScopeInfo : FunctionScopeInfo {
|
||||
bool hasBlockDeclRefExprs;
|
||||
|
||||
BlockDecl *TheDecl;
|
||||
|
||||
/// TheScope - This is the scope for the block itself, which contains
|
||||
/// arguments etc.
|
||||
Scope *TheScope;
|
||||
|
||||
/// ReturnType - The return type of the block, or null if the block
|
||||
/// signature didn't provide an explicit return type.
|
||||
QualType ReturnType;
|
||||
|
||||
/// BlockType - The function type of the block, if one was given.
|
||||
/// Its return type may be BuiltinType::Dependent.
|
||||
QualType FunctionType;
|
||||
|
||||
BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block)
|
||||
: FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false),
|
||||
TheDecl(Block), TheScope(BlockScope)
|
||||
{
|
||||
IsBlockInfo = true;
|
||||
}
|
||||
|
||||
virtual ~BlockScopeInfo();
|
||||
|
||||
static bool classof(const FunctionScopeInfo *FSI) { return FSI->IsBlockInfo; }
|
||||
static bool classof(const BlockScopeInfo *BSI) { return true; }
|
||||
};
|
||||
|
||||
/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator
|
||||
/// parsing.
|
||||
///
|
||||
|
@ -303,16 +217,11 @@ public:
|
|||
/// VisContext - Manages the stack for #pragma GCC visibility.
|
||||
void *VisContext; // Really a "PragmaVisStack*"
|
||||
|
||||
/// \brief Stack containing information about each of the nested function,
|
||||
/// block, and method scopes that are currently active.
|
||||
llvm::SmallVector<FunctionScopeInfo *, 4> FunctionScopes;
|
||||
|
||||
/// \brief Cached function scope object used for the top function scope
|
||||
/// and when there is no function scope (in error cases).
|
||||
/// \brief Stack containing information about each of the nested
|
||||
/// function, block, and method scopes that are currently active.
|
||||
///
|
||||
/// This should never be accessed directly; rather, its address will
|
||||
/// be pushed into \c FunctionScopes when we want to re-use it.
|
||||
FunctionScopeInfo TopFunctionScope;
|
||||
/// This array is never empty, but the first element is meaningless.
|
||||
llvm::SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
|
||||
|
||||
/// ExprTemporaries - This is the stack of temporaries that are created by
|
||||
/// the current full expression.
|
||||
|
@ -727,52 +636,14 @@ public:
|
|||
void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
|
||||
void PopFunctionOrBlockScope();
|
||||
|
||||
/// getLabelMap() - Return the current label map. If we're in a block, we
|
||||
/// return it.
|
||||
llvm::DenseMap<IdentifierInfo*, LabelStmt*> &getLabelMap() {
|
||||
if (FunctionScopes.empty())
|
||||
return TopFunctionScope.LabelMap;
|
||||
|
||||
return FunctionScopes.back()->LabelMap;
|
||||
sema::FunctionScopeInfo *getCurFunction() const {
|
||||
return FunctionScopes.back();
|
||||
}
|
||||
|
||||
/// getSwitchStack - This is returns the switch stack for the current block or
|
||||
/// function.
|
||||
llvm::SmallVector<SwitchStmt*,8> &getSwitchStack() {
|
||||
if (FunctionScopes.empty())
|
||||
return TopFunctionScope.SwitchStack;
|
||||
|
||||
return FunctionScopes.back()->SwitchStack;
|
||||
}
|
||||
|
||||
/// \brief Determine whether the current function or block needs scope
|
||||
/// checking.
|
||||
bool FunctionNeedsScopeChecking() {
|
||||
if (!FunctionScopes.empty())
|
||||
return FunctionScopes.back()->NeedsScopeChecking();
|
||||
return false;
|
||||
}
|
||||
|
||||
void setFunctionHasBranchIntoScope() {
|
||||
if (!FunctionScopes.empty())
|
||||
FunctionScopes.back()->HasBranchIntoScope = true;
|
||||
}
|
||||
|
||||
void setFunctionHasBranchProtectedScope() {
|
||||
if (!FunctionScopes.empty())
|
||||
FunctionScopes.back()->HasBranchProtectedScope = true;
|
||||
}
|
||||
|
||||
void setFunctionHasIndirectGoto() {
|
||||
if (!FunctionScopes.empty())
|
||||
FunctionScopes.back()->HasIndirectGoto = true;
|
||||
}
|
||||
|
||||
|
||||
bool hasAnyErrorsInThisFunction() const;
|
||||
|
||||
/// \brief Retrieve the current block, if any.
|
||||
BlockScopeInfo *getCurBlock();
|
||||
sema::BlockScopeInfo *getCurBlock();
|
||||
|
||||
/// WeakTopLevelDeclDecls - access to #pragma weak-generated Decls
|
||||
llvm::SmallVector<Decl*,2> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "clang/Sema/CXXFieldCollector.h"
|
||||
#include "clang/Sema/ExternalSemaSource.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/SemaConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTDiagnostic.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "clang/Basic/PartialDiagnostic.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
FunctionScopeInfo::~FunctionScopeInfo() { }
|
||||
|
||||
|
@ -129,7 +131,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
|||
LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
|
||||
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
|
||||
ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0),
|
||||
PackContext(0), VisContext(0), TopFunctionScope(0), ParsingDeclDepth(0),
|
||||
PackContext(0), VisContext(0), ParsingDeclDepth(0),
|
||||
IdResolver(pp.getLangOptions()), GlobalNewDeleteDeclared(false),
|
||||
CompleteTranslationUnit(CompleteTranslationUnit),
|
||||
NumSFINAEErrors(0), SuppressAccessChecking(false),
|
||||
|
@ -146,6 +148,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
|
|||
|
||||
ExprEvalContexts.push_back(
|
||||
ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0));
|
||||
|
||||
FunctionScopes.push_back(new FunctionScopeInfo(Diags.getNumErrors()));
|
||||
}
|
||||
|
||||
void Sema::Initialize() {
|
||||
|
@ -166,8 +170,12 @@ Sema::~Sema() {
|
|||
if (PackContext) FreePackedContext();
|
||||
if (VisContext) FreeVisContext();
|
||||
delete TheTargetAttributesSema;
|
||||
while (!FunctionScopes.empty())
|
||||
PopFunctionOrBlockScope();
|
||||
|
||||
// Kill all the active scopes.
|
||||
for (unsigned I = 1, E = FunctionScopes.size(); I != E; ++I)
|
||||
delete FunctionScopes[I];
|
||||
if (FunctionScopes.size() == 1)
|
||||
delete FunctionScopes[0];
|
||||
|
||||
// Tell the SemaConsumer to forget about us; we're going out of scope.
|
||||
if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer))
|
||||
|
@ -510,11 +518,11 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) {
|
|||
|
||||
/// \brief Enter a new function scope
|
||||
void Sema::PushFunctionScope() {
|
||||
if (FunctionScopes.empty()) {
|
||||
// Use the "top" function scope rather than having to allocate memory for
|
||||
// a new scope.
|
||||
TopFunctionScope.Clear(getDiagnostics().getNumErrors());
|
||||
FunctionScopes.push_back(&TopFunctionScope);
|
||||
if (FunctionScopes.size() == 1) {
|
||||
// Use the "top" function scope rather than having to allocate
|
||||
// memory for a new scope.
|
||||
FunctionScopes.back()->Clear(getDiagnostics().getNumErrors());
|
||||
FunctionScopes.push_back(FunctionScopes.back());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -528,21 +536,17 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) {
|
|||
}
|
||||
|
||||
void Sema::PopFunctionOrBlockScope() {
|
||||
if (FunctionScopes.back() != &TopFunctionScope)
|
||||
delete FunctionScopes.back();
|
||||
else
|
||||
TopFunctionScope.Clear(getDiagnostics().getNumErrors());
|
||||
|
||||
FunctionScopes.pop_back();
|
||||
FunctionScopeInfo *Scope = FunctionScopes.pop_back_val();
|
||||
assert(!FunctionScopes.empty() && "mismatched push/pop!");
|
||||
if (FunctionScopes.back() != Scope)
|
||||
delete Scope;
|
||||
}
|
||||
|
||||
/// \brief Determine whether any errors occurred within this function/method/
|
||||
/// block.
|
||||
bool Sema::hasAnyErrorsInThisFunction() const {
|
||||
unsigned NumErrors = TopFunctionScope.NumErrorsAtStartOfFunction;
|
||||
if (!FunctionScopes.empty())
|
||||
NumErrors = FunctionScopes.back()->NumErrorsAtStartOfFunction;
|
||||
return NumErrors != getDiagnostics().getNumErrors();
|
||||
return getCurFunction()->NumErrorsAtStartOfFunction
|
||||
!= getDiagnostics().getNumErrors();
|
||||
}
|
||||
|
||||
BlockScopeInfo *Sema::getCurBlock() {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Analysis/Analyses/FormatString.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include "clang/Basic/TargetInfo.h"
|
||||
#include <limits>
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
/// getLocationOfStringLiteralByte - Return a source location that points to the
|
||||
/// specified byte of the specified string literal.
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "clang/Sema/CodeCompleteConsumer.h"
|
||||
#include "clang/Sema/ExternalSemaSource.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/ExprCXX.h"
|
||||
#include "clang/AST/ExprObjC.h"
|
||||
|
@ -29,6 +30,7 @@
|
|||
#include <vector>
|
||||
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
namespace {
|
||||
/// \brief A container of code-completion results.
|
||||
|
@ -1376,7 +1378,7 @@ static void AddOrdinaryNameResults(Action::ParserCompletionContext CCC,
|
|||
}
|
||||
|
||||
// Switch-specific statements.
|
||||
if (!SemaRef.getSwitchStack().empty()) {
|
||||
if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
|
||||
// case expression:
|
||||
Pattern = new CodeCompletionString;
|
||||
Pattern->AddTypedTextChunk("case");
|
||||
|
@ -2751,10 +2753,10 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
|
|||
}
|
||||
|
||||
void Sema::CodeCompleteCase(Scope *S) {
|
||||
if (getSwitchStack().empty() || !CodeCompleter)
|
||||
if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
|
||||
return;
|
||||
|
||||
SwitchStmt *Switch = getSwitchStack().back();
|
||||
SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
|
||||
if (!Switch->getCond()->getType()->isEnumeralType()) {
|
||||
CodeCompleteExpressionData Data(Switch->getCond()->getType());
|
||||
Data.IntegralConstantExpression = true;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/CXXFieldCollector.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/AST/APValue.h"
|
||||
#include "clang/AST/ASTConsumer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
@ -39,6 +40,7 @@
|
|||
#include <cstring>
|
||||
#include <functional>
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
/// getDeclName - Return a pretty name for the specified decl if possible, or
|
||||
/// an empty string if not. This is used for pretty crash reporting.
|
||||
|
@ -2546,7 +2548,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
// that redeclarations will match.
|
||||
QualType T = NewTD->getUnderlyingType();
|
||||
if (T->isVariablyModifiedType()) {
|
||||
setFunctionHasBranchProtectedScope();
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
|
||||
if (S->getFnParent() == 0) {
|
||||
bool SizeIsNegative;
|
||||
|
@ -2983,7 +2985,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD,
|
|||
bool isVM = T->isVariablyModifiedType();
|
||||
if (isVM || NewVD->hasAttr<CleanupAttr>() ||
|
||||
NewVD->hasAttr<BlocksAttr>())
|
||||
setFunctionHasBranchProtectedScope();
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
|
||||
if ((isVM && NewVD->hasLinkage()) ||
|
||||
(T->isVariableArrayType() && NewVD->hasGlobalStorage())) {
|
||||
|
@ -4152,7 +4154,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) {
|
|||
}
|
||||
|
||||
if (getLangOptions().CPlusPlus && VDecl->hasLocalStorage())
|
||||
setFunctionHasBranchProtectedScope();
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
|
||||
// Capture the variable that is being initialized and the style of
|
||||
// initialization.
|
||||
|
@ -4477,7 +4479,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl,
|
|||
// clarifies that this applies to a "variable with automatic
|
||||
// storage duration", not a "local variable".
|
||||
if (getLangOptions().CPlusPlus && Var->hasLocalStorage())
|
||||
setFunctionHasBranchProtectedScope();
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
|
||||
InitializedEntity Entity = InitializedEntity::InitializeVariable(Var);
|
||||
InitializationKind Kind
|
||||
|
@ -4901,9 +4903,11 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
|
|||
/// FIXME: Employ a smarter algorithm that accounts for multiple return
|
||||
/// statements and the lifetimes of the NRVO candidates. We should be able to
|
||||
/// find a maximal set of NRVO variables.
|
||||
static void ComputeNRVO(Stmt *Body, ReturnStmt **Returns, unsigned NumReturns) {
|
||||
static void ComputeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
|
||||
ReturnStmt **Returns = Scope->Returns.data();
|
||||
|
||||
const VarDecl *NRVOCandidate = 0;
|
||||
for (unsigned I = 0; I != NumReturns; ++I) {
|
||||
for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) {
|
||||
if (!Returns[I]->getNRVOCandidate())
|
||||
return;
|
||||
|
||||
|
@ -4948,8 +4952,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD))
|
||||
MarkVTableUsed(FD->getLocation(), Constructor->getParent());
|
||||
|
||||
ComputeNRVO(Body, FunctionScopes.back()->Returns.data(),
|
||||
FunctionScopes.back()->Returns.size());
|
||||
ComputeNRVO(Body, getCurFunction());
|
||||
}
|
||||
|
||||
assert(FD == getCurFunctionDecl() && "Function parsing confused");
|
||||
|
@ -4966,8 +4969,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
// Verify and clean out per-function state.
|
||||
|
||||
// Check goto/label use.
|
||||
FunctionScopeInfo *CurFn = getCurFunction();
|
||||
for (llvm::DenseMap<IdentifierInfo*, LabelStmt*>::iterator
|
||||
I = getLabelMap().begin(), E = getLabelMap().end(); I != E; ++I) {
|
||||
I = CurFn->LabelMap.begin(), E = CurFn->LabelMap.end(); I != E; ++I) {
|
||||
LabelStmt *L = I->second;
|
||||
|
||||
// Verify that we have no forward references left. If so, there was a goto
|
||||
|
@ -5013,7 +5017,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
|||
|
||||
// Verify that that gotos and switch cases don't jump into scopes illegally.
|
||||
// Verify that that gotos and switch cases don't jump into scopes illegally.
|
||||
if (FunctionNeedsScopeChecking() &&
|
||||
if (getCurFunction()->NeedsScopeChecking() &&
|
||||
!dcl->isInvalidDecl() &&
|
||||
!hasAnyErrorsInThisFunction())
|
||||
DiagnoseInvalidJumps(Body);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/ExternalSemaSource.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
|
@ -1480,7 +1481,7 @@ Decl *Sema::ActOnMethodDeclaration(
|
|||
// Make sure we can establish a context for the method.
|
||||
if (!ClassDecl) {
|
||||
Diag(MethodLoc, diag::error_missing_method_context);
|
||||
getLabelMap().clear();
|
||||
getCurFunction()->LabelMap.clear();
|
||||
return 0;
|
||||
}
|
||||
QualType resultDeclType;
|
||||
|
|
|
@ -32,9 +32,11 @@
|
|||
#include "clang/Sema/DeclSpec.h"
|
||||
#include "clang/Sema/Designator.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/ParsedTemplate.h"
|
||||
#include "clang/Sema/Template.h"
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
|
||||
/// \brief Determine whether the use of this declaration is valid, and
|
||||
|
@ -6790,7 +6792,7 @@ ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc,
|
|||
SourceLocation LabLoc,
|
||||
IdentifierInfo *LabelII) {
|
||||
// Look up the record for this label identifier.
|
||||
LabelStmt *&LabelDecl = getLabelMap()[LabelII];
|
||||
LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII];
|
||||
|
||||
// If we haven't seen this label yet, create a forward reference. It
|
||||
// will be validated and/or cleaned up in ActOnFinishFunctionBody.
|
||||
|
@ -7268,7 +7270,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc,
|
|||
BlockTy = Context.getBlockPointerType(BlockTy);
|
||||
|
||||
// If needed, diagnose invalid gotos and switches in the block.
|
||||
if (FunctionNeedsScopeChecking() && !hasAnyErrorsInThisFunction())
|
||||
if (getCurFunction()->NeedsScopeChecking() && !hasAnyErrorsInThisFunction())
|
||||
DiagnoseInvalidJumps(cast<CompoundStmt>(Body));
|
||||
|
||||
BSI->TheDecl->setBody(cast<CompoundStmt>(Body));
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/DeclSpec.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/TemplateDeduction.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
|
@ -2986,7 +2987,7 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS,
|
|||
if (S && S->getContinueParent())
|
||||
Consumer.addKeywordResult(Context, "continue");
|
||||
|
||||
if (!getSwitchStack().empty()) {
|
||||
if (!getCurFunction()->SwitchStack.empty()) {
|
||||
Consumer.addKeywordResult(Context, "case");
|
||||
Consumer.addKeywordResult(Context, "default");
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/Initialization.h"
|
||||
#include "clang/AST/APValue.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
StmtResult Sema::ActOnExprStmt(FullExprArg expr) {
|
||||
Expr *E = expr.get();
|
||||
|
@ -190,14 +192,14 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal,
|
|||
RHSVal = 0; // Recover by just forgetting about it.
|
||||
}
|
||||
|
||||
if (getSwitchStack().empty()) {
|
||||
if (getCurFunction()->SwitchStack.empty()) {
|
||||
Diag(CaseLoc, diag::err_case_not_in_switch);
|
||||
return StmtError();
|
||||
}
|
||||
|
||||
CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc,
|
||||
ColonLoc);
|
||||
getSwitchStack().back()->addSwitchCase(CS);
|
||||
getCurFunction()->SwitchStack.back()->addSwitchCase(CS);
|
||||
return Owned(CS);
|
||||
}
|
||||
|
||||
|
@ -210,13 +212,13 @@ void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) {
|
|||
StmtResult
|
||||
Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
|
||||
Stmt *SubStmt, Scope *CurScope) {
|
||||
if (getSwitchStack().empty()) {
|
||||
if (getCurFunction()->SwitchStack.empty()) {
|
||||
Diag(DefaultLoc, diag::err_default_not_in_switch);
|
||||
return Owned(SubStmt);
|
||||
}
|
||||
|
||||
DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
|
||||
getSwitchStack().back()->addSwitchCase(DS);
|
||||
getCurFunction()->SwitchStack.back()->addSwitchCase(DS);
|
||||
return Owned(DS);
|
||||
}
|
||||
|
||||
|
@ -224,7 +226,7 @@ StmtResult
|
|||
Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
|
||||
SourceLocation ColonLoc, Stmt *SubStmt) {
|
||||
// Look up the record for this label identifier.
|
||||
LabelStmt *&LabelDecl = getLabelMap()[II];
|
||||
LabelStmt *&LabelDecl = getCurFunction()->LabelMap[II];
|
||||
|
||||
// If not forward referenced or defined already, just create a new LabelStmt.
|
||||
if (LabelDecl == 0)
|
||||
|
@ -421,10 +423,10 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond,
|
|||
Cond = CondResult.take();
|
||||
}
|
||||
|
||||
setFunctionHasBranchIntoScope();
|
||||
getCurFunction()->setHasBranchIntoScope();
|
||||
|
||||
SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond);
|
||||
getSwitchStack().push_back(SS);
|
||||
getCurFunction()->SwitchStack.push_back(SS);
|
||||
return Owned(SS);
|
||||
}
|
||||
|
||||
|
@ -432,10 +434,11 @@ StmtResult
|
|||
Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch,
|
||||
Stmt *BodyStmt) {
|
||||
SwitchStmt *SS = cast<SwitchStmt>(Switch);
|
||||
assert(SS == getSwitchStack().back() && "switch stack missing push/pop!");
|
||||
assert(SS == getCurFunction()->SwitchStack.back() &&
|
||||
"switch stack missing push/pop!");
|
||||
|
||||
SS->setBody(BodyStmt, SwitchLoc);
|
||||
getSwitchStack().pop_back();
|
||||
getCurFunction()->SwitchStack.pop_back();
|
||||
|
||||
if (SS->getCond() == 0)
|
||||
return StmtError();
|
||||
|
@ -941,9 +944,9 @@ StmtResult
|
|||
Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc,
|
||||
IdentifierInfo *LabelII) {
|
||||
// Look up the record for this label identifier.
|
||||
LabelStmt *&LabelDecl = getLabelMap()[LabelII];
|
||||
LabelStmt *&LabelDecl = getCurFunction()->LabelMap[LabelII];
|
||||
|
||||
setFunctionHasBranchIntoScope();
|
||||
getCurFunction()->setHasBranchIntoScope();
|
||||
|
||||
// If we haven't seen this label yet, create a forward reference.
|
||||
if (LabelDecl == 0)
|
||||
|
@ -965,7 +968,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc,
|
|||
return StmtError();
|
||||
}
|
||||
|
||||
setFunctionHasIndirectGoto();
|
||||
getCurFunction()->setHasIndirectGoto();
|
||||
|
||||
return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E));
|
||||
}
|
||||
|
@ -1482,7 +1485,7 @@ Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) {
|
|||
StmtResult
|
||||
Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try,
|
||||
MultiStmtArg CatchStmts, Stmt *Finally) {
|
||||
setFunctionHasBranchProtectedScope();
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
unsigned NumCatchStmts = CatchStmts.size();
|
||||
return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try,
|
||||
CatchStmts.release(),
|
||||
|
@ -1526,7 +1529,7 @@ Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw,
|
|||
StmtResult
|
||||
Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr,
|
||||
Stmt *SyncBody) {
|
||||
setFunctionHasBranchProtectedScope();
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
|
||||
// Make sure the expression type is an ObjC pointer or "void *".
|
||||
if (!SyncExpr->getType()->isDependentType() &&
|
||||
|
@ -1632,7 +1635,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock,
|
|||
}
|
||||
}
|
||||
|
||||
setFunctionHasBranchProtectedScope();
|
||||
getCurFunction()->setHasBranchProtectedScope();
|
||||
|
||||
// FIXME: We should detect handlers that cannot catch anything because an
|
||||
// earlier handler catches a superclass. Need to find a method that is not
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/SemaDiagnostic.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
namespace clang {
|
||||
using namespace sema;
|
||||
|
||||
/// \brief A semantic tree transformation that allows one to transform one
|
||||
/// abstract syntax tree into another.
|
||||
|
|
Loading…
Reference in New Issue