From: John McCall Date: Wed, 25 Aug 2010 08:40:02 +0000 (+0000) Subject: Split FunctionScopeInfo and BlockScopeInfo into their own header. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=781472fe99a120098c631b0cbe33c89f8cef5e70;p=clang Split FunctionScopeInfo and BlockScopeInfo into their own header. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112038 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h new file mode 100644 index 0000000000..50cfa9bb56 --- /dev/null +++ b/include/clang/Sema/ScopeInfo.h @@ -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 LabelMap; + + /// SwitchStack - This is the current set of active switch statements in the + /// block. + llvm::SmallVector 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 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 diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 2c06bcaf98..01c5a41b42 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 LabelMap; - - /// SwitchStack - This is the current set of active switch statements in the - /// block. - llvm::SmallVector 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 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 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 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 &getLabelMap() { - if (FunctionScopes.empty()) - return TopFunctionScope.LabelMap; - - return FunctionScopes.back()->LabelMap; - } - - /// getSwitchStack - This is returns the switch stack for the current block or - /// function. - llvm::SmallVector &getSwitchStack() { - if (FunctionScopes.empty()) - return TopFunctionScope.SwitchStack; - - return FunctionScopes.back()->SwitchStack; + sema::FunctionScopeInfo *getCurFunction() const { + return FunctionScopes.back(); } - /// \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 &WeakTopLevelDecls() { return WeakTopLevelDecl; } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 1de7b7fbea..2320d7dc32 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -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(&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() { diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 7a64511f32..7ea96f4014 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -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 using namespace clang; +using namespace sema; /// getLocationOfStringLiteralByte - Return a source location that points to the /// specified byte of the specified string literal. diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 4228bed9ee..ad4382e09b 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -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 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; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 219a46d7da..659c0d1a92 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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 #include 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() || NewVD->hasAttr()) - 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(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::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); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index b4acfbd044..13e42edaae 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -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; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ae8e657aee..5986eca373 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(Body)); BSI->TheDecl->setBody(cast(Body)); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 8c8c0073b3..4cc78ef976 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -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"); } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 7f88e2ff52..41aec13e82 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -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(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 diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index fe1f6b96e8..432caa7329 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -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 namespace clang { +using namespace sema; /// \brief A semantic tree transformation that allows one to transform one /// abstract syntax tree into another.