diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
38 files changed, 110912 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp new file mode 100644 index 0000000..9efae61 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -0,0 +1,712 @@ +//=- AnalysisBasedWarnings.cpp - Sema warnings based on libAnalysis -*- 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 analysis_warnings::[Policy,Executor]. +// Together they are used by Sema to issue warnings based on inexpensive +// static analysis algorithms in libAnalysis. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/AnalysisBasedWarnings.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/Analyses/ReachableCode.h" +#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/CFGStmtMap.h" +#include "clang/Analysis/Analyses/UninitializedValues.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/Support/Casting.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// Unreachable code analysis. +//===----------------------------------------------------------------------===// + +namespace { + class UnreachableCodeHandler : public reachable_code::Callback { + Sema &S; + public: + UnreachableCodeHandler(Sema &s) : S(s) {} + + void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { + S.Diag(L, diag::warn_unreachable) << R1 << R2; + } + }; +} + +/// CheckUnreachable - Check for unreachable code. +static void CheckUnreachable(Sema &S, AnalysisContext &AC) { + UnreachableCodeHandler UC(S); + reachable_code::FindUnreachableCode(AC, UC); +} + +//===----------------------------------------------------------------------===// +// Check for missing return value. +//===----------------------------------------------------------------------===// + +enum ControlFlowKind { + UnknownFallThrough, + NeverFallThrough, + MaybeFallThrough, + AlwaysFallThrough, + NeverFallThroughOrReturn +}; + +/// CheckFallThrough - Check that we don't fall off the end of a +/// Statement that should return a value. +/// +/// \returns AlwaysFallThrough iff we always fall off the end of the statement, +/// MaybeFallThrough iff we might or might not fall off the end, +/// NeverFallThroughOrReturn iff we never fall off the end of the statement or +/// return. We assume NeverFallThrough iff we never fall off the end of the +/// statement but we may return. We assume that functions not marked noreturn +/// will return. +static ControlFlowKind CheckFallThrough(AnalysisContext &AC) { + CFG *cfg = AC.getCFG(); + if (cfg == 0) return UnknownFallThrough; + + // The CFG leaves in dead things, and we don't want the dead code paths to + // confuse us, so we mark all live things first. + llvm::BitVector live(cfg->getNumBlockIDs()); + unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(), + live); + + bool AddEHEdges = AC.getAddEHEdges(); + if (!AddEHEdges && count != cfg->getNumBlockIDs()) + // When there are things remaining dead, and we didn't add EH edges + // from CallExprs to the catch clauses, we have to go back and + // mark them as live. + for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { + CFGBlock &b = **I; + if (!live[b.getBlockID()]) { + if (b.pred_begin() == b.pred_end()) { + if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) + // When not adding EH edges from calls, catch clauses + // can otherwise seem dead. Avoid noting them as dead. + count += reachable_code::ScanReachableFromBlock(b, live); + continue; + } + } + } + + // Now we know what is live, we check the live precessors of the exit block + // and look for fall through paths, being careful to ignore normal returns, + // and exceptional paths. + bool HasLiveReturn = false; + bool HasFakeEdge = false; + bool HasPlainEdge = false; + bool HasAbnormalEdge = false; + + // Ignore default cases that aren't likely to be reachable because all + // enums in a switch(X) have explicit case statements. + CFGBlock::FilterOptions FO; + FO.IgnoreDefaultsWithCoveredEnums = 1; + + for (CFGBlock::filtered_pred_iterator + I = cfg->getExit().filtered_pred_start_end(FO); I.hasMore(); ++I) { + const CFGBlock& B = **I; + if (!live[B.getBlockID()]) + continue; + + // Destructors can appear after the 'return' in the CFG. This is + // normal. We need to look pass the destructors for the return + // statement (if it exists). + CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); + bool hasNoReturnDtor = false; + + for ( ; ri != re ; ++ri) { + CFGElement CE = *ri; + + // FIXME: The right solution is to just sever the edges in the + // CFG itself. + if (const CFGImplicitDtor *iDtor = ri->getAs<CFGImplicitDtor>()) + if (iDtor->isNoReturn(AC.getASTContext())) { + hasNoReturnDtor = true; + HasFakeEdge = true; + break; + } + + if (isa<CFGStmt>(CE)) + break; + } + + if (hasNoReturnDtor) + continue; + + // No more CFGElements in the block? + if (ri == re) { + if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) { + HasAbnormalEdge = true; + continue; + } + // A labeled empty statement, or the entry block... + HasPlainEdge = true; + continue; + } + + CFGStmt CS = cast<CFGStmt>(*ri); + Stmt *S = CS.getStmt(); + if (isa<ReturnStmt>(S)) { + HasLiveReturn = true; + continue; + } + if (isa<ObjCAtThrowStmt>(S)) { + HasFakeEdge = true; + continue; + } + if (isa<CXXThrowExpr>(S)) { + HasFakeEdge = true; + continue; + } + if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) { + if (AS->isMSAsm()) { + HasFakeEdge = true; + HasLiveReturn = true; + continue; + } + } + if (isa<CXXTryStmt>(S)) { + HasAbnormalEdge = true; + continue; + } + + bool NoReturnEdge = false; + if (CallExpr *C = dyn_cast<CallExpr>(S)) { + if (std::find(B.succ_begin(), B.succ_end(), &cfg->getExit()) + == B.succ_end()) { + HasAbnormalEdge = true; + continue; + } + Expr *CEE = C->getCallee()->IgnoreParenCasts(); + QualType calleeType = CEE->getType(); + if (calleeType == AC.getASTContext().BoundMemberTy) { + calleeType = Expr::findBoundMemberType(CEE); + assert(!calleeType.isNull() && "analyzing unresolved call?"); + } + if (getFunctionExtInfo(calleeType).getNoReturn()) { + NoReturnEdge = true; + HasFakeEdge = true; + } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { + ValueDecl *VD = DRE->getDecl(); + if (VD->hasAttr<NoReturnAttr>()) { + NoReturnEdge = true; + HasFakeEdge = true; + } + } + } + // FIXME: Add noreturn message sends. + if (NoReturnEdge == false) + HasPlainEdge = true; + } + if (!HasPlainEdge) { + if (HasLiveReturn) + return NeverFallThrough; + return NeverFallThroughOrReturn; + } + if (HasAbnormalEdge || HasFakeEdge || HasLiveReturn) + return MaybeFallThrough; + // This says AlwaysFallThrough for calls to functions that are not marked + // noreturn, that don't return. If people would like this warning to be more + // accurate, such functions should be marked as noreturn. + return AlwaysFallThrough; +} + +namespace { + +struct CheckFallThroughDiagnostics { + unsigned diag_MaybeFallThrough_HasNoReturn; + unsigned diag_MaybeFallThrough_ReturnsNonVoid; + unsigned diag_AlwaysFallThrough_HasNoReturn; + unsigned diag_AlwaysFallThrough_ReturnsNonVoid; + unsigned diag_NeverFallThroughOrReturn; + bool funMode; + SourceLocation FuncLoc; + + static CheckFallThroughDiagnostics MakeForFunction(const Decl *Func) { + CheckFallThroughDiagnostics D; + D.FuncLoc = Func->getLocation(); + D.diag_MaybeFallThrough_HasNoReturn = + diag::warn_falloff_noreturn_function; + D.diag_MaybeFallThrough_ReturnsNonVoid = + diag::warn_maybe_falloff_nonvoid_function; + D.diag_AlwaysFallThrough_HasNoReturn = + diag::warn_falloff_noreturn_function; + D.diag_AlwaysFallThrough_ReturnsNonVoid = + diag::warn_falloff_nonvoid_function; + + // Don't suggest that virtual functions be marked "noreturn", since they + // might be overridden by non-noreturn functions. + bool isVirtualMethod = false; + if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Func)) + isVirtualMethod = Method->isVirtual(); + + if (!isVirtualMethod) + D.diag_NeverFallThroughOrReturn = + diag::warn_suggest_noreturn_function; + else + D.diag_NeverFallThroughOrReturn = 0; + + D.funMode = true; + return D; + } + + static CheckFallThroughDiagnostics MakeForBlock() { + CheckFallThroughDiagnostics D; + D.diag_MaybeFallThrough_HasNoReturn = + diag::err_noreturn_block_has_return_expr; + D.diag_MaybeFallThrough_ReturnsNonVoid = + diag::err_maybe_falloff_nonvoid_block; + D.diag_AlwaysFallThrough_HasNoReturn = + diag::err_noreturn_block_has_return_expr; + D.diag_AlwaysFallThrough_ReturnsNonVoid = + diag::err_falloff_nonvoid_block; + D.diag_NeverFallThroughOrReturn = + diag::warn_suggest_noreturn_block; + D.funMode = false; + return D; + } + + bool checkDiagnostics(Diagnostic &D, bool ReturnsVoid, + bool HasNoReturn) const { + if (funMode) { + return (ReturnsVoid || + D.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function, + FuncLoc) == Diagnostic::Ignored) + && (!HasNoReturn || + D.getDiagnosticLevel(diag::warn_noreturn_function_has_return_expr, + FuncLoc) == Diagnostic::Ignored) + && (!ReturnsVoid || + D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) + == Diagnostic::Ignored); + } + + // For blocks. + return ReturnsVoid && !HasNoReturn + && (!ReturnsVoid || + D.getDiagnosticLevel(diag::warn_suggest_noreturn_block, FuncLoc) + == Diagnostic::Ignored); + } +}; + +} + +/// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a +/// function that should return a value. Check that we don't fall off the end +/// of a noreturn function. We assume that functions and blocks not marked +/// noreturn will return. +static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, + const BlockExpr *blkExpr, + const CheckFallThroughDiagnostics& CD, + AnalysisContext &AC) { + + bool ReturnsVoid = false; + bool HasNoReturn = false; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + ReturnsVoid = FD->getResultType()->isVoidType(); + HasNoReturn = FD->hasAttr<NoReturnAttr>() || + FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); + } + else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { + ReturnsVoid = MD->getResultType()->isVoidType(); + HasNoReturn = MD->hasAttr<NoReturnAttr>(); + } + else if (isa<BlockDecl>(D)) { + QualType BlockTy = blkExpr->getType(); + if (const FunctionType *FT = + BlockTy->getPointeeType()->getAs<FunctionType>()) { + if (FT->getResultType()->isVoidType()) + ReturnsVoid = true; + if (FT->getNoReturnAttr()) + HasNoReturn = true; + } + } + + Diagnostic &Diags = S.getDiagnostics(); + + // Short circuit for compilation speed. + if (CD.checkDiagnostics(Diags, ReturnsVoid, HasNoReturn)) + return; + + // FIXME: Function try block + if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body)) { + switch (CheckFallThrough(AC)) { + case UnknownFallThrough: + break; + + case MaybeFallThrough: + if (HasNoReturn) + S.Diag(Compound->getRBracLoc(), + CD.diag_MaybeFallThrough_HasNoReturn); + else if (!ReturnsVoid) + S.Diag(Compound->getRBracLoc(), + CD.diag_MaybeFallThrough_ReturnsNonVoid); + break; + case AlwaysFallThrough: + if (HasNoReturn) + S.Diag(Compound->getRBracLoc(), + CD.diag_AlwaysFallThrough_HasNoReturn); + else if (!ReturnsVoid) + S.Diag(Compound->getRBracLoc(), + CD.diag_AlwaysFallThrough_ReturnsNonVoid); + break; + case NeverFallThroughOrReturn: + if (ReturnsVoid && !HasNoReturn && CD.diag_NeverFallThroughOrReturn) + S.Diag(Compound->getLBracLoc(), + CD.diag_NeverFallThroughOrReturn); + break; + case NeverFallThrough: + break; + } + } +} + +//===----------------------------------------------------------------------===// +// -Wuninitialized +//===----------------------------------------------------------------------===// + +namespace { +/// ContainsReference - A visitor class to search for references to +/// a particular declaration (the needle) within any evaluated component of an +/// expression (recursively). +class ContainsReference : public EvaluatedExprVisitor<ContainsReference> { + bool FoundReference; + const DeclRefExpr *Needle; + +public: + ContainsReference(ASTContext &Context, const DeclRefExpr *Needle) + : EvaluatedExprVisitor<ContainsReference>(Context), + FoundReference(false), Needle(Needle) {} + + void VisitExpr(Expr *E) { + // Stop evaluating if we already have a reference. + if (FoundReference) + return; + + EvaluatedExprVisitor<ContainsReference>::VisitExpr(E); + } + + void VisitDeclRefExpr(DeclRefExpr *E) { + if (E == Needle) + FoundReference = true; + else + EvaluatedExprVisitor<ContainsReference>::VisitDeclRefExpr(E); + } + + bool doesContainReference() const { return FoundReference; } +}; +} + +/// DiagnoseUninitializedUse -- Helper function for diagnosing uses of an +/// uninitialized variable. This manages the different forms of diagnostic +/// emitted for particular types of uses. Returns true if the use was diagnosed +/// as a warning. If a pariticular use is one we omit warnings for, returns +/// false. +static bool DiagnoseUninitializedUse(Sema &S, const VarDecl *VD, + const Expr *E, bool isAlwaysUninit) { + bool isSelfInit = false; + + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (isAlwaysUninit) { + // Inspect the initializer of the variable declaration which is + // being referenced prior to its initialization. We emit + // specialized diagnostics for self-initialization, and we + // specifically avoid warning about self references which take the + // form of: + // + // int x = x; + // + // This is used to indicate to GCC that 'x' is intentionally left + // uninitialized. Proven code paths which access 'x' in + // an uninitialized state after this will still warn. + // + // TODO: Should we suppress maybe-uninitialized warnings for + // variables initialized in this way? + if (const Expr *Initializer = VD->getInit()) { + if (DRE == Initializer->IgnoreParenImpCasts()) + return false; + + ContainsReference CR(S.Context, DRE); + CR.Visit(const_cast<Expr*>(Initializer)); + isSelfInit = CR.doesContainReference(); + } + if (isSelfInit) { + S.Diag(DRE->getLocStart(), + diag::warn_uninit_self_reference_in_init) + << VD->getDeclName() << VD->getLocation() << DRE->getSourceRange(); + } else { + S.Diag(DRE->getLocStart(), diag::warn_uninit_var) + << VD->getDeclName() << DRE->getSourceRange(); + } + } else { + S.Diag(DRE->getLocStart(), diag::warn_maybe_uninit_var) + << VD->getDeclName() << DRE->getSourceRange(); + } + } else { + const BlockExpr *BE = cast<BlockExpr>(E); + S.Diag(BE->getLocStart(), + isAlwaysUninit ? diag::warn_uninit_var_captured_by_block + : diag::warn_maybe_uninit_var_captured_by_block) + << VD->getDeclName(); + } + + // Report where the variable was declared when the use wasn't within + // the initializer of that declaration. + if (!isSelfInit) + S.Diag(VD->getLocStart(), diag::note_uninit_var_def) + << VD->getDeclName(); + + return true; +} + +static void SuggestInitializationFixit(Sema &S, const VarDecl *VD) { + // Don't issue a fixit if there is already an initializer. + if (VD->getInit()) + return; + + // Suggest possible initialization (if any). + const char *initialization = 0; + QualType VariableTy = VD->getType().getCanonicalType(); + + if (VariableTy->getAs<ObjCObjectPointerType>()) { + // Check if 'nil' is defined. + if (S.PP.getMacroInfo(&S.getASTContext().Idents.get("nil"))) + initialization = " = nil"; + else + initialization = " = 0"; + } + else if (VariableTy->isRealFloatingType()) + initialization = " = 0.0"; + else if (VariableTy->isBooleanType() && S.Context.getLangOptions().CPlusPlus) + initialization = " = false"; + else if (VariableTy->isEnumeralType()) + return; + else if (VariableTy->isScalarType()) + initialization = " = 0"; + + if (initialization) { + SourceLocation loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); + S.Diag(loc, diag::note_var_fixit_add_initialization) + << FixItHint::CreateInsertion(loc, initialization); + } +} + +typedef std::pair<const Expr*, bool> UninitUse; + +namespace { +struct SLocSort { + bool operator()(const UninitUse &a, const UninitUse &b) { + SourceLocation aLoc = a.first->getLocStart(); + SourceLocation bLoc = b.first->getLocStart(); + return aLoc.getRawEncoding() < bLoc.getRawEncoding(); + } +}; + +class UninitValsDiagReporter : public UninitVariablesHandler { + Sema &S; + typedef llvm::SmallVector<UninitUse, 2> UsesVec; + typedef llvm::DenseMap<const VarDecl *, UsesVec*> UsesMap; + UsesMap *uses; + +public: + UninitValsDiagReporter(Sema &S) : S(S), uses(0) {} + ~UninitValsDiagReporter() { + flushDiagnostics(); + } + + void handleUseOfUninitVariable(const Expr *ex, const VarDecl *vd, + bool isAlwaysUninit) { + if (!uses) + uses = new UsesMap(); + + UsesVec *&vec = (*uses)[vd]; + if (!vec) + vec = new UsesVec(); + + vec->push_back(std::make_pair(ex, isAlwaysUninit)); + } + + void flushDiagnostics() { + if (!uses) + return; + + for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { + const VarDecl *vd = i->first; + UsesVec *vec = i->second; + + bool fixitIssued = false; + + // Sort the uses by their SourceLocations. While not strictly + // guaranteed to produce them in line/column order, this will provide + // a stable ordering. + std::sort(vec->begin(), vec->end(), SLocSort()); + + for (UsesVec::iterator vi = vec->begin(), ve = vec->end(); vi != ve; + ++vi) { + if (!DiagnoseUninitializedUse(S, vd, vi->first, + /*isAlwaysUninit=*/vi->second)) + continue; + + // Suggest a fixit hint the first time we diagnose a use of a variable. + if (!fixitIssued) { + SuggestInitializationFixit(S, vd); + fixitIssued = true; + } + } + + delete vec; + } + delete uses; + } +}; +} + +//===----------------------------------------------------------------------===// +// AnalysisBasedWarnings - Worker object used by Sema to execute analysis-based +// warnings on a function, method, or block. +//===----------------------------------------------------------------------===// + +clang::sema::AnalysisBasedWarnings::Policy::Policy() { + enableCheckFallThrough = 1; + enableCheckUnreachable = 0; +} + +clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) { + Diagnostic &D = S.getDiagnostics(); + DefaultPolicy.enableCheckUnreachable = (unsigned) + (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != + Diagnostic::Ignored); +} + +static void flushDiagnostics(Sema &S, sema::FunctionScopeInfo *fscope) { + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + S.Diag(D.Loc, D.PD); + } +} + +void clang::sema:: +AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, + sema::FunctionScopeInfo *fscope, + const Decl *D, const BlockExpr *blkExpr) { + + // We avoid doing analysis-based warnings when there are errors for + // two reasons: + // (1) The CFGs often can't be constructed (if the body is invalid), so + // don't bother trying. + // (2) The code already has problems; running the analysis just takes more + // time. + Diagnostic &Diags = S.getDiagnostics(); + + // Do not do any analysis for declarations in system headers if we are + // going to just ignore them. + if (Diags.getSuppressSystemWarnings() && + S.SourceMgr.isInSystemHeader(D->getLocation())) + return; + + // For code in dependent contexts, we'll do this at instantiation time. + if (cast<DeclContext>(D)->isDependentContext()) + return; + + if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { + // Flush out any possibly unreachable diagnostics. + flushDiagnostics(S, fscope); + return; + } + + const Stmt *Body = D->getBody(); + assert(Body); + + // Don't generate EH edges for CallExprs as we'd like to avoid the n^2 + // explosion for destrutors that can result and the compile time hit. + AnalysisContext AC(D, 0, /*useUnoptimizedCFG=*/false, /*addehedges=*/false, + /*addImplicitDtors=*/true, /*addInitializers=*/true); + + // Emit delayed diagnostics. + if (!fscope->PossiblyUnreachableDiags.empty()) { + bool analyzed = false; + + // Register the expressions with the CFGBuilder. + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + if (const Stmt *stmt = i->stmt) + AC.registerForcedBlockExpression(stmt); + } + + if (AC.getCFG()) { + analyzed = true; + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = fscope->PossiblyUnreachableDiags.begin(), + e = fscope->PossiblyUnreachableDiags.end(); + i != e; ++i) + { + const sema::PossiblyUnreachableDiag &D = *i; + bool processed = false; + if (const Stmt *stmt = i->stmt) { + const CFGBlock *block = AC.getBlockForRegisteredExpression(stmt); + assert(block); + if (CFGReverseBlockReachabilityAnalysis *cra = AC.getCFGReachablityAnalysis()) { + // Can this block be reached from the entrance? + if (cra->isReachable(&AC.getCFG()->getEntry(), block)) + S.Diag(D.Loc, D.PD); + processed = true; + } + } + if (!processed) { + // Emit the warning anyway if we cannot map to a basic block. + S.Diag(D.Loc, D.PD); + } + } + } + + if (!analyzed) + flushDiagnostics(S, fscope); + } + + + // Warning: check missing 'return' + if (P.enableCheckFallThrough) { + const CheckFallThroughDiagnostics &CD = + (isa<BlockDecl>(D) ? CheckFallThroughDiagnostics::MakeForBlock() + : CheckFallThroughDiagnostics::MakeForFunction(D)); + CheckFallThroughForBody(S, D, Body, blkExpr, CD, AC); + } + + // Warning: check for unreachable code + if (P.enableCheckUnreachable) + CheckUnreachable(S, AC); + + if (Diags.getDiagnosticLevel(diag::warn_uninit_var, D->getLocStart()) + != Diagnostic::Ignored || + Diags.getDiagnosticLevel(diag::warn_maybe_uninit_var, D->getLocStart()) + != Diagnostic::Ignored) { + if (CFG *cfg = AC.getCFG()) { + UninitValsDiagReporter reporter(S); + runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, + reporter); + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp new file mode 100644 index 0000000..619a5b9 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/AttributeList.cpp @@ -0,0 +1,207 @@ +//===--- AttributeList.cpp --------------------------------------*- 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 the AttributeList class implementation +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/AttributeList.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/IdentifierTable.h" +#include "llvm/ADT/StringSwitch.h" +using namespace clang; + +size_t AttributeList::allocated_size() const { + if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; + return (sizeof(AttributeList) + NumArgs * sizeof(Expr*)); +} + +AttributeFactory::AttributeFactory() { + // Go ahead and configure all the inline capacity. This is just a memset. + FreeLists.resize(InlineFreeListsCapacity); +} +AttributeFactory::~AttributeFactory() {} + +static size_t getFreeListIndexForSize(size_t size) { + assert(size >= sizeof(AttributeList)); + assert((size % sizeof(void*)) == 0); + return ((size - sizeof(AttributeList)) / sizeof(void*)); +} + +void *AttributeFactory::allocate(size_t size) { + // Check for a previously reclaimed attribute. + size_t index = getFreeListIndexForSize(size); + if (index < FreeLists.size()) { + if (AttributeList *attr = FreeLists[index]) { + FreeLists[index] = attr->NextInPool; + return attr; + } + } + + // Otherwise, allocate something new. + return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment); +} + +void AttributeFactory::reclaimPool(AttributeList *cur) { + assert(cur && "reclaiming empty pool!"); + do { + // Read this here, because we're going to overwrite NextInPool + // when we toss 'cur' into the appropriate queue. + AttributeList *next = cur->NextInPool; + + size_t size = cur->allocated_size(); + size_t freeListIndex = getFreeListIndexForSize(size); + + // Expand FreeLists to the appropriate size, if required. + if (freeListIndex >= FreeLists.size()) + FreeLists.resize(freeListIndex+1); + + // Add 'cur' to the appropriate free-list. + cur->NextInPool = FreeLists[freeListIndex]; + FreeLists[freeListIndex] = cur; + + cur = next; + } while (cur); +} + +void AttributePool::takePool(AttributeList *pool) { + assert(pool); + + // Fast path: this pool is empty. + if (!Head) { + Head = pool; + return; + } + + // Reverse the pool onto the current head. This optimizes for the + // pattern of pulling a lot of pools into a single pool. + do { + AttributeList *next = pool->NextInPool; + pool->NextInPool = Head; + Head = pool; + pool = next; + } while (pool); +} + +AttributeList * +AttributePool::createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, + SourceLocation TokLoc, int Arg) { + Expr *IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t) Arg), + C.IntTy, TokLoc); + return create(Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0); +} + +AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { + llvm::StringRef AttrName = Name->getName(); + + // Normalize the attribute name, __foo__ becomes foo. + if (AttrName.startswith("__") && AttrName.endswith("__")) + AttrName = AttrName.substr(2, AttrName.size() - 4); + + return llvm::StringSwitch<AttributeList::Kind>(AttrName) + .Case("weak", AT_weak) + .Case("weakref", AT_weakref) + .Case("pure", AT_pure) + .Case("mode", AT_mode) + .Case("used", AT_used) + .Case("alias", AT_alias) + .Case("align", AT_aligned) + .Case("cdecl", AT_cdecl) + .Case("const", AT_const) + .Case("__const", AT_const) // some GCC headers do contain this spelling + .Case("blocks", AT_blocks) + .Case("format", AT_format) + .Case("malloc", AT_malloc) + .Case("packed", AT_packed) + .Case("unused", AT_unused) + .Case("aligned", AT_aligned) + .Case("cleanup", AT_cleanup) + .Case("naked", AT_naked) + .Case("nodebug", AT_nodebug) + .Case("nonnull", AT_nonnull) + .Case("nothrow", AT_nothrow) + .Case("objc_gc", AT_objc_gc) + .Case("regparm", AT_regparm) + .Case("section", AT_section) + .Case("stdcall", AT_stdcall) + .Case("annotate", AT_annotate) + .Case("fastcall", AT_fastcall) + .Case("ibaction", AT_IBAction) + .Case("iboutlet", AT_IBOutlet) + .Case("iboutletcollection", AT_IBOutletCollection) + .Case("noreturn", AT_noreturn) + .Case("noinline", AT_noinline) + .Case("sentinel", AT_sentinel) + .Case("NSObject", AT_nsobject) + .Case("dllimport", AT_dllimport) + .Case("dllexport", AT_dllexport) + .Case("may_alias", AT_may_alias) + .Case("base_check", AT_base_check) + .Case("deprecated", AT_deprecated) + .Case("availability", AT_availability) + .Case("visibility", AT_visibility) + .Case("destructor", AT_destructor) + .Case("format_arg", AT_format_arg) + .Case("gnu_inline", AT_gnu_inline) + .Case("weak_import", AT_weak_import) + .Case("vecreturn", AT_vecreturn) + .Case("vector_size", AT_vector_size) + .Case("constructor", AT_constructor) + .Case("unavailable", AT_unavailable) + .Case("overloadable", AT_overloadable) + .Case("address_space", AT_address_space) + .Case("opencl_image_access", AT_opencl_image_access) + .Case("always_inline", AT_always_inline) + .Case("returns_twice", IgnoredAttribute) + .Case("vec_type_hint", IgnoredAttribute) + .Case("objc_exception", AT_objc_exception) + .Case("objc_method_family", AT_objc_method_family) + .Case("ext_vector_type", AT_ext_vector_type) + .Case("neon_vector_type", AT_neon_vector_type) + .Case("neon_polyvector_type", AT_neon_polyvector_type) + .Case("transparent_union", AT_transparent_union) + .Case("analyzer_noreturn", AT_analyzer_noreturn) + .Case("warn_unused_result", AT_warn_unused_result) + .Case("carries_dependency", AT_carries_dependency) + .Case("ns_consumed", AT_ns_consumed) + .Case("ns_consumes_self", AT_ns_consumes_self) + .Case("ns_returns_autoreleased", AT_ns_returns_autoreleased) + .Case("ns_returns_not_retained", AT_ns_returns_not_retained) + .Case("ns_returns_retained", AT_ns_returns_retained) + .Case("cf_consumed", AT_cf_consumed) + .Case("cf_returns_not_retained", AT_cf_returns_not_retained) + .Case("cf_returns_retained", AT_cf_returns_retained) + .Case("ownership_returns", AT_ownership_returns) + .Case("ownership_holds", AT_ownership_holds) + .Case("ownership_takes", AT_ownership_takes) + .Case("reqd_work_group_size", AT_reqd_wg_size) + .Case("init_priority", AT_init_priority) + .Case("no_instrument_function", AT_no_instrument_function) + .Case("thiscall", AT_thiscall) + .Case("bounded", IgnoredAttribute) // OpenBSD + .Case("pascal", AT_pascal) + .Case("__cdecl", AT_cdecl) + .Case("__stdcall", AT_stdcall) + .Case("__fastcall", AT_fastcall) + .Case("__thiscall", AT_thiscall) + .Case("__pascal", AT_pascal) + .Case("constant", AT_constant) + .Case("device", AT_device) + .Case("global", AT_global) + .Case("host", AT_host) + .Case("shared", AT_shared) + .Case("launch_bounds", AT_launch_bounds) + .Case("common", AT_common) + .Case("nocommon", AT_nocommon) + .Case("opencl_kernel_function", AT_opencl_kernel_function) + .Case("uuid", AT_uuid) + .Case("pcs", AT_pcs) + .Case("ms_struct", AT_MsStruct) + .Default(UnknownAttribute); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp new file mode 100644 index 0000000..2334ab5 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/CodeCompleteConsumer.cpp @@ -0,0 +1,469 @@ +//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the CodeCompleteConsumer class. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Sema.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/Lex/Preprocessor.h" +#include "clang-c/Index.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cstring> +#include <functional> + +using namespace clang; +using llvm::StringRef; + +//===----------------------------------------------------------------------===// +// Code completion context implementation +//===----------------------------------------------------------------------===// + +bool CodeCompletionContext::wantConstructorResults() const { + switch (Kind) { + case CCC_Recovery: + case CCC_Statement: + case CCC_Expression: + case CCC_ObjCMessageReceiver: + case CCC_ParenthesizedExpression: + return true; + + case CCC_TopLevel: + case CCC_ObjCInterface: + case CCC_ObjCImplementation: + case CCC_ObjCIvarList: + case CCC_ClassStructUnion: + case CCC_MemberAccess: + case CCC_EnumTag: + case CCC_UnionTag: + case CCC_ClassOrStructTag: + case CCC_ObjCProtocolName: + case CCC_Namespace: + case CCC_Type: + case CCC_Name: + case CCC_PotentiallyQualifiedName: + case CCC_MacroName: + case CCC_MacroNameUse: + case CCC_PreprocessorExpression: + case CCC_PreprocessorDirective: + case CCC_NaturalLanguage: + case CCC_SelectorName: + case CCC_TypeQualifiers: + case CCC_Other: + case CCC_OtherWithMacros: + return false; + } + + return false; +} + +//===----------------------------------------------------------------------===// +// Code completion string implementation +//===----------------------------------------------------------------------===// +CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) + : Kind(Kind), Text("") +{ + switch (Kind) { + case CK_TypedText: + case CK_Text: + case CK_Placeholder: + case CK_Informative: + case CK_ResultType: + case CK_CurrentParameter: + this->Text = Text; + break; + + case CK_Optional: + llvm_unreachable("Optional strings cannot be created from text"); + break; + + case CK_LeftParen: + this->Text = "("; + break; + + case CK_RightParen: + this->Text = ")"; + break; + + case CK_LeftBracket: + this->Text = "["; + break; + + case CK_RightBracket: + this->Text = "]"; + break; + + case CK_LeftBrace: + this->Text = "{"; + break; + + case CK_RightBrace: + this->Text = "}"; + break; + + case CK_LeftAngle: + this->Text = "<"; + break; + + case CK_RightAngle: + this->Text = ">"; + break; + + case CK_Comma: + this->Text = ", "; + break; + + case CK_Colon: + this->Text = ":"; + break; + + case CK_SemiColon: + this->Text = ";"; + break; + + case CK_Equal: + this->Text = " = "; + break; + + case CK_HorizontalSpace: + this->Text = " "; + break; + + case CK_VerticalSpace: + this->Text = "\n"; + break; + } +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateText(const char *Text) { + return Chunk(CK_Text, Text); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateOptional(CodeCompletionString *Optional) { + Chunk Result; + Result.Kind = CK_Optional; + Result.Optional = Optional; + return Result; +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { + return Chunk(CK_Placeholder, Placeholder); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateInformative(const char *Informative) { + return Chunk(CK_Informative, Informative); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateResultType(const char *ResultType) { + return Chunk(CK_ResultType, ResultType); +} + +CodeCompletionString::Chunk +CodeCompletionString::Chunk::CreateCurrentParameter( + const char *CurrentParameter) { + return Chunk(CK_CurrentParameter, CurrentParameter); +} + +CodeCompletionString::CodeCompletionString(const Chunk *Chunks, + unsigned NumChunks, + unsigned Priority, + CXAvailabilityKind Availability) + : NumChunks(NumChunks), Priority(Priority), Availability(Availability) +{ + Chunk *StoredChunks = reinterpret_cast<Chunk *>(this + 1); + for (unsigned I = 0; I != NumChunks; ++I) + StoredChunks[I] = Chunks[I]; +} + +std::string CodeCompletionString::getAsString() const { + std::string Result; + llvm::raw_string_ostream OS(Result); + + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { + switch (C->Kind) { + case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; + case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; + + case CK_Informative: + case CK_ResultType: + OS << "[#" << C->Text << "#]"; + break; + + case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break; + default: OS << C->Text; break; + } + } + return OS.str(); +} + +const char *CodeCompletionString::getTypedText() const { + for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) + if (C->Kind == CK_TypedText) + return C->Text; + + return 0; +} + +const char *CodeCompletionAllocator::CopyString(llvm::StringRef String) { + char *Mem = (char *)Allocate(String.size() + 1, 1); + std::copy(String.begin(), String.end(), Mem); + Mem[String.size()] = 0; + return Mem; +} + +const char *CodeCompletionAllocator::CopyString(llvm::Twine String) { + // FIXME: It would be more efficient to teach Twine to tell us its size and + // then add a routine there to fill in an allocated char* with the contents + // of the string. + llvm::SmallString<128> Data; + return CopyString(String.toStringRef(Data)); +} + +CodeCompletionString *CodeCompletionBuilder::TakeString() { + void *Mem = Allocator.Allocate( + sizeof(CodeCompletionString) + sizeof(Chunk) * Chunks.size(), + llvm::alignOf<CodeCompletionString>()); + CodeCompletionString *Result + = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), + Priority, Availability); + Chunks.clear(); + return Result; +} + +unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) { + if (!ND) + return CCP_Unlikely; + + // Context-based decisions. + DeclContext *DC = ND->getDeclContext()->getRedeclContext(); + if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) { + // _cmd is relatively rare + if (ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND)) + if (ImplicitParam->getIdentifier() && + ImplicitParam->getIdentifier()->isStr("_cmd")) + return CCP_ObjC_cmd; + + return CCP_LocalDeclaration; + } + if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) + return CCP_MemberDeclaration; + + // Content-based decisions. + if (isa<EnumConstantDecl>(ND)) + return CCP_Constant; + if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) + return CCP_Type; + + return CCP_Declaration; +} + +//===----------------------------------------------------------------------===// +// Code completion overload candidate implementation +//===----------------------------------------------------------------------===// +FunctionDecl * +CodeCompleteConsumer::OverloadCandidate::getFunction() const { + if (getKind() == CK_Function) + return Function; + else if (getKind() == CK_FunctionTemplate) + return FunctionTemplate->getTemplatedDecl(); + else + return 0; +} + +const FunctionType * +CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { + switch (Kind) { + case CK_Function: + return Function->getType()->getAs<FunctionType>(); + + case CK_FunctionTemplate: + return FunctionTemplate->getTemplatedDecl()->getType() + ->getAs<FunctionType>(); + + case CK_FunctionType: + return Type; + } + + return 0; +} + +//===----------------------------------------------------------------------===// +// Code completion consumer implementation +//===----------------------------------------------------------------------===// + +CodeCompleteConsumer::~CodeCompleteConsumer() { } + +void +PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef, + CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) { + std::stable_sort(Results, Results + NumResults); + + // Print the results. + for (unsigned I = 0; I != NumResults; ++I) { + OS << "COMPLETION: "; + switch (Results[I].Kind) { + case CodeCompletionResult::RK_Declaration: + OS << Results[I].Declaration; + if (Results[I].Hidden) + OS << " (Hidden)"; + if (CodeCompletionString *CCS + = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) { + OS << " : " << CCS->getAsString(); + } + + OS << '\n'; + break; + + case CodeCompletionResult::RK_Keyword: + OS << Results[I].Keyword << '\n'; + break; + + case CodeCompletionResult::RK_Macro: { + OS << Results[I].Macro->getName(); + if (CodeCompletionString *CCS + = Results[I].CreateCodeCompletionString(SemaRef, Allocator)) { + OS << " : " << CCS->getAsString(); + } + OS << '\n'; + break; + } + + case CodeCompletionResult::RK_Pattern: { + OS << "Pattern : " + << Results[I].Pattern->getAsString() << '\n'; + break; + } + } + } +} + +void +PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, + unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates) { + for (unsigned I = 0; I != NumCandidates; ++I) { + if (CodeCompletionString *CCS + = Candidates[I].CreateSignatureString(CurrentArg, SemaRef, + Allocator)) { + OS << "OVERLOAD: " << CCS->getAsString() << "\n"; + } + } +} + +void CodeCompletionResult::computeCursorKindAndAvailability() { + switch (Kind) { + case RK_Declaration: + // Set the availability based on attributes. + switch (Declaration->getAvailability()) { + case AR_Available: + case AR_NotYetIntroduced: + Availability = CXAvailability_Available; + break; + + case AR_Deprecated: + Availability = CXAvailability_Deprecated; + break; + + case AR_Unavailable: + Availability = CXAvailability_NotAvailable; + break; + } + + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration)) + if (Function->isDeleted()) + Availability = CXAvailability_NotAvailable; + + CursorKind = getCursorKindForDecl(Declaration); + if (CursorKind == CXCursor_UnexposedDecl) + CursorKind = CXCursor_NotImplemented; + break; + + case RK_Macro: + Availability = CXAvailability_Available; + CursorKind = CXCursor_MacroDefinition; + break; + + case RK_Keyword: + Availability = CXAvailability_Available; + CursorKind = CXCursor_NotImplemented; + break; + + case RK_Pattern: + // Do nothing: Patterns can come with cursor kinds! + break; + } +} + +/// \brief Retrieve the name that should be used to order a result. +/// +/// If the name needs to be constructed as a string, that string will be +/// saved into Saved and the returned StringRef will refer to it. +static llvm::StringRef getOrderedName(const CodeCompletionResult &R, + std::string &Saved) { + switch (R.Kind) { + case CodeCompletionResult::RK_Keyword: + return R.Keyword; + + case CodeCompletionResult::RK_Pattern: + return R.Pattern->getTypedText(); + + case CodeCompletionResult::RK_Macro: + return R.Macro->getName(); + + case CodeCompletionResult::RK_Declaration: + // Handle declarations below. + break; + } + + DeclarationName Name = R.Declaration->getDeclName(); + + // If the name is a simple identifier (by far the common case), or a + // zero-argument selector, just return a reference to that identifier. + if (IdentifierInfo *Id = Name.getAsIdentifierInfo()) + return Id->getName(); + if (Name.isObjCZeroArgSelector()) + if (IdentifierInfo *Id + = Name.getObjCSelector().getIdentifierInfoForSlot(0)) + return Id->getName(); + + Saved = Name.getAsString(); + return Saved; +} + +bool clang::operator<(const CodeCompletionResult &X, + const CodeCompletionResult &Y) { + std::string XSaved, YSaved; + llvm::StringRef XStr = getOrderedName(X, XSaved); + llvm::StringRef YStr = getOrderedName(Y, YSaved); + int cmp = XStr.compare_lower(YStr); + if (cmp) + return cmp < 0; + + // If case-insensitive comparison fails, try case-sensitive comparison. + cmp = XStr.compare(YStr); + if (cmp) + return cmp < 0; + + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp new file mode 100644 index 0000000..5be16e7 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/DeclSpec.cpp @@ -0,0 +1,845 @@ +//===--- SemaDeclSpec.cpp - Declaration Specifier Semantic Analysis -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for declaration specifiers. +// +//===----------------------------------------------------------------------===// + +#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +#include <cstring> +using namespace clang; + + +static DiagnosticBuilder Diag(Diagnostic &D, SourceLocation Loc, + unsigned DiagID) { + return D.Report(Loc, DiagID); +} + + +void UnqualifiedId::setTemplateId(TemplateIdAnnotation *TemplateId) { + assert(TemplateId && "NULL template-id annotation?"); + Kind = IK_TemplateId; + this->TemplateId = TemplateId; + StartLocation = TemplateId->TemplateNameLoc; + EndLocation = TemplateId->RAngleLoc; +} + +void UnqualifiedId::setConstructorTemplateId(TemplateIdAnnotation *TemplateId) { + assert(TemplateId && "NULL template-id annotation?"); + Kind = IK_ConstructorTemplateId; + this->TemplateId = TemplateId; + StartLocation = TemplateId->TemplateNameLoc; + EndLocation = TemplateId->RAngleLoc; +} + +void CXXScopeSpec::Extend(ASTContext &Context, SourceLocation TemplateKWLoc, + TypeLoc TL, SourceLocation ColonColonLoc) { + Builder.Extend(Context, TemplateKWLoc, TL, ColonColonLoc); + if (Range.getBegin().isInvalid()) + Range.setBegin(TL.getBeginLoc()); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonColonLoc) { + Builder.Extend(Context, Identifier, IdentifierLoc, ColonColonLoc); + + if (Range.getBegin().isInvalid()) + Range.setBegin(IdentifierLoc); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, + SourceLocation ColonColonLoc) { + Builder.Extend(Context, Namespace, NamespaceLoc, ColonColonLoc); + + if (Range.getBegin().isInvalid()) + Range.setBegin(NamespaceLoc); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, + SourceLocation ColonColonLoc) { + Builder.Extend(Context, Alias, AliasLoc, ColonColonLoc); + + if (Range.getBegin().isInvalid()) + Range.setBegin(AliasLoc); + Range.setEnd(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeGlobal(ASTContext &Context, + SourceLocation ColonColonLoc) { + Builder.MakeGlobal(Context, ColonColonLoc); + + Range = SourceRange(ColonColonLoc); + + assert(Range == Builder.getSourceRange() && + "NestedNameSpecifierLoc range computation incorrect"); +} + +void CXXScopeSpec::MakeTrivial(ASTContext &Context, + NestedNameSpecifier *Qualifier, SourceRange R) { + Builder.MakeTrivial(Context, Qualifier, R); + Range = R; +} + +void CXXScopeSpec::Adopt(NestedNameSpecifierLoc Other) { + if (!Other) { + Range = SourceRange(); + Builder.Clear(); + return; + } + + Range = Other.getSourceRange(); + Builder.Adopt(Other); +} + +NestedNameSpecifierLoc +CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { + if (!Builder.getRepresentation()) + return NestedNameSpecifierLoc(); + + return Builder.getWithLocInContext(Context); +} + +/// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. +/// "TheDeclarator" is the declarator that this will be added to. +DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, + SourceLocation EllipsisLoc, + ParamInfo *ArgInfo, + unsigned NumArgs, + unsigned TypeQuals, + bool RefQualifierIsLvalueRef, + SourceLocation RefQualifierLoc, + ExceptionSpecificationType + ESpecType, + SourceLocation ESpecLoc, + ParsedType *Exceptions, + SourceRange *ExceptionRanges, + unsigned NumExceptions, + Expr *NoexceptExpr, + SourceLocation LocalRangeBegin, + SourceLocation LocalRangeEnd, + Declarator &TheDeclarator, + ParsedType TrailingReturnType) { + DeclaratorChunk I; + I.Kind = Function; + I.Loc = LocalRangeBegin; + I.EndLoc = LocalRangeEnd; + I.Fun.AttrList = 0; + I.Fun.hasPrototype = hasProto; + I.Fun.isVariadic = isVariadic; + I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); + I.Fun.DeleteArgInfo = false; + I.Fun.TypeQuals = TypeQuals; + I.Fun.NumArgs = NumArgs; + I.Fun.ArgInfo = 0; + I.Fun.RefQualifierIsLValueRef = RefQualifierIsLvalueRef; + I.Fun.RefQualifierLoc = RefQualifierLoc.getRawEncoding(); + I.Fun.ExceptionSpecType = ESpecType; + I.Fun.ExceptionSpecLoc = ESpecLoc.getRawEncoding(); + I.Fun.NumExceptions = 0; + I.Fun.Exceptions = 0; + I.Fun.NoexceptExpr = 0; + I.Fun.TrailingReturnType = TrailingReturnType.getAsOpaquePtr(); + + // new[] an argument array if needed. + if (NumArgs) { + // If the 'InlineParams' in Declarator is unused and big enough, put our + // parameter list there (in an effort to avoid new/delete traffic). If it + // is already used (consider a function returning a function pointer) or too + // small (function taking too many arguments), go to the heap. + if (!TheDeclarator.InlineParamsUsed && + NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) { + I.Fun.ArgInfo = TheDeclarator.InlineParams; + I.Fun.DeleteArgInfo = false; + TheDeclarator.InlineParamsUsed = true; + } else { + I.Fun.ArgInfo = new DeclaratorChunk::ParamInfo[NumArgs]; + I.Fun.DeleteArgInfo = true; + } + memcpy(I.Fun.ArgInfo, ArgInfo, sizeof(ArgInfo[0])*NumArgs); + } + + // Check what exception specification information we should actually store. + switch (ESpecType) { + default: break; // By default, save nothing. + case EST_Dynamic: + // new[] an exception array if needed + if (NumExceptions) { + I.Fun.NumExceptions = NumExceptions; + I.Fun.Exceptions = new DeclaratorChunk::TypeAndRange[NumExceptions]; + for (unsigned i = 0; i != NumExceptions; ++i) { + I.Fun.Exceptions[i].Ty = Exceptions[i]; + I.Fun.Exceptions[i].Range = ExceptionRanges[i]; + } + } + break; + + case EST_ComputedNoexcept: + I.Fun.NoexceptExpr = NoexceptExpr; + break; + } + return I; +} + +/// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this +/// declaration specifier includes. +/// +unsigned DeclSpec::getParsedSpecifiers() const { + unsigned Res = 0; + if (StorageClassSpec != SCS_unspecified || + SCS_thread_specified) + Res |= PQ_StorageClassSpecifier; + + if (TypeQualifiers != TQ_unspecified) + Res |= PQ_TypeQualifier; + + if (hasTypeSpecifier()) + Res |= PQ_TypeSpecifier; + + if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified) + Res |= PQ_FunctionSpecifier; + return Res; +} + +template <class T> static bool BadSpecifier(T TNew, T TPrev, + const char *&PrevSpec, + unsigned &DiagID) { + PrevSpec = DeclSpec::getSpecifierName(TPrev); + DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec + : diag::err_invalid_decl_spec_combination); + return true; +} + +const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) { + switch (S) { + case DeclSpec::SCS_unspecified: return "unspecified"; + case DeclSpec::SCS_typedef: return "typedef"; + case DeclSpec::SCS_extern: return "extern"; + case DeclSpec::SCS_static: return "static"; + case DeclSpec::SCS_auto: return "auto"; + case DeclSpec::SCS_register: return "register"; + case DeclSpec::SCS_private_extern: return "__private_extern__"; + case DeclSpec::SCS_mutable: return "mutable"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(TSW W) { + switch (W) { + case TSW_unspecified: return "unspecified"; + case TSW_short: return "short"; + case TSW_long: return "long"; + case TSW_longlong: return "long long"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(TSC C) { + switch (C) { + case TSC_unspecified: return "unspecified"; + case TSC_imaginary: return "imaginary"; + case TSC_complex: return "complex"; + } + llvm_unreachable("Unknown typespec!"); +} + + +const char *DeclSpec::getSpecifierName(TSS S) { + switch (S) { + case TSS_unspecified: return "unspecified"; + case TSS_signed: return "signed"; + case TSS_unsigned: return "unsigned"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { + switch (T) { + case DeclSpec::TST_unspecified: return "unspecified"; + case DeclSpec::TST_void: return "void"; + case DeclSpec::TST_char: return "char"; + case DeclSpec::TST_wchar: return "wchar_t"; + case DeclSpec::TST_char16: return "char16_t"; + case DeclSpec::TST_char32: return "char32_t"; + case DeclSpec::TST_int: return "int"; + case DeclSpec::TST_float: return "float"; + case DeclSpec::TST_double: return "double"; + case DeclSpec::TST_bool: return "_Bool"; + case DeclSpec::TST_decimal32: return "_Decimal32"; + case DeclSpec::TST_decimal64: return "_Decimal64"; + case DeclSpec::TST_decimal128: return "_Decimal128"; + case DeclSpec::TST_enum: return "enum"; + case DeclSpec::TST_class: return "class"; + case DeclSpec::TST_union: return "union"; + case DeclSpec::TST_struct: return "struct"; + case DeclSpec::TST_typename: return "type-name"; + case DeclSpec::TST_typeofType: + case DeclSpec::TST_typeofExpr: return "typeof"; + case DeclSpec::TST_auto: return "auto"; + case DeclSpec::TST_decltype: return "(decltype)"; + case DeclSpec::TST_underlyingType: return "__underlying_type"; + case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; + case DeclSpec::TST_error: return "(error)"; + } + llvm_unreachable("Unknown typespec!"); +} + +const char *DeclSpec::getSpecifierName(TQ T) { + switch (T) { + case DeclSpec::TQ_unspecified: return "unspecified"; + case DeclSpec::TQ_const: return "const"; + case DeclSpec::TQ_restrict: return "restrict"; + case DeclSpec::TQ_volatile: return "volatile"; + } + llvm_unreachable("Unknown typespec!"); +} + +bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + const LangOptions &Lang) { + // OpenCL prohibits extern, auto, register, and static + // It seems sensible to prohibit private_extern too + if (Lang.OpenCL) { + switch (S) { + case SCS_extern: + case SCS_private_extern: + case SCS_auto: + case SCS_register: + case SCS_static: + DiagID = diag::err_not_opencl_storage_class_specifier; + PrevSpec = getSpecifierName(S); + return true; + default: + break; + } + } + + if (StorageClassSpec != SCS_unspecified) { + // Changing storage class is allowed only if the previous one + // was the 'extern' that is part of a linkage specification and + // the new storage class is 'typedef'. + if (!(SCS_extern_in_linkage_spec && + StorageClassSpec == SCS_extern && + S == SCS_typedef)) + return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID); + } + StorageClassSpec = S; + StorageClassSpecLoc = Loc; + assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield"); + return false; +} + +bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (SCS_thread_specified) { + PrevSpec = "__thread"; + DiagID = diag::ext_duplicate_declspec; + return true; + } + SCS_thread_specified = true; + SCS_threadLoc = Loc; + return false; +} + +/// These methods set the specified attribute of the DeclSpec, but return true +/// and ignore the request if invalid (e.g. "extern" then "auto" is +/// specified). +bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + // Overwrite TSWLoc only if TypeSpecWidth was unspecified, so that + // for 'long long' we will keep the source location of the first 'long'. + if (TypeSpecWidth == TSW_unspecified) + TSWLoc = Loc; + // Allow turning long -> long long. + else if (W != TSW_longlong || TypeSpecWidth != TSW_long) + return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID); + TypeSpecWidth = W; + if (TypeAltiVecVector && !TypeAltiVecBool && + ((TypeSpecWidth == TSW_long) || (TypeSpecWidth == TSW_longlong))) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::warn_vector_long_decl_spec_combination; + return true; + } + return false; +} + +bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (TypeSpecComplex != TSC_unspecified) + return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID); + TypeSpecComplex = C; + TSCLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + if (TypeSpecSign != TSS_unspecified) + return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID); + TypeSpecSign = S; + TSSLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + ParsedType Rep) { + return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep); +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, + const char *&PrevSpec, + unsigned &DiagID, + ParsedType Rep) { + assert(isTypeRep(T) && "T does not store a type"); + assert(Rep && "no type provided!"); + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + TypeSpecType = T; + TypeRep = Rep; + TSTLoc = TagKwLoc; + TSTNameLoc = TagNameLoc; + TypeSpecOwned = false; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + Expr *Rep) { + assert(isExprRep(T) && "T does not store an expr"); + assert(Rep && "no expression provided!"); + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + TypeSpecType = T; + ExprRep = Rep; + TSTLoc = Loc; + TSTNameLoc = Loc; + TypeSpecOwned = false; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID, + Decl *Rep, bool Owned) { + return SetTypeSpecType(T, Loc, Loc, PrevSpec, DiagID, Rep, Owned); +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, + const char *&PrevSpec, + unsigned &DiagID, + Decl *Rep, bool Owned) { + assert(isDeclRep(T) && "T does not store a decl"); + // Unlike the other cases, we don't assert that we actually get a decl. + + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + TypeSpecType = T; + DeclRep = Rep; + TSTLoc = TagKwLoc; + TSTNameLoc = TagNameLoc; + TypeSpecOwned = Owned; + return false; +} + +bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc, + const char *&PrevSpec, + unsigned &DiagID) { + assert(!isDeclRep(T) && !isTypeRep(T) && !isExprRep(T) && + "rep required for these type-spec kinds!"); + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_decl_spec_combination; + return true; + } + TSTLoc = Loc; + TSTNameLoc = Loc; + if (TypeAltiVecVector && (T == TST_bool) && !TypeAltiVecBool) { + TypeAltiVecBool = true; + return false; + } + TypeSpecType = T; + TypeSpecOwned = false; + if (TypeAltiVecVector && !TypeAltiVecBool && (TypeSpecType == TST_double)) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_vector_decl_spec; + return true; + } + return false; +} + +bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + if (TypeSpecType != TST_unspecified) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_vector_decl_spec_combination; + return true; + } + TypeAltiVecVector = isAltiVecVector; + AltiVecLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + if (!TypeAltiVecVector || TypeAltiVecPixel || + (TypeSpecType != TST_unspecified)) { + PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType); + DiagID = diag::err_invalid_pixel_decl_spec_combination; + return true; + } + TypeAltiVecPixel = isAltiVecPixel; + TSTLoc = Loc; + TSTNameLoc = Loc; + return false; +} + +bool DeclSpec::SetTypeSpecError() { + TypeSpecType = TST_error; + TypeSpecOwned = false; + TSTLoc = SourceLocation(); + TSTNameLoc = SourceLocation(); + return false; +} + +bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID, const LangOptions &Lang) { + // Duplicates turn into warnings pre-C99. + if ((TypeQualifiers & T) && !Lang.C99) + return BadSpecifier(T, T, PrevSpec, DiagID); + TypeQualifiers |= T; + + switch (T) { + default: assert(0 && "Unknown type qualifier!"); + case TQ_const: TQ_constLoc = Loc; break; + case TQ_restrict: TQ_restrictLoc = Loc; break; + case TQ_volatile: TQ_volatileLoc = Loc; break; + } + return false; +} + +bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'inline inline' is ok. + FS_inline_specified = true; + FS_inlineLoc = Loc; + return false; +} + +bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'virtual virtual' is ok. + FS_virtual_specified = true; + FS_virtualLoc = Loc; + return false; +} + +bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'explicit explicit' is ok. + FS_explicit_specified = true; + FS_explicitLoc = Loc; + return false; +} + +bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + if (Friend_specified) { + PrevSpec = "friend"; + DiagID = diag::ext_duplicate_declspec; + return true; + } + + Friend_specified = true; + FriendLoc = Loc; + return false; +} + +bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + // 'constexpr constexpr' is ok. + Constexpr_specified = true; + ConstexprLoc = Loc; + return false; +} + +void DeclSpec::setProtocolQualifiers(Decl * const *Protos, + unsigned NP, + SourceLocation *ProtoLocs, + SourceLocation LAngleLoc) { + if (NP == 0) return; + ProtocolQualifiers = new Decl*[NP]; + ProtocolLocs = new SourceLocation[NP]; + memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP); + memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP); + NumProtocolQualifiers = NP; + ProtocolLAngleLoc = LAngleLoc; +} + +void DeclSpec::SaveWrittenBuiltinSpecs() { + writtenBS.Sign = getTypeSpecSign(); + writtenBS.Width = getTypeSpecWidth(); + writtenBS.Type = getTypeSpecType(); + // Search the list of attributes for the presence of a mode attribute. + writtenBS.ModeAttr = false; + AttributeList* attrs = getAttributes().getList(); + while (attrs) { + if (attrs->getKind() == AttributeList::AT_mode) { + writtenBS.ModeAttr = true; + break; + } + attrs = attrs->getNext(); + } +} + +void DeclSpec::SaveStorageSpecifierAsWritten() { + if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern) + // If 'extern' is part of a linkage specification, + // then it is not a storage class "as written". + StorageClassSpecAsWritten = SCS_unspecified; + else + StorageClassSpecAsWritten = StorageClassSpec; +} + +/// Finish - This does final analysis of the declspec, rejecting things like +/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or +/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method, +/// DeclSpec is guaranteed self-consistent, even if an error occurred. +void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) { + // Before possibly changing their values, save specs as written. + SaveWrittenBuiltinSpecs(); + SaveStorageSpecifierAsWritten(); + + // Check the type specifier components first. + + // Validate and finalize AltiVec vector declspec. + if (TypeAltiVecVector) { + if (TypeAltiVecBool) { + // Sign specifiers are not allowed with vector bool. (PIM 2.1) + if (TypeSpecSign != TSS_unspecified) { + Diag(D, TSSLoc, diag::err_invalid_vector_bool_decl_spec) + << getSpecifierName((TSS)TypeSpecSign); + } + + // Only char/int are valid with vector bool. (PIM 2.1) + if (((TypeSpecType != TST_unspecified) && (TypeSpecType != TST_char) && + (TypeSpecType != TST_int)) || TypeAltiVecPixel) { + Diag(D, TSTLoc, diag::err_invalid_vector_bool_decl_spec) + << (TypeAltiVecPixel ? "__pixel" : + getSpecifierName((TST)TypeSpecType)); + } + + // Only 'short' is valid with vector bool. (PIM 2.1) + if ((TypeSpecWidth != TSW_unspecified) && (TypeSpecWidth != TSW_short)) + Diag(D, TSWLoc, diag::err_invalid_vector_bool_decl_spec) + << getSpecifierName((TSW)TypeSpecWidth); + + // Elements of vector bool are interpreted as unsigned. (PIM 2.1) + if ((TypeSpecType == TST_char) || (TypeSpecType == TST_int) || + (TypeSpecWidth != TSW_unspecified)) + TypeSpecSign = TSS_unsigned; + } + + if (TypeAltiVecPixel) { + //TODO: perform validation + TypeSpecType = TST_int; + TypeSpecSign = TSS_unsigned; + TypeSpecWidth = TSW_short; + TypeSpecOwned = false; + } + } + + // signed/unsigned are only valid with int/char/wchar_t. + if (TypeSpecSign != TSS_unspecified) { + if (TypeSpecType == TST_unspecified) + TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. + else if (TypeSpecType != TST_int && + TypeSpecType != TST_char && TypeSpecType != TST_wchar) { + Diag(D, TSSLoc, diag::err_invalid_sign_spec) + << getSpecifierName((TST)TypeSpecType); + // signed double -> double. + TypeSpecSign = TSS_unspecified; + } + } + + // Validate the width of the type. + switch (TypeSpecWidth) { + case TSW_unspecified: break; + case TSW_short: // short int + case TSW_longlong: // long long int + if (TypeSpecType == TST_unspecified) + TypeSpecType = TST_int; // short -> short int, long long -> long long int. + else if (TypeSpecType != TST_int) { + Diag(D, TSWLoc, + TypeSpecWidth == TSW_short ? diag::err_invalid_short_spec + : diag::err_invalid_longlong_spec) + << getSpecifierName((TST)TypeSpecType); + TypeSpecType = TST_int; + TypeSpecOwned = false; + } + break; + case TSW_long: // long double, long int + if (TypeSpecType == TST_unspecified) + TypeSpecType = TST_int; // long -> long int. + else if (TypeSpecType != TST_int && TypeSpecType != TST_double) { + Diag(D, TSWLoc, diag::err_invalid_long_spec) + << getSpecifierName((TST)TypeSpecType); + TypeSpecType = TST_int; + TypeSpecOwned = false; + } + break; + } + + // TODO: if the implementation does not implement _Complex or _Imaginary, + // disallow their use. Need information about the backend. + if (TypeSpecComplex != TSC_unspecified) { + if (TypeSpecType == TST_unspecified) { + Diag(D, TSCLoc, diag::ext_plain_complex) + << FixItHint::CreateInsertion( + PP.getLocForEndOfToken(getTypeSpecComplexLoc()), + " double"); + TypeSpecType = TST_double; // _Complex -> _Complex double. + } else if (TypeSpecType == TST_int || TypeSpecType == TST_char) { + // Note that this intentionally doesn't include _Complex _Bool. + Diag(D, TSTLoc, diag::ext_integer_complex); + } else if (TypeSpecType != TST_float && TypeSpecType != TST_double) { + Diag(D, TSCLoc, diag::err_invalid_complex_spec) + << getSpecifierName((TST)TypeSpecType); + TypeSpecComplex = TSC_unspecified; + } + } + + // C++ [class.friend]p6: + // No storage-class-specifier shall appear in the decl-specifier-seq + // of a friend declaration. + if (isFriendSpecified() && getStorageClassSpec()) { + DeclSpec::SCS SC = getStorageClassSpec(); + const char *SpecName = getSpecifierName(SC); + + SourceLocation SCLoc = getStorageClassSpecLoc(); + SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName)); + + Diag(D, SCLoc, diag::err_friend_storage_spec) + << SpecName + << FixItHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc)); + + ClearStorageClassSpecs(); + } + + assert(!TypeSpecOwned || isDeclRep((TST) TypeSpecType)); + + // Okay, now we can infer the real type. + + // TODO: return "auto function" and other bad things based on the real type. + + // 'data definition has no type or storage class'? +} + +bool DeclSpec::isMissingDeclaratorOk() { + TST tst = getTypeSpecType(); + return isDeclRep(tst) && getRepAsDecl() != 0 && + StorageClassSpec != DeclSpec::SCS_typedef; +} + +void UnqualifiedId::clear() { + if (Kind == IK_TemplateId) + TemplateId->Destroy(); + + Kind = IK_Identifier; + Identifier = 0; + StartLocation = SourceLocation(); + EndLocation = SourceLocation(); +} + +void UnqualifiedId::setOperatorFunctionId(SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + SourceLocation SymbolLocations[3]) { + Kind = IK_OperatorFunctionId; + StartLocation = OperatorLoc; + EndLocation = OperatorLoc; + OperatorFunctionId.Operator = Op; + for (unsigned I = 0; I != 3; ++I) { + OperatorFunctionId.SymbolLocations[I] = SymbolLocations[I].getRawEncoding(); + + if (SymbolLocations[I].isValid()) + EndLocation = SymbolLocations[I]; + } +} + +bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc, + const char *&PrevSpec) { + LastLocation = Loc; + + if (Specifiers & VS) { + PrevSpec = getSpecifierName(VS); + return true; + } + + Specifiers |= VS; + + switch (VS) { + default: assert(0 && "Unknown specifier!"); + case VS_Override: VS_overrideLoc = Loc; break; + case VS_Final: VS_finalLoc = Loc; break; + } + + return false; +} + +const char *VirtSpecifiers::getSpecifierName(Specifier VS) { + switch (VS) { + default: assert(0 && "Unknown specifier"); + case VS_Override: return "override"; + case VS_Final: return "final"; + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp new file mode 100644 index 0000000..af548fe --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/DelayedDiagnostic.cpp @@ -0,0 +1,51 @@ +//===--- DelayedDiagnostic.cpp - Delayed declarator diagnostics -*- 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 the DelayedDiagnostic class implementation, which +// is used to record diagnostics that are being conditionally produced +// during declarator parsing. +// +// This file also defines AccessedEntity. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/DelayedDiagnostic.h" +#include <string.h> +using namespace clang; +using namespace sema; + +DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, + const NamedDecl *D, + llvm::StringRef Msg) { + DelayedDiagnostic DD; + DD.Kind = Deprecation; + DD.Triggered = false; + DD.Loc = Loc; + DD.DeprecationData.Decl = D; + char *MessageData = 0; + if (Msg.size()) { + MessageData = new char [Msg.size()]; + memcpy(MessageData, Msg.data(), Msg.size()); + } + + DD.DeprecationData.Message = MessageData; + DD.DeprecationData.MessageLen = Msg.size(); + return DD; +} + +void DelayedDiagnostic::Destroy() { + switch (Kind) { + case Access: + getAccessData().~AccessedEntity(); + break; + + case Deprecation: + delete [] DeprecationData.Message; + break; + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp new file mode 100644 index 0000000..95420a3 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/IdentifierResolver.cpp @@ -0,0 +1,330 @@ +//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the IdentifierResolver class, which is used for lexical +// scoped lookup, based on declaration names. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/IdentifierResolver.h" +#include "clang/Sema/Scope.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/LangOptions.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// IdDeclInfoMap class +//===----------------------------------------------------------------------===// + +/// IdDeclInfoMap - Associates IdDeclInfos with declaration names. +/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each +/// individual IdDeclInfo to heap. +class IdentifierResolver::IdDeclInfoMap { + static const unsigned int POOL_SIZE = 512; + + /// We use our own linked-list implementation because it is sadly + /// impossible to add something to a pre-C++0x STL container without + /// a completely unnecessary copy. + struct IdDeclInfoPool { + IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {} + + IdDeclInfoPool *Next; + IdDeclInfo Pool[POOL_SIZE]; + }; + + IdDeclInfoPool *CurPool; + unsigned int CurIndex; + +public: + IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {} + + ~IdDeclInfoMap() { + IdDeclInfoPool *Cur = CurPool; + while (IdDeclInfoPool *P = Cur) { + Cur = Cur->Next; + delete P; + } + } + + /// Returns the IdDeclInfo associated to the DeclarationName. + /// It creates a new IdDeclInfo if one was not created before for this id. + IdDeclInfo &operator[](DeclarationName Name); +}; + + +//===----------------------------------------------------------------------===// +// IdDeclInfo Implementation +//===----------------------------------------------------------------------===// + +/// RemoveDecl - Remove the decl from the scope chain. +/// The decl must already be part of the decl chain. +void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) { + for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { + if (D == *(I-1)) { + Decls.erase(I-1); + return; + } + } + + assert(0 && "Didn't find this decl on its identifier's chain!"); +} + +bool +IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { + for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) { + if (Old == *(I-1)) { + *(I - 1) = New; + return true; + } + } + + return false; +} + + +//===----------------------------------------------------------------------===// +// IdentifierResolver Implementation +//===----------------------------------------------------------------------===// + +IdentifierResolver::IdentifierResolver(const LangOptions &langOpt) + : LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) { +} +IdentifierResolver::~IdentifierResolver() { + delete IdDeclInfos; +} + +/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true +/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns +/// true if 'D' belongs to the given declaration context. +bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, + ASTContext &Context, Scope *S, + bool ExplicitInstantiationOrSpecialization) const { + Ctx = Ctx->getRedeclContext(); + + if (Ctx->isFunctionOrMethod()) { + // Ignore the scopes associated within transparent declaration contexts. + while (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) + S = S->getParent(); + + if (S->isDeclScope(D)) + return true; + if (LangOpt.CPlusPlus) { + // C++ 3.3.2p3: + // The name declared in a catch exception-declaration is local to the + // handler and shall not be redeclared in the outermost block of the + // handler. + // C++ 3.3.2p4: + // Names declared in the for-init-statement, and in the condition of if, + // while, for, and switch statements are local to the if, while, for, or + // switch statement (including the controlled statement), and shall not be + // redeclared in a subsequent condition of that statement nor in the + // outermost block (or, for the if statement, any of the outermost blocks) + // of the controlled statement. + // + assert(S->getParent() && "No TUScope?"); + if (S->getParent()->getFlags() & Scope::ControlScope) + return S->getParent()->isDeclScope(D); + } + return false; + } + + DeclContext *DCtx = D->getDeclContext()->getRedeclContext(); + return ExplicitInstantiationOrSpecialization + ? Ctx->InEnclosingNamespaceSetOf(DCtx) + : Ctx->Equals(DCtx); +} + +/// AddDecl - Link the decl to its shadowed decl chain. +void IdentifierResolver::AddDecl(NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + + void *Ptr = Name.getFETokenInfo<void>(); + + if (!Ptr) { + Name.setFETokenInfo(D); + return; + } + + IdDeclInfo *IDI; + + if (isDeclPtr(Ptr)) { + Name.setFETokenInfo(NULL); + IDI = &(*IdDeclInfos)[Name]; + NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); + IDI->AddDecl(PrevD); + } else + IDI = toIdDeclInfo(Ptr); + + IDI->AddDecl(D); +} + +void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) { + DeclarationName Name = D->getDeclName(); + void *Ptr = Name.getFETokenInfo<void>(); + + if (!Ptr) { + AddDecl(D); + return; + } + + if (isDeclPtr(Ptr)) { + // We only have a single declaration: insert before or after it, + // as appropriate. + if (Pos == iterator()) { + // Add the new declaration before the existing declaration. + NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); + RemoveDecl(PrevD); + AddDecl(D); + AddDecl(PrevD); + } else { + // Add new declaration after the existing declaration. + AddDecl(D); + } + + return; + } + + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + + // General case: insert the declaration at the appropriate point in the + // list, which already has at least two elements. + IdDeclInfo *IDI = toIdDeclInfo(Ptr); + if (Pos.isIterator()) { + IDI->InsertDecl(Pos.getIterator() + 1, D); + } else + IDI->InsertDecl(IDI->decls_begin(), D); +} + +/// RemoveDecl - Unlink the decl from its shadowed decl chain. +/// The decl must already be part of the decl chain. +void IdentifierResolver::RemoveDecl(NamedDecl *D) { + assert(D && "null param passed"); + DeclarationName Name = D->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + + void *Ptr = Name.getFETokenInfo<void>(); + + assert(Ptr && "Didn't find this decl on its identifier's chain!"); + + if (isDeclPtr(Ptr)) { + assert(D == Ptr && "Didn't find this decl on its identifier's chain!"); + Name.setFETokenInfo(NULL); + return; + } + + return toIdDeclInfo(Ptr)->RemoveDecl(D); +} + +bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) { + assert(Old->getDeclName() == New->getDeclName() && + "Cannot replace a decl with another decl of a different name"); + + DeclarationName Name = Old->getDeclName(); + if (IdentifierInfo *II = Name.getAsIdentifierInfo()) + II->setIsFromAST(false); + + void *Ptr = Name.getFETokenInfo<void>(); + + if (!Ptr) + return false; + + if (isDeclPtr(Ptr)) { + if (Ptr == Old) { + Name.setFETokenInfo(New); + return true; + } + return false; + } + + return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New); +} + +/// begin - Returns an iterator for decls with name 'Name'. +IdentifierResolver::iterator +IdentifierResolver::begin(DeclarationName Name) { + void *Ptr = Name.getFETokenInfo<void>(); + if (!Ptr) return end(); + + if (isDeclPtr(Ptr)) + return iterator(static_cast<NamedDecl*>(Ptr)); + + IdDeclInfo *IDI = toIdDeclInfo(Ptr); + + IdDeclInfo::DeclsTy::iterator I = IDI->decls_end(); + if (I != IDI->decls_begin()) + return iterator(I-1); + // No decls found. + return end(); +} + +void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II, + NamedDecl *D) { + II->setIsFromAST(false); + void *Ptr = II->getFETokenInfo<void>(); + + if (!Ptr) { + II->setFETokenInfo(D); + return; + } + + IdDeclInfo *IDI; + + if (isDeclPtr(Ptr)) { + II->setFETokenInfo(NULL); + IDI = &(*IdDeclInfos)[II]; + NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr); + IDI->AddDecl(PrevD); + } else + IDI = toIdDeclInfo(Ptr); + + IDI->AddDecl(D); +} + +//===----------------------------------------------------------------------===// +// IdDeclInfoMap Implementation +//===----------------------------------------------------------------------===// + +/// Returns the IdDeclInfo associated to the DeclarationName. +/// It creates a new IdDeclInfo if one was not created before for this id. +IdentifierResolver::IdDeclInfo & +IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { + void *Ptr = Name.getFETokenInfo<void>(); + + if (Ptr) return *toIdDeclInfo(Ptr); + + if (CurIndex == POOL_SIZE) { + CurPool = new IdDeclInfoPool(CurPool); + CurIndex = 0; + } + IdDeclInfo *IDI = &CurPool->Pool[CurIndex]; + Name.setFETokenInfo(reinterpret_cast<void*>( + reinterpret_cast<uintptr_t>(IDI) | 0x1) + ); + ++CurIndex; + return *IDI; +} + +void IdentifierResolver::iterator::incrementSlowCase() { + NamedDecl *D = **this; + void *InfoPtr = D->getDeclName().getFETokenInfo<void>(); + assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?"); + IdDeclInfo *Info = toIdDeclInfo(InfoPtr); + + BaseIter I = getIterator(); + if (I != Info->decls_begin()) + *this = iterator(I-1); + else // No more decls. + *this = iterator(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp new file mode 100644 index 0000000..ae154aa --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -0,0 +1,603 @@ +//===--- JumpDiagnostics.cpp - Analyze Jump Targets for VLA issues --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the JumpScopeChecker class, which is used to diagnose +// jumps that enter a VLA scope in an invalid way. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtCXX.h" +#include "llvm/ADT/BitVector.h" +using namespace clang; + +namespace { + +/// JumpScopeChecker - This object is used by Sema to diagnose invalid jumps +/// into VLA and other protected scopes. For example, this rejects: +/// goto L; +/// int a[n]; +/// L: +/// +class JumpScopeChecker { + Sema &S; + + /// GotoScope - This is a record that we use to keep track of all of the + /// scopes that are introduced by VLAs and other things that scope jumps like + /// gotos. This scope tree has nothing to do with the source scope tree, + /// because you can have multiple VLA scopes per compound statement, and most + /// compound statements don't introduce any scopes. + struct GotoScope { + /// ParentScope - The index in ScopeMap of the parent scope. This is 0 for + /// the parent scope is the function body. + unsigned ParentScope; + + /// InDiag - The diagnostic to emit if there is a jump into this scope. + unsigned InDiag; + + /// OutDiag - The diagnostic to emit if there is an indirect jump out + /// of this scope. Direct jumps always clean up their current scope + /// in an orderly way. + unsigned OutDiag; + + /// Loc - Location to emit the diagnostic. + SourceLocation Loc; + + GotoScope(unsigned parentScope, unsigned InDiag, unsigned OutDiag, + SourceLocation L) + : ParentScope(parentScope), InDiag(InDiag), OutDiag(OutDiag), Loc(L) {} + }; + + llvm::SmallVector<GotoScope, 48> Scopes; + llvm::DenseMap<Stmt*, unsigned> LabelAndGotoScopes; + llvm::SmallVector<Stmt*, 16> Jumps; + + llvm::SmallVector<IndirectGotoStmt*, 4> IndirectJumps; + llvm::SmallVector<LabelDecl*, 4> IndirectJumpTargets; +public: + JumpScopeChecker(Stmt *Body, Sema &S); +private: + void BuildScopeInformation(Decl *D, unsigned &ParentScope); + void BuildScopeInformation(Stmt *S, unsigned ParentScope); + void VerifyJumps(); + void VerifyIndirectJumps(); + void DiagnoseIndirectJump(IndirectGotoStmt *IG, unsigned IGScope, + LabelDecl *Target, unsigned TargetScope); + void CheckJump(Stmt *From, Stmt *To, + SourceLocation DiagLoc, unsigned JumpDiag); + + unsigned GetDeepestCommonScope(unsigned A, unsigned B); +}; +} // end anonymous namespace + + +JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) { + // Add a scope entry for function scope. + Scopes.push_back(GotoScope(~0U, ~0U, ~0U, SourceLocation())); + + // Build information for the top level compound statement, so that we have a + // defined scope record for every "goto" and label. + BuildScopeInformation(Body, 0); + + // Check that all jumps we saw are kosher. + VerifyJumps(); + VerifyIndirectJumps(); +} + +/// GetDeepestCommonScope - Finds the innermost scope enclosing the +/// two scopes. +unsigned JumpScopeChecker::GetDeepestCommonScope(unsigned A, unsigned B) { + while (A != B) { + // Inner scopes are created after outer scopes and therefore have + // higher indices. + if (A < B) { + assert(Scopes[B].ParentScope < B); + B = Scopes[B].ParentScope; + } else { + assert(Scopes[A].ParentScope < A); + A = Scopes[A].ParentScope; + } + } + return A; +} + +/// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a +/// diagnostic that should be emitted if control goes over it. If not, return 0. +static std::pair<unsigned,unsigned> + GetDiagForGotoScopeDecl(const Decl *D, bool isCPlusPlus) { + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + unsigned InDiag = 0, OutDiag = 0; + if (VD->getType()->isVariablyModifiedType()) + InDiag = diag::note_protected_by_vla; + + if (VD->hasAttr<BlocksAttr>()) { + InDiag = diag::note_protected_by___block; + OutDiag = diag::note_exits___block; + } else if (VD->hasAttr<CleanupAttr>()) { + InDiag = diag::note_protected_by_cleanup; + OutDiag = diag::note_exits_cleanup; + } else if (isCPlusPlus) { + if (!VD->hasLocalStorage()) + return std::make_pair(InDiag, OutDiag); + + ASTContext &Context = D->getASTContext(); + QualType T = Context.getBaseElementType(VD->getType()); + if (!T->isDependentType()) { + // C++0x [stmt.dcl]p3: + // A program that jumps from a point where a variable with automatic + // storage duration is not in scope to a point where it is in scope + // is ill-formed unless the variable has scalar type, class type with + // a trivial default constructor and a trivial destructor, a + // cv-qualified version of one of these types, or an array of one of + // the preceding types and is declared without an initializer (8.5). + // Check whether this is a C++ class. + CXXRecordDecl *Record = T->getAsCXXRecordDecl(); + + if (const Expr *Init = VD->getInit()) { + bool CallsTrivialConstructor = false; + if (Record) { + // FIXME: With generalized initializer lists, this may + // classify "X x{};" as having no initializer. + if (const CXXConstructExpr *Construct + = dyn_cast<CXXConstructExpr>(Init)) + if (const CXXConstructorDecl *Constructor + = Construct->getConstructor()) + if ((Context.getLangOptions().CPlusPlus0x + ? Record->hasTrivialDefaultConstructor() + : Record->isPOD()) && + Constructor->isDefaultConstructor()) + CallsTrivialConstructor = true; + } + + if (!CallsTrivialConstructor) + InDiag = diag::note_protected_by_variable_init; + } + + // Note whether we have a class with a non-trivial destructor. + if (Record && !Record->hasTrivialDestructor()) + OutDiag = diag::note_exits_dtor; + } + } + + return std::make_pair(InDiag, OutDiag); + } + + if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + if (TD->getUnderlyingType()->isVariablyModifiedType()) + return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0); + } + + if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) { + if (TD->getUnderlyingType()->isVariablyModifiedType()) + return std::make_pair((unsigned) diag::note_protected_by_vla_type_alias, 0); + } + + return std::make_pair(0U, 0U); +} + +/// \brief Build scope information for a declaration that is part of a DeclStmt. +void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) { + bool isCPlusPlus = this->S.getLangOptions().CPlusPlus; + + // If this decl causes a new scope, push and switch to it. + std::pair<unsigned,unsigned> Diags + = GetDiagForGotoScopeDecl(D, isCPlusPlus); + if (Diags.first || Diags.second) { + Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second, + D->getLocation())); + ParentScope = Scopes.size()-1; + } + + // If the decl has an initializer, walk it with the potentially new + // scope we just installed. + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + if (Expr *Init = VD->getInit()) + BuildScopeInformation(Init, ParentScope); +} + +/// BuildScopeInformation - The statements from CI to CE are known to form a +/// coherent VLA scope with a specified parent node. Walk through the +/// statements, adding any labels or gotos to LabelAndGotoScopes and recursively +/// walking the AST as needed. +void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { + bool SkipFirstSubStmt = false; + + // If we found a label, remember that it is in ParentScope scope. + switch (S->getStmtClass()) { + case Stmt::AddrLabelExprClass: + IndirectJumpTargets.push_back(cast<AddrLabelExpr>(S)->getLabel()); + break; + + case Stmt::IndirectGotoStmtClass: + // "goto *&&lbl;" is a special case which we treat as equivalent + // to a normal goto. In addition, we don't calculate scope in the + // operand (to avoid recording the address-of-label use), which + // works only because of the restricted set of expressions which + // we detect as constant targets. + if (cast<IndirectGotoStmt>(S)->getConstantTarget()) { + LabelAndGotoScopes[S] = ParentScope; + Jumps.push_back(S); + return; + } + + LabelAndGotoScopes[S] = ParentScope; + IndirectJumps.push_back(cast<IndirectGotoStmt>(S)); + break; + + case Stmt::SwitchStmtClass: + // Evaluate the condition variable before entering the scope of the switch + // statement. + if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) { + BuildScopeInformation(Var, ParentScope); + SkipFirstSubStmt = true; + } + // Fall through + + case Stmt::GotoStmtClass: + // Remember both what scope a goto is in as well as the fact that we have + // it. This makes the second scan not have to walk the AST again. + LabelAndGotoScopes[S] = ParentScope; + Jumps.push_back(S); + break; + + default: + break; + } + + for (Stmt::child_range CI = S->children(); CI; ++CI) { + if (SkipFirstSubStmt) { + SkipFirstSubStmt = false; + continue; + } + + Stmt *SubStmt = *CI; + if (SubStmt == 0) continue; + + // Cases, labels, and defaults aren't "scope parents". It's also + // important to handle these iteratively instead of recursively in + // order to avoid blowing out the stack. + while (true) { + Stmt *Next; + if (CaseStmt *CS = dyn_cast<CaseStmt>(SubStmt)) + Next = CS->getSubStmt(); + else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SubStmt)) + Next = DS->getSubStmt(); + else if (LabelStmt *LS = dyn_cast<LabelStmt>(SubStmt)) + Next = LS->getSubStmt(); + else + break; + + LabelAndGotoScopes[SubStmt] = ParentScope; + SubStmt = Next; + } + + // If this is a declstmt with a VLA definition, it defines a scope from here + // to the end of the containing context. + if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) { + // The decl statement creates a scope if any of the decls in it are VLAs + // or have the cleanup attribute. + for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); + I != E; ++I) + BuildScopeInformation(*I, ParentScope); + continue; + } + + // Disallow jumps into any part of an @try statement by pushing a scope and + // walking all sub-stmts in that scope. + if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) { + // Recursively walk the AST for the @try part. + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_try, + diag::note_exits_objc_try, + AT->getAtTryLoc())); + if (Stmt *TryPart = AT->getTryBody()) + BuildScopeInformation(TryPart, Scopes.size()-1); + + // Jump from the catch to the finally or try is not valid. + for (unsigned I = 0, N = AT->getNumCatchStmts(); I != N; ++I) { + ObjCAtCatchStmt *AC = AT->getCatchStmt(I); + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_catch, + diag::note_exits_objc_catch, + AC->getAtCatchLoc())); + // @catches are nested and it isn't + BuildScopeInformation(AC->getCatchBody(), Scopes.size()-1); + } + + // Jump from the finally to the try or catch is not valid. + if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) { + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_finally, + diag::note_exits_objc_finally, + AF->getAtFinallyLoc())); + BuildScopeInformation(AF, Scopes.size()-1); + } + + continue; + } + + // Disallow jumps into the protected statement of an @synchronized, but + // allow jumps into the object expression it protects. + if (ObjCAtSynchronizedStmt *AS = dyn_cast<ObjCAtSynchronizedStmt>(SubStmt)){ + // Recursively walk the AST for the @synchronized object expr, it is + // evaluated in the normal scope. + BuildScopeInformation(AS->getSynchExpr(), ParentScope); + + // Recursively walk the AST for the @synchronized part, protected by a new + // scope. + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_objc_synchronized, + diag::note_exits_objc_synchronized, + AS->getAtSynchronizedLoc())); + BuildScopeInformation(AS->getSynchBody(), Scopes.size()-1); + continue; + } + + // Disallow jumps into any part of a C++ try statement. This is pretty + // much the same as for Obj-C. + if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) { + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_try, + diag::note_exits_cxx_try, + TS->getSourceRange().getBegin())); + if (Stmt *TryBlock = TS->getTryBlock()) + BuildScopeInformation(TryBlock, Scopes.size()-1); + + // Jump from the catch into the try is not allowed either. + for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { + CXXCatchStmt *CS = TS->getHandler(I); + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_catch, + diag::note_exits_cxx_catch, + CS->getSourceRange().getBegin())); + BuildScopeInformation(CS->getHandlerBlock(), Scopes.size()-1); + } + + continue; + } + + // Recursively walk the AST. + BuildScopeInformation(SubStmt, ParentScope); + } +} + +/// VerifyJumps - Verify each element of the Jumps array to see if they are +/// valid, emitting diagnostics if not. +void JumpScopeChecker::VerifyJumps() { + while (!Jumps.empty()) { + Stmt *Jump = Jumps.pop_back_val(); + + // With a goto, + if (GotoStmt *GS = dyn_cast<GotoStmt>(Jump)) { + CheckJump(GS, GS->getLabel()->getStmt(), GS->getGotoLoc(), + diag::err_goto_into_protected_scope); + continue; + } + + // We only get indirect gotos here when they have a constant target. + if (IndirectGotoStmt *IGS = dyn_cast<IndirectGotoStmt>(Jump)) { + LabelDecl *Target = IGS->getConstantTarget(); + CheckJump(IGS, Target->getStmt(), IGS->getGotoLoc(), + diag::err_goto_into_protected_scope); + continue; + } + + SwitchStmt *SS = cast<SwitchStmt>(Jump); + for (SwitchCase *SC = SS->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + assert(LabelAndGotoScopes.count(SC) && "Case not visited?"); + CheckJump(SS, SC, SC->getLocStart(), + diag::err_switch_into_protected_scope); + } + } +} + +/// VerifyIndirectJumps - Verify whether any possible indirect jump +/// might cross a protection boundary. Unlike direct jumps, indirect +/// jumps count cleanups as protection boundaries: since there's no +/// way to know where the jump is going, we can't implicitly run the +/// right cleanups the way we can with direct jumps. +/// +/// Thus, an indirect jump is "trivial" if it bypasses no +/// initializations and no teardowns. More formally, an indirect jump +/// from A to B is trivial if the path out from A to DCA(A,B) is +/// trivial and the path in from DCA(A,B) to B is trivial, where +/// DCA(A,B) is the deepest common ancestor of A and B. +/// Jump-triviality is transitive but asymmetric. +/// +/// A path in is trivial if none of the entered scopes have an InDiag. +/// A path out is trivial is none of the exited scopes have an OutDiag. +/// +/// Under these definitions, this function checks that the indirect +/// jump between A and B is trivial for every indirect goto statement A +/// and every label B whose address was taken in the function. +void JumpScopeChecker::VerifyIndirectJumps() { + if (IndirectJumps.empty()) return; + + // If there aren't any address-of-label expressions in this function, + // complain about the first indirect goto. + if (IndirectJumpTargets.empty()) { + S.Diag(IndirectJumps[0]->getGotoLoc(), + diag::err_indirect_goto_without_addrlabel); + return; + } + + // Collect a single representative of every scope containing an + // indirect goto. For most code bases, this substantially cuts + // down on the number of jump sites we'll have to consider later. + typedef std::pair<unsigned, IndirectGotoStmt*> JumpScope; + llvm::SmallVector<JumpScope, 32> JumpScopes; + { + llvm::DenseMap<unsigned, IndirectGotoStmt*> JumpScopesMap; + for (llvm::SmallVectorImpl<IndirectGotoStmt*>::iterator + I = IndirectJumps.begin(), E = IndirectJumps.end(); I != E; ++I) { + IndirectGotoStmt *IG = *I; + assert(LabelAndGotoScopes.count(IG) && + "indirect jump didn't get added to scopes?"); + unsigned IGScope = LabelAndGotoScopes[IG]; + IndirectGotoStmt *&Entry = JumpScopesMap[IGScope]; + if (!Entry) Entry = IG; + } + JumpScopes.reserve(JumpScopesMap.size()); + for (llvm::DenseMap<unsigned, IndirectGotoStmt*>::iterator + I = JumpScopesMap.begin(), E = JumpScopesMap.end(); I != E; ++I) + JumpScopes.push_back(*I); + } + + // Collect a single representative of every scope containing a + // label whose address was taken somewhere in the function. + // For most code bases, there will be only one such scope. + llvm::DenseMap<unsigned, LabelDecl*> TargetScopes; + for (llvm::SmallVectorImpl<LabelDecl*>::iterator + I = IndirectJumpTargets.begin(), E = IndirectJumpTargets.end(); + I != E; ++I) { + LabelDecl *TheLabel = *I; + assert(LabelAndGotoScopes.count(TheLabel->getStmt()) && + "Referenced label didn't get added to scopes?"); + unsigned LabelScope = LabelAndGotoScopes[TheLabel->getStmt()]; + LabelDecl *&Target = TargetScopes[LabelScope]; + if (!Target) Target = TheLabel; + } + + // For each target scope, make sure it's trivially reachable from + // every scope containing a jump site. + // + // A path between scopes always consists of exitting zero or more + // scopes, then entering zero or more scopes. We build a set of + // of scopes S from which the target scope can be trivially + // entered, then verify that every jump scope can be trivially + // exitted to reach a scope in S. + llvm::BitVector Reachable(Scopes.size(), false); + for (llvm::DenseMap<unsigned,LabelDecl*>::iterator + TI = TargetScopes.begin(), TE = TargetScopes.end(); TI != TE; ++TI) { + unsigned TargetScope = TI->first; + LabelDecl *TargetLabel = TI->second; + + Reachable.reset(); + + // Mark all the enclosing scopes from which you can safely jump + // into the target scope. 'Min' will end up being the index of + // the shallowest such scope. + unsigned Min = TargetScope; + while (true) { + Reachable.set(Min); + + // Don't go beyond the outermost scope. + if (Min == 0) break; + + // Stop if we can't trivially enter the current scope. + if (Scopes[Min].InDiag) break; + + Min = Scopes[Min].ParentScope; + } + + // Walk through all the jump sites, checking that they can trivially + // reach this label scope. + for (llvm::SmallVectorImpl<JumpScope>::iterator + I = JumpScopes.begin(), E = JumpScopes.end(); I != E; ++I) { + unsigned Scope = I->first; + + // Walk out the "scope chain" for this scope, looking for a scope + // we've marked reachable. For well-formed code this amortizes + // to O(JumpScopes.size() / Scopes.size()): we only iterate + // when we see something unmarked, and in well-formed code we + // mark everything we iterate past. + bool IsReachable = false; + while (true) { + if (Reachable.test(Scope)) { + // If we find something reachable, mark all the scopes we just + // walked through as reachable. + for (unsigned S = I->first; S != Scope; S = Scopes[S].ParentScope) + Reachable.set(S); + IsReachable = true; + break; + } + + // Don't walk out if we've reached the top-level scope or we've + // gotten shallower than the shallowest reachable scope. + if (Scope == 0 || Scope < Min) break; + + // Don't walk out through an out-diagnostic. + if (Scopes[Scope].OutDiag) break; + + Scope = Scopes[Scope].ParentScope; + } + + // Only diagnose if we didn't find something. + if (IsReachable) continue; + + DiagnoseIndirectJump(I->second, I->first, TargetLabel, TargetScope); + } + } +} + +/// Diagnose an indirect jump which is known to cross scopes. +void JumpScopeChecker::DiagnoseIndirectJump(IndirectGotoStmt *Jump, + unsigned JumpScope, + LabelDecl *Target, + unsigned TargetScope) { + assert(JumpScope != TargetScope); + + S.Diag(Jump->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); + S.Diag(Target->getStmt()->getIdentLoc(), diag::note_indirect_goto_target); + + unsigned Common = GetDeepestCommonScope(JumpScope, TargetScope); + + // Walk out the scope chain until we reach the common ancestor. + for (unsigned I = JumpScope; I != Common; I = Scopes[I].ParentScope) + if (Scopes[I].OutDiag) + S.Diag(Scopes[I].Loc, Scopes[I].OutDiag); + + // Now walk into the scopes containing the label whose address was taken. + for (unsigned I = TargetScope; I != Common; I = Scopes[I].ParentScope) + if (Scopes[I].InDiag) + S.Diag(Scopes[I].Loc, Scopes[I].InDiag); +} + +/// CheckJump - Validate that the specified jump statement is valid: that it is +/// jumping within or out of its current scope, not into a deeper one. +void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, + SourceLocation DiagLoc, unsigned JumpDiag) { + assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?"); + unsigned FromScope = LabelAndGotoScopes[From]; + + assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?"); + unsigned ToScope = LabelAndGotoScopes[To]; + + // Common case: exactly the same scope, which is fine. + if (FromScope == ToScope) return; + + unsigned CommonScope = GetDeepestCommonScope(FromScope, ToScope); + + // It's okay to jump out from a nested scope. + if (CommonScope == ToScope) return; + + // Pull out (and reverse) any scopes we might need to diagnose skipping. + llvm::SmallVector<unsigned, 10> ToScopes; + for (unsigned I = ToScope; I != CommonScope; I = Scopes[I].ParentScope) + if (Scopes[I].InDiag) + ToScopes.push_back(I); + + // If the only scopes present are cleanup scopes, we're okay. + if (ToScopes.empty()) return; + + S.Diag(DiagLoc, JumpDiag); + + // Emit diagnostics for whatever is left in ToScopes. + for (unsigned i = 0, e = ToScopes.size(); i != e; ++i) + S.Diag(Scopes[ToScopes[i]].Loc, Scopes[ToScopes[i]].InDiag); +} + +void Sema::DiagnoseInvalidJumps(Stmt *Body) { + (void)JumpScopeChecker(Body, *this); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/Scope.cpp b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp new file mode 100644 index 0000000..833a59f --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/Scope.cpp @@ -0,0 +1,57 @@ +//===- Scope.cpp - Lexical scope information --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Scope class, which is used for recording +// information about a lexical scope. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/Scope.h" + +using namespace clang; + +void Scope::Init(Scope *parent, unsigned flags) { + AnyParent = parent; + Flags = flags; + + if (parent) { + Depth = parent->Depth + 1; + PrototypeDepth = parent->PrototypeDepth; + PrototypeIndex = 0; + FnParent = parent->FnParent; + BreakParent = parent->BreakParent; + ContinueParent = parent->ContinueParent; + ControlParent = parent->ControlParent; + BlockParent = parent->BlockParent; + TemplateParamParent = parent->TemplateParamParent; + } else { + Depth = 0; + PrototypeDepth = 0; + PrototypeIndex = 0; + FnParent = BreakParent = ContinueParent = BlockParent = 0; + ControlParent = 0; + TemplateParamParent = 0; + } + + // If this scope is a function or contains breaks/continues, remember it. + if (flags & FnScope) FnParent = this; + if (flags & BreakScope) BreakParent = this; + if (flags & ContinueScope) ContinueParent = this; + if (flags & ControlScope) ControlParent = this; + if (flags & BlockScope) BlockParent = this; + if (flags & TemplateParamScope) TemplateParamParent = this; + + // If this is a prototype scope, record that. + if (flags & FunctionPrototypeScope) PrototypeDepth++; + + DeclsInScope.clear(); + UsingDirectives.clear(); + Entity = 0; + ErrorTrap.reset(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp new file mode 100644 index 0000000..8297b31 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -0,0 +1,865 @@ +//===--- Sema.cpp - AST Builder and Semantic Analysis Implementation ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the actions class which performs semantic analysis and +// builds an AST out of a parse stream. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "TargetAttributesSema.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/APFloat.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/ObjCMethodList.h" +#include "clang/Sema/PrettyDeclStackTrace.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" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtCXX.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h" +using namespace clang; +using namespace sema; + +FunctionScopeInfo::~FunctionScopeInfo() { } + +void FunctionScopeInfo::Clear() { + HasBranchProtectedScope = false; + HasBranchIntoScope = false; + HasIndirectGoto = false; + + SwitchStack.clear(); + Returns.clear(); + ErrorTrap.reset(); + PossiblyUnreachableDiags.clear(); +} + +BlockScopeInfo::~BlockScopeInfo() { } + +void Sema::ActOnTranslationUnitScope(Scope *S) { + TUScope = S; + PushDeclContext(S, Context.getTranslationUnitDecl()); + + VAListTagName = PP.getIdentifierInfo("__va_list_tag"); + + if (!Context.isInt128Installed() && // May be set by ASTReader. + PP.getTargetInfo().getPointerWidth(0) >= 64) { + TypeSourceInfo *TInfo; + + // Install [u]int128_t for 64-bit targets. + TInfo = Context.getTrivialTypeSourceInfo(Context.Int128Ty); + PushOnScopeChains(TypedefDecl::Create(Context, CurContext, + SourceLocation(), + SourceLocation(), + &Context.Idents.get("__int128_t"), + TInfo), TUScope); + + TInfo = Context.getTrivialTypeSourceInfo(Context.UnsignedInt128Ty); + PushOnScopeChains(TypedefDecl::Create(Context, CurContext, + SourceLocation(), + SourceLocation(), + &Context.Idents.get("__uint128_t"), + TInfo), TUScope); + Context.setInt128Installed(); + } + + + if (!PP.getLangOptions().ObjC1) return; + + // Built-in ObjC types may already be set by ASTReader (hence isNull checks). + if (Context.getObjCSelType().isNull()) { + // Create the built-in typedef for 'SEL'. + QualType SelT = Context.getPointerType(Context.ObjCBuiltinSelTy); + TypeSourceInfo *SelInfo = Context.getTrivialTypeSourceInfo(SelT); + TypedefDecl *SelTypedef + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), + &Context.Idents.get("SEL"), SelInfo); + PushOnScopeChains(SelTypedef, TUScope); + Context.setObjCSelType(Context.getTypeDeclType(SelTypedef)); + Context.ObjCSelRedefinitionType = Context.getObjCSelType(); + } + + // Synthesize "@class Protocol; + if (Context.getObjCProtoType().isNull()) { + ObjCInterfaceDecl *ProtocolDecl = + ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(), + &Context.Idents.get("Protocol"), + SourceLocation(), true); + Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl)); + PushOnScopeChains(ProtocolDecl, TUScope, false); + } + // Create the built-in typedef for 'id'. + if (Context.getObjCIdType().isNull()) { + QualType T = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, 0, 0); + T = Context.getObjCObjectPointerType(T); + TypeSourceInfo *IdInfo = Context.getTrivialTypeSourceInfo(T); + TypedefDecl *IdTypedef + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), + &Context.Idents.get("id"), IdInfo); + PushOnScopeChains(IdTypedef, TUScope); + Context.setObjCIdType(Context.getTypeDeclType(IdTypedef)); + Context.ObjCIdRedefinitionType = Context.getObjCIdType(); + } + // Create the built-in typedef for 'Class'. + if (Context.getObjCClassType().isNull()) { + QualType T = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, 0, 0); + T = Context.getObjCObjectPointerType(T); + TypeSourceInfo *ClassInfo = Context.getTrivialTypeSourceInfo(T); + TypedefDecl *ClassTypedef + = TypedefDecl::Create(Context, CurContext, + SourceLocation(), SourceLocation(), + &Context.Idents.get("Class"), ClassInfo); + PushOnScopeChains(ClassTypedef, TUScope); + Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef)); + Context.ObjCClassRedefinitionType = Context.getObjCClassType(); + } +} + +Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, + bool CompleteTranslationUnit, + CodeCompleteConsumer *CodeCompleter) + : TheTargetAttributesSema(0), FPFeatures(pp.getLangOptions()), + LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), + Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), + ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), + PackContext(0), MSStructPragmaOn(false), VisContext(0), + LateTemplateParser(0), OpaqueParser(0), + IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), + GlobalNewDeleteDeclared(false), + CompleteTranslationUnit(CompleteTranslationUnit), + NumSFINAEErrors(0), SuppressAccessChecking(false), + AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), + NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), + CurrentInstantiationScope(0), TyposCorrected(0), + AnalysisWarnings(*this) +{ + TUScope = 0; + if (getLangOptions().CPlusPlus) + FieldCollector.reset(new CXXFieldCollector()); + + // Tell diagnostics how to render things from the AST library. + PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, + &Context); + + ExprEvalContexts.push_back( + ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); + + FunctionScopes.push_back(new FunctionScopeInfo(Diags)); +} + +void Sema::Initialize() { + // Tell the AST consumer about this Sema object. + Consumer.Initialize(Context); + + // FIXME: Isn't this redundant with the initialization above? + if (SemaConsumer *SC = dyn_cast<SemaConsumer>(&Consumer)) + SC->InitializeSema(*this); + + // Tell the external Sema source about this Sema object. + if (ExternalSemaSource *ExternalSema + = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource())) + ExternalSema->InitializeSema(*this); +} + +Sema::~Sema() { + if (PackContext) FreePackedContext(); + if (VisContext) FreeVisContext(); + delete TheTargetAttributesSema; + MSStructPragmaOn = false; + // 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)) + SC->ForgetSema(); + + // Detach from the external Sema source. + if (ExternalSemaSource *ExternalSema + = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource())) + ExternalSema->ForgetSema(); +} + +ASTMutationListener *Sema::getASTMutationListener() const { + return getASTConsumer().GetASTMutationListener(); +} + +/// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. +/// If there is already an implicit cast, merge into the existing one. +/// The result is of the given category. +ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, + CastKind Kind, ExprValueKind VK, + const CXXCastPath *BasePath) { + QualType ExprTy = Context.getCanonicalType(E->getType()); + QualType TypeTy = Context.getCanonicalType(Ty); + + if (ExprTy == TypeTy) + return Owned(E); + + // If this is a derived-to-base cast to a through a virtual base, we + // need a vtable. + if (Kind == CK_DerivedToBase && + BasePathInvolvesVirtualBase(*BasePath)) { + QualType T = E->getType(); + if (const PointerType *Pointer = T->getAs<PointerType>()) + T = Pointer->getPointeeType(); + if (const RecordType *RecordTy = T->getAs<RecordType>()) + MarkVTableUsed(E->getLocStart(), + cast<CXXRecordDecl>(RecordTy->getDecl())); + } + + if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) { + if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { + ImpCast->setType(Ty); + ImpCast->setValueKind(VK); + return Owned(E); + } + } + + return Owned(ImplicitCastExpr::Create(Context, Ty, Kind, E, BasePath, VK)); +} + +/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding +/// to the conversion from scalar type ScalarTy to the Boolean type. +CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { + switch (ScalarTy->getScalarTypeKind()) { + case Type::STK_Bool: return CK_NoOp; + case Type::STK_Pointer: return CK_PointerToBoolean; + case Type::STK_MemberPointer: return CK_MemberPointerToBoolean; + case Type::STK_Integral: return CK_IntegralToBoolean; + case Type::STK_Floating: return CK_FloatingToBoolean; + case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean; + case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean; + } + return CK_Invalid; +} + +ExprValueKind Sema::CastCategory(Expr *E) { + Expr::Classification Classification = E->Classify(Context); + return Classification.isRValue() ? VK_RValue : + (Classification.isLValue() ? VK_LValue : VK_XValue); +} + +/// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector. +static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { + if (D->isUsed()) + return true; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // UnusedFileScopedDecls stores the first declaration. + // The declaration may have become definition so check again. + const FunctionDecl *DeclToCheck; + if (FD->hasBody(DeclToCheck)) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + + // Later redecls may add new information resulting in not having to warn, + // so check again. + DeclToCheck = FD->getMostRecentDeclaration(); + if (DeclToCheck != FD) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + } + + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + // UnusedFileScopedDecls stores the first declaration. + // The declaration may have become definition so check again. + const VarDecl *DeclToCheck = VD->getDefinition(); + if (DeclToCheck) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + + // Later redecls may add new information resulting in not having to warn, + // so check again. + DeclToCheck = VD->getMostRecentDeclaration(); + if (DeclToCheck != VD) + return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); + } + + return false; +} + +namespace { + struct UndefinedInternal { + NamedDecl *decl; + FullSourceLoc useLoc; + + UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc) + : decl(decl), useLoc(useLoc) {} + }; + + bool operator<(const UndefinedInternal &l, const UndefinedInternal &r) { + return l.useLoc.isBeforeInTranslationUnitThan(r.useLoc); + } +} + +/// checkUndefinedInternals - Check for undefined objects with internal linkage. +static void checkUndefinedInternals(Sema &S) { + if (S.UndefinedInternals.empty()) return; + + // Collect all the still-undefined entities with internal linkage. + llvm::SmallVector<UndefinedInternal, 16> undefined; + for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator + i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end(); + i != e; ++i) { + NamedDecl *decl = i->first; + + // Ignore attributes that have become invalid. + if (decl->isInvalidDecl()) continue; + + // __attribute__((weakref)) is basically a definition. + if (decl->hasAttr<WeakRefAttr>()) continue; + + if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { + if (fn->isPure() || fn->hasBody()) + continue; + } else { + if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly) + continue; + } + + // We build a FullSourceLoc so that we can sort with array_pod_sort. + FullSourceLoc loc(i->second, S.Context.getSourceManager()); + undefined.push_back(UndefinedInternal(decl, loc)); + } + + if (undefined.empty()) return; + + // Sort (in order of use site) so that we're not (as) dependent on + // the iteration order through an llvm::DenseMap. + llvm::array_pod_sort(undefined.begin(), undefined.end()); + + for (llvm::SmallVectorImpl<UndefinedInternal>::iterator + i = undefined.begin(), e = undefined.end(); i != e; ++i) { + NamedDecl *decl = i->decl; + S.Diag(decl->getLocation(), diag::warn_undefined_internal) + << isa<VarDecl>(decl) << decl; + S.Diag(i->useLoc, diag::note_used_here); + } +} + +/// ActOnEndOfTranslationUnit - This is called at the very end of the +/// translation unit when EOF is reached and all but the top-level scope is +/// popped. +void Sema::ActOnEndOfTranslationUnit() { + // At PCH writing, implicit instantiations and VTable handling info are + // stored and performed when the PCH is included. + if (CompleteTranslationUnit) { + // If any dynamic classes have their key function defined within + // this translation unit, then those vtables are considered "used" and must + // be emitted. + for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) { + assert(!DynamicClasses[I]->isDependentType() && + "Should not see dependent types here!"); + if (const CXXMethodDecl *KeyFunction + = Context.getKeyFunction(DynamicClasses[I])) { + const FunctionDecl *Definition = 0; + if (KeyFunction->hasBody(Definition)) + MarkVTableUsed(Definition->getLocation(), DynamicClasses[I], true); + } + } + + // If DefinedUsedVTables ends up marking any virtual member functions it + // might lead to more pending template instantiations, which we then need + // to instantiate. + DefineUsedVTables(); + + // C++: Perform implicit template instantiations. + // + // FIXME: When we perform these implicit instantiations, we do not + // carefully keep track of the point of instantiation (C++ [temp.point]). + // This means that name lookup that occurs within the template + // instantiation will always happen at the end of the translation unit, + // so it will find some names that should not be found. Although this is + // common behavior for C++ compilers, it is technically wrong. In the + // future, we either need to be able to filter the results of name lookup + // or we need to perform template instantiations earlier. + PerformPendingInstantiations(); + } + + // Remove file scoped decls that turned out to be used. + UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(), + UnusedFileScopedDecls.end(), + std::bind1st(std::ptr_fun(ShouldRemoveFromUnused), + this)), + UnusedFileScopedDecls.end()); + + if (!CompleteTranslationUnit) { + TUScope = 0; + return; + } + + // Check for #pragma weak identifiers that were never declared + // FIXME: This will cause diagnostics to be emitted in a non-determinstic + // order! Iterating over a densemap like this is bad. + for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator + I = WeakUndeclaredIdentifiers.begin(), + E = WeakUndeclaredIdentifiers.end(); I != E; ++I) { + if (I->second.getUsed()) continue; + + Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared) + << I->first; + } + + // C99 6.9.2p2: + // A declaration of an identifier for an object that has file + // scope without an initializer, and without a storage-class + // specifier or with the storage-class specifier static, + // constitutes a tentative definition. If a translation unit + // contains one or more tentative definitions for an identifier, + // and the translation unit contains no external definition for + // that identifier, then the behavior is exactly as if the + // translation unit contains a file scope declaration of that + // identifier, with the composite type as of the end of the + // translation unit, with an initializer equal to 0. + llvm::SmallSet<VarDecl *, 32> Seen; + for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) { + VarDecl *VD = TentativeDefinitions[i]->getActingDefinition(); + + // If the tentative definition was completed, getActingDefinition() returns + // null. If we've already seen this variable before, insert()'s second + // return value is false. + if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD)) + continue; + + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(VD->getType())) { + if (RequireCompleteType(VD->getLocation(), + ArrayT->getElementType(), + diag::err_tentative_def_incomplete_type_arr)) { + VD->setInvalidDecl(); + continue; + } + + // Set the length of the array to 1 (C99 6.9.2p5). + Diag(VD->getLocation(), diag::warn_tentative_incomplete_array); + llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true); + QualType T = Context.getConstantArrayType(ArrayT->getElementType(), + One, ArrayType::Normal, 0); + VD->setType(T); + } else if (RequireCompleteType(VD->getLocation(), VD->getType(), + diag::err_tentative_def_incomplete_type)) + VD->setInvalidDecl(); + + // Notify the consumer that we've completed a tentative definition. + if (!VD->isInvalidDecl()) + Consumer.CompleteTentativeDefinition(VD); + + } + + if (LangOpts.CPlusPlus0x && + Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle, + SourceLocation()) + != Diagnostic::Ignored) + CheckDelegatingCtorCycles(); + + // If there were errors, disable 'unused' warnings since they will mostly be + // noise. + if (!Diags.hasErrorOccurred()) { + // Output warning for unused file scoped decls. + for (llvm::SmallVectorImpl<const DeclaratorDecl*>::iterator + I = UnusedFileScopedDecls.begin(), + E = UnusedFileScopedDecls.end(); I != E; ++I) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { + const FunctionDecl *DiagD; + if (!FD->hasBody(DiagD)) + DiagD = FD; + if (DiagD->isDeleted()) + continue; // Deleted functions are supposed to be unused. + if (DiagD->isReferenced()) { + if (isa<CXXMethodDecl>(DiagD)) + Diag(DiagD->getLocation(), diag::warn_unneeded_member_function) + << DiagD->getDeclName(); + else + Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) + << /*function*/0 << DiagD->getDeclName(); + } else { + Diag(DiagD->getLocation(), + isa<CXXMethodDecl>(DiagD) ? diag::warn_unused_member_function + : diag::warn_unused_function) + << DiagD->getDeclName(); + } + } else { + const VarDecl *DiagD = cast<VarDecl>(*I)->getDefinition(); + if (!DiagD) + DiagD = cast<VarDecl>(*I); + if (DiagD->isReferenced()) { + Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) + << /*variable*/1 << DiagD->getDeclName(); + } else { + Diag(DiagD->getLocation(), diag::warn_unused_variable) + << DiagD->getDeclName(); + } + } + } + + checkUndefinedInternals(*this); + } + + // Check we've noticed that we're no longer parsing the initializer for every + // variable. If we miss cases, then at best we have a performance issue and + // at worst a rejects-valid bug. + assert(ParsingInitForAutoVars.empty() && + "Didn't unmark var as having its initializer parsed"); + + TUScope = 0; +} + + +//===----------------------------------------------------------------------===// +// Helper functions. +//===----------------------------------------------------------------------===// + +DeclContext *Sema::getFunctionLevelDeclContext() { + DeclContext *DC = CurContext; + + while (isa<BlockDecl>(DC) || isa<EnumDecl>(DC)) + DC = DC->getParent(); + + return DC; +} + +/// getCurFunctionDecl - If inside of a function body, this returns a pointer +/// to the function decl for the function being parsed. If we're currently +/// in a 'block', this returns the containing context. +FunctionDecl *Sema::getCurFunctionDecl() { + DeclContext *DC = getFunctionLevelDeclContext(); + return dyn_cast<FunctionDecl>(DC); +} + +ObjCMethodDecl *Sema::getCurMethodDecl() { + DeclContext *DC = getFunctionLevelDeclContext(); + return dyn_cast<ObjCMethodDecl>(DC); +} + +NamedDecl *Sema::getCurFunctionOrMethodDecl() { + DeclContext *DC = getFunctionLevelDeclContext(); + if (isa<ObjCMethodDecl>(DC) || isa<FunctionDecl>(DC)) + return cast<NamedDecl>(DC); + return 0; +} + +Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { + if (!isActive()) + return; + + if (llvm::Optional<TemplateDeductionInfo*> Info = SemaRef.isSFINAEContext()) { + switch (DiagnosticIDs::getDiagnosticSFINAEResponse(getDiagID())) { + case DiagnosticIDs::SFINAE_Report: + // Fall through; we'll report the diagnostic below. + break; + + case DiagnosticIDs::SFINAE_AccessControl: + // Per C++ Core Issue 1170, access control is part of SFINAE. + // Additionally, the AccessCheckingSFINAE flag can be used to temporary + // make access control a part of SFINAE for the purposes of checking + // type traits. + if (!SemaRef.AccessCheckingSFINAE && + !SemaRef.getLangOptions().CPlusPlus0x) + break; + + case DiagnosticIDs::SFINAE_SubstitutionFailure: + // Count this failure so that we know that template argument deduction + // has failed. + ++SemaRef.NumSFINAEErrors; + SemaRef.Diags.setLastDiagnosticIgnored(); + SemaRef.Diags.Clear(); + Clear(); + return; + + case DiagnosticIDs::SFINAE_Suppress: + // Make a copy of this suppressed diagnostic and store it with the + // template-deduction information; + FlushCounts(); + DiagnosticInfo DiagInfo(&SemaRef.Diags); + + if (*Info) + (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(), + PartialDiagnostic(DiagInfo, + SemaRef.Context.getDiagAllocator())); + + // Suppress this diagnostic. + SemaRef.Diags.setLastDiagnosticIgnored(); + SemaRef.Diags.Clear(); + Clear(); + return; + } + } + + // Emit the diagnostic. + if (!this->Emit()) + return; + + // If this is not a note, and we're in a template instantiation + // that is different from the last template instantiation where + // we emitted an error, print a template instantiation + // backtrace. + if (!DiagnosticIDs::isBuiltinNote(DiagID) && + !SemaRef.ActiveTemplateInstantiations.empty() && + SemaRef.ActiveTemplateInstantiations.back() + != SemaRef.LastTemplateInstantiationErrorContext) { + SemaRef.PrintInstantiationStack(); + SemaRef.LastTemplateInstantiationErrorContext + = SemaRef.ActiveTemplateInstantiations.back(); + } +} + +Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID) { + DiagnosticBuilder DB = Diags.Report(Loc, DiagID); + return SemaDiagnosticBuilder(DB, *this, DiagID); +} + +Sema::SemaDiagnosticBuilder +Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { + SemaDiagnosticBuilder Builder(Diag(Loc, PD.getDiagID())); + PD.Emit(Builder); + + return Builder; +} + +/// \brief Looks through the macro-instantiation chain for the given +/// location, looking for a macro instantiation with the given name. +/// If one is found, returns true and sets the location to that +/// instantiation loc. +bool Sema::findMacroSpelling(SourceLocation &locref, llvm::StringRef name) { + SourceLocation loc = locref; + if (!loc.isMacroID()) return false; + + // There's no good way right now to look at the intermediate + // instantiations, so just jump to the instantiation location. + loc = getSourceManager().getInstantiationLoc(loc); + + // If that's written with the name, stop here. + llvm::SmallVector<char, 16> buffer; + if (getPreprocessor().getSpelling(loc, buffer) == name) { + locref = loc; + return true; + } + return false; +} + +/// \brief Determines the active Scope associated with the given declaration +/// context. +/// +/// This routine maps a declaration context to the active Scope object that +/// represents that declaration context in the parser. It is typically used +/// from "scope-less" code (e.g., template instantiation, lazy creation of +/// declarations) that injects a name for name-lookup purposes and, therefore, +/// must update the Scope. +/// +/// \returns The scope corresponding to the given declaraion context, or NULL +/// if no such scope is open. +Scope *Sema::getScopeForContext(DeclContext *Ctx) { + + if (!Ctx) + return 0; + + Ctx = Ctx->getPrimaryContext(); + for (Scope *S = getCurScope(); S; S = S->getParent()) { + // Ignore scopes that cannot have declarations. This is important for + // out-of-line definitions of static class members. + if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) + if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity())) + if (Ctx == Entity->getPrimaryContext()) + return S; + } + + return 0; +} + +/// \brief Enter a new function scope +void Sema::PushFunctionScope() { + if (FunctionScopes.size() == 1) { + // Use the "top" function scope rather than having to allocate + // memory for a new scope. + FunctionScopes.back()->Clear(); + FunctionScopes.push_back(FunctionScopes.back()); + return; + } + + FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics())); +} + +void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { + FunctionScopes.push_back(new BlockScopeInfo(getDiagnostics(), + BlockScope, Block)); +} + +void Sema::PopFunctionOrBlockScope(const AnalysisBasedWarnings::Policy *WP, + const Decl *D, const BlockExpr *blkExpr) { + FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); + assert(!FunctionScopes.empty() && "mismatched push/pop!"); + + // Issue any analysis-based warnings. + if (WP && D) + AnalysisWarnings.IssueWarnings(*WP, Scope, D, blkExpr); + else { + for (llvm::SmallVectorImpl<sema::PossiblyUnreachableDiag>::iterator + i = Scope->PossiblyUnreachableDiags.begin(), + e = Scope->PossiblyUnreachableDiags.end(); + i != e; ++i) { + const sema::PossiblyUnreachableDiag &D = *i; + Diag(D.Loc, D.PD); + } + } + + if (FunctionScopes.back() != Scope) { + delete Scope; + } +} + +/// \brief Determine whether any errors occurred within this function/method/ +/// block. +bool Sema::hasAnyErrorsInThisFunction() const { + return getCurFunction()->ErrorTrap.hasErrorOccurred(); +} + +BlockScopeInfo *Sema::getCurBlock() { + if (FunctionScopes.empty()) + return 0; + + return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); +} + +// Pin this vtable to this file. +ExternalSemaSource::~ExternalSemaSource() {} + +std::pair<ObjCMethodList, ObjCMethodList> +ExternalSemaSource::ReadMethodPool(Selector Sel) { + return std::pair<ObjCMethodList, ObjCMethodList>(); +} + +void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const { + SourceLocation Loc = this->Loc; + if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); + if (Loc.isValid()) { + Loc.print(OS, S.getSourceManager()); + OS << ": "; + } + OS << Message; + + if (TheDecl && isa<NamedDecl>(TheDecl)) { + std::string Name = cast<NamedDecl>(TheDecl)->getNameAsString(); + if (!Name.empty()) + OS << " '" << Name << '\''; + } + + OS << '\n'; +} + +/// \brief Figure out if an expression could be turned into a call. +/// +/// Use this when trying to recover from an error where the programmer may have +/// written just the name of a function instead of actually calling it. +/// +/// \param E - The expression to examine. +/// \param ZeroArgCallReturnTy - If the expression can be turned into a call +/// with no arguments, this parameter is set to the type returned by such a +/// call; otherwise, it is set to an empty QualType. +/// \param NonTemplateOverloads - If the expression is an overloaded function +/// name, this parameter is populated with the decls of the various overloads. +bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, + UnresolvedSetImpl &NonTemplateOverloads) { + ZeroArgCallReturnTy = QualType(); + NonTemplateOverloads.clear(); + if (const OverloadExpr *Overloads = dyn_cast<OverloadExpr>(&E)) { + for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), + DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { + // Our overload set may include TemplateDecls, which we'll ignore for our + // present purpose. + if (const FunctionDecl *OverloadDecl = dyn_cast<FunctionDecl>(*it)) { + NonTemplateOverloads.addDecl(*it); + if (OverloadDecl->getMinRequiredArguments() == 0) + ZeroArgCallReturnTy = OverloadDecl->getResultType(); + } + } + return true; + } + + if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(&E)) { + if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(DeclRef->getDecl())) { + if (Fun->getMinRequiredArguments() == 0) + ZeroArgCallReturnTy = Fun->getResultType(); + return true; + } + } + + // We don't have an expression that's convenient to get a FunctionDecl from, + // but we can at least check if the type is "function of 0 arguments". + QualType ExprTy = E.getType(); + const FunctionType *FunTy = NULL; + QualType PointeeTy = ExprTy->getPointeeType(); + if (!PointeeTy.isNull()) + FunTy = PointeeTy->getAs<FunctionType>(); + if (!FunTy) + FunTy = ExprTy->getAs<FunctionType>(); + if (!FunTy && ExprTy == Context.BoundMemberTy) { + // Look for the bound-member type. If it's still overloaded, give up, + // although we probably should have fallen into the OverloadExpr case above + // if we actually have an overloaded bound member. + QualType BoundMemberTy = Expr::findBoundMemberType(&E); + if (!BoundMemberTy.isNull()) + FunTy = BoundMemberTy->castAs<FunctionType>(); + } + + if (const FunctionProtoType *FPT = + dyn_cast_or_null<FunctionProtoType>(FunTy)) { + if (FPT->getNumArgs() == 0) + ZeroArgCallReturnTy = FunTy->getResultType(); + return true; + } + return false; +} + +/// \brief Give notes for a set of overloads. +/// +/// A companion to isExprCallable. In cases when the name that the programmer +/// wrote was an overloaded function, we may be able to make some guesses about +/// plausible overloads based on their return types; such guesses can be handed +/// off to this method to be emitted as notes. +/// +/// \param Overloads - The overloads to note. +/// \param FinalNoteLoc - If we've suppressed printing some overloads due to +/// -fshow-overloads=best, this is the location to attach to the note about too +/// many candidates. Typically this will be the location of the original +/// ill-formed expression. +void Sema::NoteOverloads(const UnresolvedSetImpl &Overloads, + const SourceLocation FinalNoteLoc) { + int ShownOverloads = 0; + int SuppressedOverloads = 0; + for (UnresolvedSetImpl::iterator It = Overloads.begin(), + DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { + // FIXME: Magic number for max shown overloads stolen from + // OverloadCandidateSet::NoteCandidates. + if (ShownOverloads >= 4 && + Diags.getShowOverloads() == Diagnostic::Ovl_Best) { + ++SuppressedOverloads; + continue; + } + Diag(cast<FunctionDecl>(*It)->getSourceRange().getBegin(), + diag::note_member_ref_possible_intended_overload); + ++ShownOverloads; + } + if (SuppressedOverloads) + Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates) + << SuppressedOverloads; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp new file mode 100644 index 0000000..a26737e --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -0,0 +1,1658 @@ +//===---- SemaAccess.cpp - C++ Access Control -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sema routines for C++ access control semantics. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DependentDiagnostic.h" +#include "clang/AST/ExprCXX.h" + +using namespace clang; +using namespace sema; + +/// A copy of Sema's enum without AR_delayed. +enum AccessResult { + AR_accessible, + AR_inaccessible, + AR_dependent +}; + +/// SetMemberAccessSpecifier - Set the access specifier of a member. +/// Returns true on error (when the previous member decl access specifier +/// is different from the new member decl access specifier). +bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, + NamedDecl *PrevMemberDecl, + AccessSpecifier LexicalAS) { + if (!PrevMemberDecl) { + // Use the lexical access specifier. + MemberDecl->setAccess(LexicalAS); + return false; + } + + // C++ [class.access.spec]p3: When a member is redeclared its access + // specifier must be same as its initial declaration. + if (LexicalAS != AS_none && LexicalAS != PrevMemberDecl->getAccess()) { + Diag(MemberDecl->getLocation(), + diag::err_class_redeclared_with_different_access) + << MemberDecl << LexicalAS; + Diag(PrevMemberDecl->getLocation(), diag::note_previous_access_declaration) + << PrevMemberDecl << PrevMemberDecl->getAccess(); + + MemberDecl->setAccess(LexicalAS); + return true; + } + + MemberDecl->setAccess(PrevMemberDecl->getAccess()); + return false; +} + +static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { + DeclContext *DC = D->getDeclContext(); + + // This can only happen at top: enum decls only "publish" their + // immediate members. + if (isa<EnumDecl>(DC)) + DC = cast<EnumDecl>(DC)->getDeclContext(); + + CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(DC); + while (DeclaringClass->isAnonymousStructOrUnion()) + DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); + return DeclaringClass; +} + +namespace { +struct EffectiveContext { + EffectiveContext() : Inner(0), Dependent(false) {} + + explicit EffectiveContext(DeclContext *DC) + : Inner(DC), + Dependent(DC->isDependentContext()) { + + // C++ [class.access.nest]p1: + // A nested class is a member and as such has the same access + // rights as any other member. + // C++ [class.access]p2: + // A member of a class can also access all the names to which + // the class has access. A local class of a member function + // may access the same names that the member function itself + // may access. + // This almost implies that the privileges of nesting are transitive. + // Technically it says nothing about the local classes of non-member + // functions (which can gain privileges through friendship), but we + // take that as an oversight. + while (true) { + if (isa<CXXRecordDecl>(DC)) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); + Records.push_back(Record); + DC = Record->getDeclContext(); + } else if (isa<FunctionDecl>(DC)) { + FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); + Functions.push_back(Function); + DC = Function->getDeclContext(); + } else if (DC->isFileContext()) { + break; + } else { + DC = DC->getParent(); + } + } + } + + bool isDependent() const { return Dependent; } + + bool includesClass(const CXXRecordDecl *R) const { + R = R->getCanonicalDecl(); + return std::find(Records.begin(), Records.end(), R) + != Records.end(); + } + + /// Retrieves the innermost "useful" context. Can be null if we're + /// doing access-control without privileges. + DeclContext *getInnerContext() const { + return Inner; + } + + typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator; + + DeclContext *Inner; + llvm::SmallVector<FunctionDecl*, 4> Functions; + llvm::SmallVector<CXXRecordDecl*, 4> Records; + bool Dependent; +}; + +/// Like sema::AccessedEntity, but kindly lets us scribble all over +/// it. +struct AccessTarget : public AccessedEntity { + AccessTarget(const AccessedEntity &Entity) + : AccessedEntity(Entity) { + initialize(); + } + + AccessTarget(ASTContext &Context, + MemberNonce _, + CXXRecordDecl *NamingClass, + DeclAccessPair FoundDecl, + QualType BaseObjectType, + bool IsUsingDecl = false) + : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType), + IsUsingDeclaration(IsUsingDecl) { + initialize(); + } + + AccessTarget(ASTContext &Context, + BaseNonce _, + CXXRecordDecl *BaseClass, + CXXRecordDecl *DerivedClass, + AccessSpecifier Access) + : AccessedEntity(Context, Base, BaseClass, DerivedClass, Access) { + initialize(); + } + + bool hasInstanceContext() const { + return HasInstanceContext; + } + + class SavedInstanceContext { + public: + ~SavedInstanceContext() { + Target.HasInstanceContext = Has; + } + + private: + friend struct AccessTarget; + explicit SavedInstanceContext(AccessTarget &Target) + : Target(Target), Has(Target.HasInstanceContext) {} + AccessTarget &Target; + bool Has; + }; + + SavedInstanceContext saveInstanceContext() { + return SavedInstanceContext(*this); + } + + void suppressInstanceContext() { + HasInstanceContext = false; + } + + const CXXRecordDecl *resolveInstanceContext(Sema &S) const { + assert(HasInstanceContext); + if (CalculatedInstanceContext) + return InstanceContext; + + CalculatedInstanceContext = true; + DeclContext *IC = S.computeDeclContext(getBaseObjectType()); + InstanceContext = (IC ? cast<CXXRecordDecl>(IC)->getCanonicalDecl() : 0); + return InstanceContext; + } + + const CXXRecordDecl *getDeclaringClass() const { + return DeclaringClass; + } + +private: + void initialize() { + HasInstanceContext = (isMemberAccess() && + !getBaseObjectType().isNull() && + getTargetDecl()->isCXXInstanceMember()); + CalculatedInstanceContext = false; + InstanceContext = 0; + + if (isMemberAccess()) + DeclaringClass = FindDeclaringClass(getTargetDecl()); + else + DeclaringClass = getBaseClass(); + DeclaringClass = DeclaringClass->getCanonicalDecl(); + } + + bool IsUsingDeclaration : 1; + bool HasInstanceContext : 1; + mutable bool CalculatedInstanceContext : 1; + mutable const CXXRecordDecl *InstanceContext; + const CXXRecordDecl *DeclaringClass; +}; + +} + +/// Checks whether one class might instantiate to the other. +static bool MightInstantiateTo(const CXXRecordDecl *From, + const CXXRecordDecl *To) { + // Declaration names are always preserved by instantiation. + if (From->getDeclName() != To->getDeclName()) + return false; + + const DeclContext *FromDC = From->getDeclContext()->getPrimaryContext(); + const DeclContext *ToDC = To->getDeclContext()->getPrimaryContext(); + if (FromDC == ToDC) return true; + if (FromDC->isFileContext() || ToDC->isFileContext()) return false; + + // Be conservative. + return true; +} + +/// Checks whether one class is derived from another, inclusively. +/// Properly indicates when it couldn't be determined due to +/// dependence. +/// +/// This should probably be donated to AST or at least Sema. +static AccessResult IsDerivedFromInclusive(const CXXRecordDecl *Derived, + const CXXRecordDecl *Target) { + assert(Derived->getCanonicalDecl() == Derived); + assert(Target->getCanonicalDecl() == Target); + + if (Derived == Target) return AR_accessible; + + bool CheckDependent = Derived->isDependentContext(); + if (CheckDependent && MightInstantiateTo(Derived, Target)) + return AR_dependent; + + AccessResult OnFailure = AR_inaccessible; + llvm::SmallVector<const CXXRecordDecl*, 8> Queue; // actually a stack + + while (true) { + for (CXXRecordDecl::base_class_const_iterator + I = Derived->bases_begin(), E = Derived->bases_end(); I != E; ++I) { + + const CXXRecordDecl *RD; + + QualType T = I->getType(); + if (const RecordType *RT = T->getAs<RecordType>()) { + RD = cast<CXXRecordDecl>(RT->getDecl()); + } else if (const InjectedClassNameType *IT + = T->getAs<InjectedClassNameType>()) { + RD = IT->getDecl(); + } else { + assert(T->isDependentType() && "non-dependent base wasn't a record?"); + OnFailure = AR_dependent; + continue; + } + + RD = RD->getCanonicalDecl(); + if (RD == Target) return AR_accessible; + if (CheckDependent && MightInstantiateTo(RD, Target)) + OnFailure = AR_dependent; + + Queue.push_back(RD); + } + + if (Queue.empty()) break; + + Derived = Queue.back(); + Queue.pop_back(); + } + + return OnFailure; +} + + +static bool MightInstantiateTo(Sema &S, DeclContext *Context, + DeclContext *Friend) { + if (Friend == Context) + return true; + + assert(!Friend->isDependentContext() && + "can't handle friends with dependent contexts here"); + + if (!Context->isDependentContext()) + return false; + + if (Friend->isFileContext()) + return false; + + // TODO: this is very conservative + return true; +} + +// Asks whether the type in 'context' can ever instantiate to the type +// in 'friend'. +static bool MightInstantiateTo(Sema &S, CanQualType Context, CanQualType Friend) { + if (Friend == Context) + return true; + + if (!Friend->isDependentType() && !Context->isDependentType()) + return false; + + // TODO: this is very conservative. + return true; +} + +static bool MightInstantiateTo(Sema &S, + FunctionDecl *Context, + FunctionDecl *Friend) { + if (Context->getDeclName() != Friend->getDeclName()) + return false; + + if (!MightInstantiateTo(S, + Context->getDeclContext(), + Friend->getDeclContext())) + return false; + + CanQual<FunctionProtoType> FriendTy + = S.Context.getCanonicalType(Friend->getType()) + ->getAs<FunctionProtoType>(); + CanQual<FunctionProtoType> ContextTy + = S.Context.getCanonicalType(Context->getType()) + ->getAs<FunctionProtoType>(); + + // There isn't any way that I know of to add qualifiers + // during instantiation. + if (FriendTy.getQualifiers() != ContextTy.getQualifiers()) + return false; + + if (FriendTy->getNumArgs() != ContextTy->getNumArgs()) + return false; + + if (!MightInstantiateTo(S, + ContextTy->getResultType(), + FriendTy->getResultType())) + return false; + + for (unsigned I = 0, E = FriendTy->getNumArgs(); I != E; ++I) + if (!MightInstantiateTo(S, + ContextTy->getArgType(I), + FriendTy->getArgType(I))) + return false; + + return true; +} + +static bool MightInstantiateTo(Sema &S, + FunctionTemplateDecl *Context, + FunctionTemplateDecl *Friend) { + return MightInstantiateTo(S, + Context->getTemplatedDecl(), + Friend->getTemplatedDecl()); +} + +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + const CXXRecordDecl *Friend) { + if (EC.includesClass(Friend)) + return AR_accessible; + + if (EC.isDependent()) { + CanQualType FriendTy + = S.Context.getCanonicalType(S.Context.getTypeDeclType(Friend)); + + for (EffectiveContext::record_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + CanQualType ContextTy + = S.Context.getCanonicalType(S.Context.getTypeDeclType(*I)); + if (MightInstantiateTo(S, ContextTy, FriendTy)) + return AR_dependent; + } + } + + return AR_inaccessible; +} + +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + CanQualType Friend) { + if (const RecordType *RT = Friend->getAs<RecordType>()) + return MatchesFriend(S, EC, cast<CXXRecordDecl>(RT->getDecl())); + + // TODO: we can do better than this + if (Friend->isDependentType()) + return AR_dependent; + + return AR_inaccessible; +} + +/// Determines whether the given friend class template matches +/// anything in the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + ClassTemplateDecl *Friend) { + AccessResult OnFailure = AR_inaccessible; + + // Check whether the friend is the template of a class in the + // context chain. + for (llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + CXXRecordDecl *Record = *I; + + // Figure out whether the current class has a template: + ClassTemplateDecl *CTD; + + // A specialization of the template... + if (isa<ClassTemplateSpecializationDecl>(Record)) { + CTD = cast<ClassTemplateSpecializationDecl>(Record) + ->getSpecializedTemplate(); + + // ... or the template pattern itself. + } else { + CTD = Record->getDescribedClassTemplate(); + if (!CTD) continue; + } + + // It's a match. + if (Friend == CTD->getCanonicalDecl()) + return AR_accessible; + + // If the context isn't dependent, it can't be a dependent match. + if (!EC.isDependent()) + continue; + + // If the template names don't match, it can't be a dependent + // match. + if (CTD->getDeclName() != Friend->getDeclName()) + continue; + + // If the class's context can't instantiate to the friend's + // context, it can't be a dependent match. + if (!MightInstantiateTo(S, CTD->getDeclContext(), + Friend->getDeclContext())) + continue; + + // Otherwise, it's a dependent match. + OnFailure = AR_dependent; + } + + return OnFailure; +} + +/// Determines whether the given friend function matches anything in +/// the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + FunctionDecl *Friend) { + AccessResult OnFailure = AR_inaccessible; + + for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator + I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { + if (Friend == *I) + return AR_accessible; + + if (EC.isDependent() && MightInstantiateTo(S, *I, Friend)) + OnFailure = AR_dependent; + } + + return OnFailure; +} + +/// Determines whether the given friend function template matches +/// anything in the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + FunctionTemplateDecl *Friend) { + if (EC.Functions.empty()) return AR_inaccessible; + + AccessResult OnFailure = AR_inaccessible; + + for (llvm::SmallVectorImpl<FunctionDecl*>::const_iterator + I = EC.Functions.begin(), E = EC.Functions.end(); I != E; ++I) { + + FunctionTemplateDecl *FTD = (*I)->getPrimaryTemplate(); + if (!FTD) + FTD = (*I)->getDescribedFunctionTemplate(); + if (!FTD) + continue; + + FTD = FTD->getCanonicalDecl(); + + if (Friend == FTD) + return AR_accessible; + + if (EC.isDependent() && MightInstantiateTo(S, FTD, Friend)) + OnFailure = AR_dependent; + } + + return OnFailure; +} + +/// Determines whether the given friend declaration matches anything +/// in the effective context. +static AccessResult MatchesFriend(Sema &S, + const EffectiveContext &EC, + FriendDecl *FriendD) { + // Whitelist accesses if there's an invalid or unsupported friend + // declaration. + if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) + return AR_accessible; + + if (TypeSourceInfo *T = FriendD->getFriendType()) + return MatchesFriend(S, EC, T->getType()->getCanonicalTypeUnqualified()); + + NamedDecl *Friend + = cast<NamedDecl>(FriendD->getFriendDecl()->getCanonicalDecl()); + + // FIXME: declarations with dependent or templated scope. + + if (isa<ClassTemplateDecl>(Friend)) + return MatchesFriend(S, EC, cast<ClassTemplateDecl>(Friend)); + + if (isa<FunctionTemplateDecl>(Friend)) + return MatchesFriend(S, EC, cast<FunctionTemplateDecl>(Friend)); + + if (isa<CXXRecordDecl>(Friend)) + return MatchesFriend(S, EC, cast<CXXRecordDecl>(Friend)); + + assert(isa<FunctionDecl>(Friend) && "unknown friend decl kind"); + return MatchesFriend(S, EC, cast<FunctionDecl>(Friend)); +} + +static AccessResult GetFriendKind(Sema &S, + const EffectiveContext &EC, + const CXXRecordDecl *Class) { + AccessResult OnFailure = AR_inaccessible; + + // Okay, check friends. + for (CXXRecordDecl::friend_iterator I = Class->friend_begin(), + E = Class->friend_end(); I != E; ++I) { + FriendDecl *Friend = *I; + + switch (MatchesFriend(S, EC, Friend)) { + case AR_accessible: + return AR_accessible; + + case AR_inaccessible: + continue; + + case AR_dependent: + OnFailure = AR_dependent; + break; + } + } + + // That's it, give up. + return OnFailure; +} + +namespace { + +/// A helper class for checking for a friend which will grant access +/// to a protected instance member. +struct ProtectedFriendContext { + Sema &S; + const EffectiveContext &EC; + const CXXRecordDecl *NamingClass; + bool CheckDependent; + bool EverDependent; + + /// The path down to the current base class. + llvm::SmallVector<const CXXRecordDecl*, 20> CurPath; + + ProtectedFriendContext(Sema &S, const EffectiveContext &EC, + const CXXRecordDecl *InstanceContext, + const CXXRecordDecl *NamingClass) + : S(S), EC(EC), NamingClass(NamingClass), + CheckDependent(InstanceContext->isDependentContext() || + NamingClass->isDependentContext()), + EverDependent(false) {} + + /// Check classes in the current path for friendship, starting at + /// the given index. + bool checkFriendshipAlongPath(unsigned I) { + assert(I < CurPath.size()); + for (unsigned E = CurPath.size(); I != E; ++I) { + switch (GetFriendKind(S, EC, CurPath[I])) { + case AR_accessible: return true; + case AR_inaccessible: continue; + case AR_dependent: EverDependent = true; continue; + } + } + return false; + } + + /// Perform a search starting at the given class. + /// + /// PrivateDepth is the index of the last (least derived) class + /// along the current path such that a notional public member of + /// the final class in the path would have access in that class. + bool findFriendship(const CXXRecordDecl *Cur, unsigned PrivateDepth) { + // If we ever reach the naming class, check the current path for + // friendship. We can also stop recursing because we obviously + // won't find the naming class there again. + if (Cur == NamingClass) + return checkFriendshipAlongPath(PrivateDepth); + + if (CheckDependent && MightInstantiateTo(Cur, NamingClass)) + EverDependent = true; + + // Recurse into the base classes. + for (CXXRecordDecl::base_class_const_iterator + I = Cur->bases_begin(), E = Cur->bases_end(); I != E; ++I) { + + // If this is private inheritance, then a public member of the + // base will not have any access in classes derived from Cur. + unsigned BasePrivateDepth = PrivateDepth; + if (I->getAccessSpecifier() == AS_private) + BasePrivateDepth = CurPath.size() - 1; + + const CXXRecordDecl *RD; + + QualType T = I->getType(); + if (const RecordType *RT = T->getAs<RecordType>()) { + RD = cast<CXXRecordDecl>(RT->getDecl()); + } else if (const InjectedClassNameType *IT + = T->getAs<InjectedClassNameType>()) { + RD = IT->getDecl(); + } else { + assert(T->isDependentType() && "non-dependent base wasn't a record?"); + EverDependent = true; + continue; + } + + // Recurse. We don't need to clean up if this returns true. + CurPath.push_back(RD); + if (findFriendship(RD->getCanonicalDecl(), BasePrivateDepth)) + return true; + CurPath.pop_back(); + } + + return false; + } + + bool findFriendship(const CXXRecordDecl *Cur) { + assert(CurPath.empty()); + CurPath.push_back(Cur); + return findFriendship(Cur, 0); + } +}; +} + +/// Search for a class P that EC is a friend of, under the constraint +/// InstanceContext <= P <= NamingClass +/// and with the additional restriction that a protected member of +/// NamingClass would have some natural access in P. +/// +/// That second condition isn't actually quite right: the condition in +/// the standard is whether the target would have some natural access +/// in P. The difference is that the target might be more accessible +/// along some path not passing through NamingClass. Allowing that +/// introduces two problems: +/// - It breaks encapsulation because you can suddenly access a +/// forbidden base class's members by subclassing it elsewhere. +/// - It makes access substantially harder to compute because it +/// breaks the hill-climbing algorithm: knowing that the target is +/// accessible in some base class would no longer let you change +/// the question solely to whether the base class is accessible, +/// because the original target might have been more accessible +/// because of crazy subclassing. +/// So we don't implement that. +static AccessResult GetProtectedFriendKind(Sema &S, const EffectiveContext &EC, + const CXXRecordDecl *InstanceContext, + const CXXRecordDecl *NamingClass) { + assert(InstanceContext->getCanonicalDecl() == InstanceContext); + assert(NamingClass->getCanonicalDecl() == NamingClass); + + ProtectedFriendContext PRC(S, EC, InstanceContext, NamingClass); + if (PRC.findFriendship(InstanceContext)) return AR_accessible; + if (PRC.EverDependent) return AR_dependent; + return AR_inaccessible; +} + +static AccessResult HasAccess(Sema &S, + const EffectiveContext &EC, + const CXXRecordDecl *NamingClass, + AccessSpecifier Access, + const AccessTarget &Target) { + assert(NamingClass->getCanonicalDecl() == NamingClass && + "declaration should be canonicalized before being passed here"); + + if (Access == AS_public) return AR_accessible; + assert(Access == AS_private || Access == AS_protected); + + AccessResult OnFailure = AR_inaccessible; + + for (EffectiveContext::record_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + // All the declarations in EC have been canonicalized, so pointer + // equality from this point on will work fine. + const CXXRecordDecl *ECRecord = *I; + + // [B2] and [M2] + if (Access == AS_private) { + if (ECRecord == NamingClass) + return AR_accessible; + + if (EC.isDependent() && MightInstantiateTo(ECRecord, NamingClass)) + OnFailure = AR_dependent; + + // [B3] and [M3] + } else { + assert(Access == AS_protected); + switch (IsDerivedFromInclusive(ECRecord, NamingClass)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: OnFailure = AR_dependent; continue; + } + + if (!Target.hasInstanceContext()) + return AR_accessible; + + const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); + if (!InstanceContext) { + OnFailure = AR_dependent; + continue; + } + + // C++ [class.protected]p1: + // An additional access check beyond those described earlier in + // [class.access] is applied when a non-static data member or + // non-static member function is a protected member of its naming + // class. As described earlier, access to a protected member is + // granted because the reference occurs in a friend or member of + // some class C. If the access is to form a pointer to member, + // the nested-name-specifier shall name C or a class derived from + // C. All other accesses involve a (possibly implicit) object + // expression. In this case, the class of the object expression + // shall be C or a class derived from C. + // + // We interpret this as a restriction on [M3]. Most of the + // conditions are encoded by not having any instance context. + switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { + case AR_accessible: return AR_accessible; + case AR_inaccessible: continue; + case AR_dependent: OnFailure = AR_dependent; continue; + } + } + } + + // [M3] and [B3] say that, if the target is protected in N, we grant + // access if the access occurs in a friend or member of some class P + // that's a subclass of N and where the target has some natural + // access in P. The 'member' aspect is easy to handle because P + // would necessarily be one of the effective-context records, and we + // address that above. The 'friend' aspect is completely ridiculous + // to implement because there are no restrictions at all on P + // *unless* the [class.protected] restriction applies. If it does, + // however, we should ignore whether the naming class is a friend, + // and instead rely on whether any potential P is a friend. + if (Access == AS_protected && Target.hasInstanceContext()) { + const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); + if (!InstanceContext) return AR_dependent; + switch (GetProtectedFriendKind(S, EC, InstanceContext, NamingClass)) { + case AR_accessible: return AR_accessible; + case AR_inaccessible: return OnFailure; + case AR_dependent: return AR_dependent; + } + llvm_unreachable("impossible friendship kind"); + } + + switch (GetFriendKind(S, EC, NamingClass)) { + case AR_accessible: return AR_accessible; + case AR_inaccessible: return OnFailure; + case AR_dependent: return AR_dependent; + } + + // Silence bogus warnings + llvm_unreachable("impossible friendship kind"); + return OnFailure; +} + +/// Finds the best path from the naming class to the declaring class, +/// taking friend declarations into account. +/// +/// C++0x [class.access.base]p5: +/// A member m is accessible at the point R when named in class N if +/// [M1] m as a member of N is public, or +/// [M2] m as a member of N is private, and R occurs in a member or +/// friend of class N, or +/// [M3] m as a member of N is protected, and R occurs in a member or +/// friend of class N, or in a member or friend of a class P +/// derived from N, where m as a member of P is public, private, +/// or protected, or +/// [M4] there exists a base class B of N that is accessible at R, and +/// m is accessible at R when named in class B. +/// +/// C++0x [class.access.base]p4: +/// A base class B of N is accessible at R, if +/// [B1] an invented public member of B would be a public member of N, or +/// [B2] R occurs in a member or friend of class N, and an invented public +/// member of B would be a private or protected member of N, or +/// [B3] R occurs in a member or friend of a class P derived from N, and an +/// invented public member of B would be a private or protected member +/// of P, or +/// [B4] there exists a class S such that B is a base class of S accessible +/// at R and S is a base class of N accessible at R. +/// +/// Along a single inheritance path we can restate both of these +/// iteratively: +/// +/// First, we note that M1-4 are equivalent to B1-4 if the member is +/// treated as a notional base of its declaring class with inheritance +/// access equivalent to the member's access. Therefore we need only +/// ask whether a class B is accessible from a class N in context R. +/// +/// Let B_1 .. B_n be the inheritance path in question (i.e. where +/// B_1 = N, B_n = B, and for all i, B_{i+1} is a direct base class of +/// B_i). For i in 1..n, we will calculate ACAB(i), the access to the +/// closest accessible base in the path: +/// Access(a, b) = (* access on the base specifier from a to b *) +/// Merge(a, forbidden) = forbidden +/// Merge(a, private) = forbidden +/// Merge(a, b) = min(a,b) +/// Accessible(c, forbidden) = false +/// Accessible(c, private) = (R is c) || IsFriend(c, R) +/// Accessible(c, protected) = (R derived from c) || IsFriend(c, R) +/// Accessible(c, public) = true +/// ACAB(n) = public +/// ACAB(i) = +/// let AccessToBase = Merge(Access(B_i, B_{i+1}), ACAB(i+1)) in +/// if Accessible(B_i, AccessToBase) then public else AccessToBase +/// +/// B is an accessible base of N at R iff ACAB(1) = public. +/// +/// \param FinalAccess the access of the "final step", or AS_public if +/// there is no final step. +/// \return null if friendship is dependent +static CXXBasePath *FindBestPath(Sema &S, + const EffectiveContext &EC, + AccessTarget &Target, + AccessSpecifier FinalAccess, + CXXBasePaths &Paths) { + // Derive the paths to the desired base. + const CXXRecordDecl *Derived = Target.getNamingClass(); + const CXXRecordDecl *Base = Target.getDeclaringClass(); + + // FIXME: fail correctly when there are dependent paths. + bool isDerived = Derived->isDerivedFrom(const_cast<CXXRecordDecl*>(Base), + Paths); + assert(isDerived && "derived class not actually derived from base"); + (void) isDerived; + + CXXBasePath *BestPath = 0; + + assert(FinalAccess != AS_none && "forbidden access after declaring class"); + + bool AnyDependent = false; + + // Derive the friend-modified access along each path. + for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); + PI != PE; ++PI) { + AccessTarget::SavedInstanceContext _ = Target.saveInstanceContext(); + + // Walk through the path backwards. + AccessSpecifier PathAccess = FinalAccess; + CXXBasePath::iterator I = PI->end(), E = PI->begin(); + while (I != E) { + --I; + + assert(PathAccess != AS_none); + + // If the declaration is a private member of a base class, there + // is no level of friendship in derived classes that can make it + // accessible. + if (PathAccess == AS_private) { + PathAccess = AS_none; + break; + } + + const CXXRecordDecl *NC = I->Class->getCanonicalDecl(); + + AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); + PathAccess = std::max(PathAccess, BaseAccess); + + switch (HasAccess(S, EC, NC, PathAccess, Target)) { + case AR_inaccessible: break; + case AR_accessible: + PathAccess = AS_public; + + // Future tests are not against members and so do not have + // instance context. + Target.suppressInstanceContext(); + break; + case AR_dependent: + AnyDependent = true; + goto Next; + } + } + + // Note that we modify the path's Access field to the + // friend-modified access. + if (BestPath == 0 || PathAccess < BestPath->Access) { + BestPath = &*PI; + BestPath->Access = PathAccess; + + // Short-circuit if we found a public path. + if (BestPath->Access == AS_public) + return BestPath; + } + + Next: ; + } + + assert((!BestPath || BestPath->Access != AS_public) && + "fell out of loop with public path"); + + // We didn't find a public path, but at least one path was subject + // to dependent friendship, so delay the check. + if (AnyDependent) + return 0; + + return BestPath; +} + +/// Given that an entity has protected natural access, check whether +/// access might be denied because of the protected member access +/// restriction. +/// +/// \return true if a note was emitted +static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, + AccessTarget &Target) { + // Only applies to instance accesses. + if (!Target.hasInstanceContext()) + return false; + assert(Target.isMemberAccess()); + NamedDecl *D = Target.getTargetDecl(); + + const CXXRecordDecl *DeclaringClass = Target.getDeclaringClass(); + DeclaringClass = DeclaringClass->getCanonicalDecl(); + + for (EffectiveContext::record_iterator + I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { + const CXXRecordDecl *ECRecord = *I; + switch (IsDerivedFromInclusive(ECRecord, DeclaringClass)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: continue; + } + + // The effective context is a subclass of the declaring class. + // If that class isn't a superclass of the instance context, + // then the [class.protected] restriction applies. + + // To get this exactly right, this might need to be checked more + // holistically; it's not necessarily the case that gaining + // access here would grant us access overall. + + const CXXRecordDecl *InstanceContext = Target.resolveInstanceContext(S); + assert(InstanceContext && "diagnosing dependent access"); + + switch (IsDerivedFromInclusive(InstanceContext, ECRecord)) { + case AR_accessible: continue; + case AR_dependent: continue; + case AR_inaccessible: + S.Diag(D->getLocation(), diag::note_access_protected_restricted) + << (InstanceContext != Target.getNamingClass()->getCanonicalDecl()) + << S.Context.getTypeDeclType(InstanceContext) + << S.Context.getTypeDeclType(ECRecord); + return true; + } + } + + return false; +} + +/// Diagnose the path which caused the given declaration or base class +/// to become inaccessible. +static void DiagnoseAccessPath(Sema &S, + const EffectiveContext &EC, + AccessTarget &Entity) { + AccessSpecifier Access = Entity.getAccess(); + const CXXRecordDecl *NamingClass = Entity.getNamingClass(); + NamingClass = NamingClass->getCanonicalDecl(); + + NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); + const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); + + // Easy case: the decl's natural access determined its path access. + // We have to check against AS_private here in case Access is AS_none, + // indicating a non-public member of a private base class. + if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { + switch (HasAccess(S, EC, DeclaringClass, D->getAccess(), Entity)) { + case AR_inaccessible: { + if (Access == AS_protected && + TryDiagnoseProtectedAccess(S, EC, Entity)) + return; + + // Find an original declaration. + while (D->isOutOfLine()) { + NamedDecl *PrevDecl = 0; + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + PrevDecl = VD->getPreviousDeclaration(); + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + PrevDecl = FD->getPreviousDeclaration(); + else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) + PrevDecl = TND->getPreviousDeclaration(); + else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) + break; + PrevDecl = TD->getPreviousDeclaration(); + } + if (!PrevDecl) break; + D = PrevDecl; + } + + CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); + Decl *ImmediateChild; + if (D->getDeclContext() == DeclaringClass) + ImmediateChild = D; + else { + DeclContext *DC = D->getDeclContext(); + while (DC->getParent() != DeclaringClass) + DC = DC->getParent(); + ImmediateChild = cast<Decl>(DC); + } + + // Check whether there's an AccessSpecDecl preceding this in the + // chain of the DeclContext. + bool Implicit = true; + for (CXXRecordDecl::decl_iterator + I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end(); + I != E; ++I) { + if (*I == ImmediateChild) break; + if (isa<AccessSpecDecl>(*I)) { + Implicit = false; + break; + } + } + + S.Diag(D->getLocation(), diag::note_access_natural) + << (unsigned) (Access == AS_protected) + << Implicit; + return; + } + + case AR_accessible: break; + + case AR_dependent: + llvm_unreachable("can't diagnose dependent access failures"); + return; + } + } + + CXXBasePaths Paths; + CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths); + + CXXBasePath::iterator I = Path.end(), E = Path.begin(); + while (I != E) { + --I; + + const CXXBaseSpecifier *BS = I->Base; + AccessSpecifier BaseAccess = BS->getAccessSpecifier(); + + // If this is public inheritance, or the derived class is a friend, + // skip this step. + if (BaseAccess == AS_public) + continue; + + switch (GetFriendKind(S, EC, I->Class)) { + case AR_accessible: continue; + case AR_inaccessible: break; + case AR_dependent: + llvm_unreachable("can't diagnose dependent access failures"); + } + + // Check whether this base specifier is the tighest point + // constraining access. We have to check against AS_private for + // the same reasons as above. + if (BaseAccess == AS_private || BaseAccess >= Access) { + + // We're constrained by inheritance, but we want to say + // "declared private here" if we're diagnosing a hierarchy + // conversion and this is the final step. + unsigned diagnostic; + if (D) diagnostic = diag::note_access_constrained_by_path; + else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; + else diagnostic = diag::note_access_constrained_by_path; + + S.Diag(BS->getSourceRange().getBegin(), diagnostic) + << BS->getSourceRange() + << (BaseAccess == AS_protected) + << (BS->getAccessSpecifierAsWritten() == AS_none); + + if (D) + S.Diag(D->getLocation(), diag::note_field_decl); + + return; + } + } + + llvm_unreachable("access not apparently constrained by path"); +} + +static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, + const EffectiveContext &EC, + AccessTarget &Entity) { + const CXXRecordDecl *NamingClass = Entity.getNamingClass(); + const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); + NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); + + S.Diag(Loc, Entity.getDiag()) + << (Entity.getAccess() == AS_protected) + << (D ? D->getDeclName() : DeclarationName()) + << S.Context.getTypeDeclType(NamingClass) + << S.Context.getTypeDeclType(DeclaringClass); + DiagnoseAccessPath(S, EC, Entity); +} + +/// MSVC has a bug where if during an using declaration name lookup, +/// the declaration found is unaccessible (private) and that declaration +/// was bring into scope via another using declaration whose target +/// declaration is accessible (public) then no error is generated. +/// Example: +/// class A { +/// public: +/// int f(); +/// }; +/// class B : public A { +/// private: +/// using A::f; +/// }; +/// class C : public B { +/// private: +/// using B::f; +/// }; +/// +/// Here, B::f is private so this should fail in Standard C++, but +/// because B::f refers to A::f which is public MSVC accepts it. +static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, + SourceLocation AccessLoc, + AccessTarget &Entity) { + if (UsingShadowDecl *Shadow = + dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) { + const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl(); + if (Entity.getTargetDecl()->getAccess() == AS_private && + (OrigDecl->getAccess() == AS_public || + OrigDecl->getAccess() == AS_protected)) { + S.Diag(AccessLoc, diag::war_ms_using_declaration_inaccessible) + << Shadow->getUsingDecl()->getQualifiedNameAsString() + << OrigDecl->getQualifiedNameAsString(); + return true; + } + } + return false; +} + +/// Determines whether the accessed entity is accessible. Public members +/// have been weeded out by this point. +static AccessResult IsAccessible(Sema &S, + const EffectiveContext &EC, + AccessTarget &Entity) { + // Determine the actual naming class. + CXXRecordDecl *NamingClass = Entity.getNamingClass(); + while (NamingClass->isAnonymousStructOrUnion()) + NamingClass = cast<CXXRecordDecl>(NamingClass->getParent()); + NamingClass = NamingClass->getCanonicalDecl(); + + AccessSpecifier UnprivilegedAccess = Entity.getAccess(); + assert(UnprivilegedAccess != AS_public && "public access not weeded out"); + + // Before we try to recalculate access paths, try to white-list + // accesses which just trade in on the final step, i.e. accesses + // which don't require [M4] or [B4]. These are by far the most + // common forms of privileged access. + if (UnprivilegedAccess != AS_none) { + switch (HasAccess(S, EC, NamingClass, UnprivilegedAccess, Entity)) { + case AR_dependent: + // This is actually an interesting policy decision. We don't + // *have* to delay immediately here: we can do the full access + // calculation in the hope that friendship on some intermediate + // class will make the declaration accessible non-dependently. + // But that's not cheap, and odds are very good (note: assertion + // made without data) that the friend declaration will determine + // access. + return AR_dependent; + + case AR_accessible: return AR_accessible; + case AR_inaccessible: break; + } + } + + AccessTarget::SavedInstanceContext _ = Entity.saveInstanceContext(); + + // We lower member accesses to base accesses by pretending that the + // member is a base class of its declaring class. + AccessSpecifier FinalAccess; + + if (Entity.isMemberAccess()) { + // Determine if the declaration is accessible from EC when named + // in its declaring class. + NamedDecl *Target = Entity.getTargetDecl(); + const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); + + FinalAccess = Target->getAccess(); + switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { + case AR_accessible: + FinalAccess = AS_public; + break; + case AR_inaccessible: break; + case AR_dependent: return AR_dependent; // see above + } + + if (DeclaringClass == NamingClass) + return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); + + Entity.suppressInstanceContext(); + } else { + FinalAccess = AS_public; + } + + assert(Entity.getDeclaringClass() != NamingClass); + + // Append the declaration's access if applicable. + CXXBasePaths Paths; + CXXBasePath *Path = FindBestPath(S, EC, Entity, FinalAccess, Paths); + if (!Path) + return AR_dependent; + + assert(Path->Access <= UnprivilegedAccess && + "access along best path worse than direct?"); + if (Path->Access == AS_public) + return AR_accessible; + return AR_inaccessible; +} + +static void DelayDependentAccess(Sema &S, + const EffectiveContext &EC, + SourceLocation Loc, + const AccessTarget &Entity) { + assert(EC.isDependent() && "delaying non-dependent access"); + DeclContext *DC = EC.getInnerContext(); + assert(DC->isDependentContext() && "delaying non-dependent access"); + DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access, + Loc, + Entity.isMemberAccess(), + Entity.getAccess(), + Entity.getTargetDecl(), + Entity.getNamingClass(), + Entity.getBaseObjectType(), + Entity.getDiag()); +} + +/// Checks access to an entity from the given effective context. +static AccessResult CheckEffectiveAccess(Sema &S, + const EffectiveContext &EC, + SourceLocation Loc, + AccessTarget &Entity) { + assert(Entity.getAccess() != AS_public && "called for public access!"); + + if (S.getLangOptions().Microsoft && + IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity)) + return AR_accessible; + + switch (IsAccessible(S, EC, Entity)) { + case AR_dependent: + DelayDependentAccess(S, EC, Loc, Entity); + return AR_dependent; + + case AR_inaccessible: + if (!Entity.isQuiet()) + DiagnoseBadAccess(S, Loc, EC, Entity); + return AR_inaccessible; + + case AR_accessible: + return AR_accessible; + } + + // silence unnecessary warning + llvm_unreachable("invalid access result"); + return AR_accessible; +} + +static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, + AccessTarget &Entity) { + // If the access path is public, it's accessible everywhere. + if (Entity.getAccess() == AS_public) + return Sema::AR_accessible; + + if (S.SuppressAccessChecking) + return Sema::AR_accessible; + + // If we're currently parsing a declaration, we may need to delay + // access control checking, because our effective context might be + // different based on what the declaration comes out as. + // + // For example, we might be parsing a declaration with a scope + // specifier, like this: + // A::private_type A::foo() { ... } + // + // Or we might be parsing something that will turn out to be a friend: + // void foo(A::private_type); + // void B::foo(A::private_type); + if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { + S.DelayedDiagnostics.add(DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; + } + + EffectiveContext EC(S.CurContext); + switch (CheckEffectiveAccess(S, EC, Loc, Entity)) { + case AR_accessible: return Sema::AR_accessible; + case AR_inaccessible: return Sema::AR_inaccessible; + case AR_dependent: return Sema::AR_dependent; + } + llvm_unreachable("falling off end"); + return Sema::AR_accessible; +} + +void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) { + // Access control for names used in the declarations of functions + // and function templates should normally be evaluated in the context + // of the declaration, just in case it's a friend of something. + // However, this does not apply to local extern declarations. + + DeclContext *DC = decl->getDeclContext(); + if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { + if (!DC->isFunctionOrMethod()) DC = fn; + } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) { + // Never a local declaration. + DC = fnt->getTemplatedDecl(); + } + + EffectiveContext EC(DC); + + AccessTarget Target(DD.getAccessData()); + + if (CheckEffectiveAccess(*this, EC, DD.Loc, Target) == ::AR_inaccessible) + DD.Triggered = true; +} + +void Sema::HandleDependentAccessCheck(const DependentDiagnostic &DD, + const MultiLevelTemplateArgumentList &TemplateArgs) { + SourceLocation Loc = DD.getAccessLoc(); + AccessSpecifier Access = DD.getAccess(); + + Decl *NamingD = FindInstantiatedDecl(Loc, DD.getAccessNamingClass(), + TemplateArgs); + if (!NamingD) return; + Decl *TargetD = FindInstantiatedDecl(Loc, DD.getAccessTarget(), + TemplateArgs); + if (!TargetD) return; + + if (DD.isAccessToMember()) { + CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(NamingD); + NamedDecl *TargetDecl = cast<NamedDecl>(TargetD); + QualType BaseObjectType = DD.getAccessBaseObjectType(); + if (!BaseObjectType.isNull()) { + BaseObjectType = SubstType(BaseObjectType, TemplateArgs, Loc, + DeclarationName()); + if (BaseObjectType.isNull()) return; + } + + AccessTarget Entity(Context, + AccessTarget::Member, + NamingClass, + DeclAccessPair::make(TargetDecl, Access), + BaseObjectType); + Entity.setDiag(DD.getDiagnostic()); + CheckAccess(*this, Loc, Entity); + } else { + AccessTarget Entity(Context, + AccessTarget::Base, + cast<CXXRecordDecl>(TargetD), + cast<CXXRecordDecl>(NamingD), + Access); + Entity.setDiag(DD.getDiagnostic()); + CheckAccess(*this, Loc, Entity); + } +} + +Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + DeclAccessPair Found) { + if (!getLangOptions().AccessControl || + !E->getNamingClass() || + Found.getAccess() == AS_public) + return AR_accessible; + + AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), + Found, QualType()); + Entity.setDiag(diag::err_access) << E->getSourceRange(); + + return CheckAccess(*this, E->getNameLoc(), Entity); +} + +/// Perform access-control checking on a previously-unresolved member +/// access which has now been resolved to a member. +Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + DeclAccessPair Found) { + if (!getLangOptions().AccessControl || + Found.getAccess() == AS_public) + return AR_accessible; + + QualType BaseType = E->getBaseType(); + if (E->isArrow()) + BaseType = BaseType->getAs<PointerType>()->getPointeeType(); + + AccessTarget Entity(Context, AccessTarget::Member, E->getNamingClass(), + Found, BaseType); + Entity.setDiag(diag::err_access) << E->getSourceRange(); + + return CheckAccess(*this, E->getMemberLoc(), Entity); +} + +Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, + CXXDestructorDecl *Dtor, + const PartialDiagnostic &PDiag) { + if (!getLangOptions().AccessControl) + return AR_accessible; + + // There's never a path involved when checking implicit destructor access. + AccessSpecifier Access = Dtor->getAccess(); + if (Access == AS_public) + return AR_accessible; + + CXXRecordDecl *NamingClass = Dtor->getParent(); + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(Dtor, Access), + QualType()); + Entity.setDiag(PDiag); // TODO: avoid copy + + return CheckAccess(*this, Loc, Entity); +} + +/// Checks access to a constructor. +Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, + CXXConstructorDecl *Constructor, + const InitializedEntity &Entity, + AccessSpecifier Access, + bool IsCopyBindingRefToTemp) { + if (!getLangOptions().AccessControl || + Access == AS_public) + return AR_accessible; + + CXXRecordDecl *NamingClass = Constructor->getParent(); + AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(Constructor, Access), + QualType()); + PartialDiagnostic PD(PDiag()); + switch (Entity.getKind()) { + default: + PD = PDiag(IsCopyBindingRefToTemp + ? diag::ext_rvalue_to_reference_access_ctor + : diag::err_access_ctor); + + break; + + case InitializedEntity::EK_Base: + PD = PDiag(diag::err_access_base_ctor); + PD << Entity.isInheritedVirtualBase() + << Entity.getBaseSpecifier()->getType() << getSpecialMember(Constructor); + break; + + case InitializedEntity::EK_Member: { + const FieldDecl *Field = cast<FieldDecl>(Entity.getDecl()); + PD = PDiag(diag::err_access_field_ctor); + PD << Field->getType() << getSpecialMember(Constructor); + break; + } + + } + + return CheckConstructorAccess(UseLoc, Constructor, Access, PD); +} + +/// Checks access to a constructor. +Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, + CXXConstructorDecl *Constructor, + AccessSpecifier Access, + PartialDiagnostic PD) { + if (!getLangOptions().AccessControl || + Access == AS_public) + return AR_accessible; + + CXXRecordDecl *NamingClass = Constructor->getParent(); + AccessTarget AccessEntity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(Constructor, Access), + QualType()); + AccessEntity.setDiag(PD); + + return CheckAccess(*this, UseLoc, AccessEntity); +} + +/// Checks direct (i.e. non-inherited) access to an arbitrary class +/// member. +Sema::AccessResult Sema::CheckDirectMemberAccess(SourceLocation UseLoc, + NamedDecl *Target, + const PartialDiagnostic &Diag) { + AccessSpecifier Access = Target->getAccess(); + if (!getLangOptions().AccessControl || + Access == AS_public) + return AR_accessible; + + CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(Target->getDeclContext()); + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, + DeclAccessPair::make(Target, Access), + QualType()); + Entity.setDiag(Diag); + return CheckAccess(*this, UseLoc, Entity); +} + + +/// Checks access to an overloaded operator new or delete. +Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, + SourceRange PlacementRange, + CXXRecordDecl *NamingClass, + DeclAccessPair Found, + bool Diagnose) { + if (!getLangOptions().AccessControl || + !NamingClass || + Found.getAccess() == AS_public) + return AR_accessible; + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, + QualType()); + if (Diagnose) + Entity.setDiag(diag::err_access) + << PlacementRange; + + return CheckAccess(*this, OpLoc, Entity); +} + +/// Checks access to an overloaded member operator, including +/// conversion operators. +Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, + Expr *ObjectExpr, + Expr *ArgExpr, + DeclAccessPair Found) { + if (!getLangOptions().AccessControl || + Found.getAccess() == AS_public) + return AR_accessible; + + const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); + assert(RT && "found member operator but object expr not of record type"); + CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, + ObjectExpr->getType()); + Entity.setDiag(diag::err_access) + << ObjectExpr->getSourceRange() + << (ArgExpr ? ArgExpr->getSourceRange() : SourceRange()); + + return CheckAccess(*this, OpLoc, Entity); +} + +Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, + DeclAccessPair Found) { + if (!getLangOptions().AccessControl || + Found.getAccess() == AS_none || + Found.getAccess() == AS_public) + return AR_accessible; + + OverloadExpr *Ovl = OverloadExpr::find(OvlExpr).Expression; + CXXRecordDecl *NamingClass = Ovl->getNamingClass(); + + AccessTarget Entity(Context, AccessTarget::Member, NamingClass, Found, + Context.getTypeDeclType(NamingClass)); + Entity.setDiag(diag::err_access) + << Ovl->getSourceRange(); + + return CheckAccess(*this, Ovl->getNameLoc(), Entity); +} + +/// Checks access for a hierarchy conversion. +/// +/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) +/// or a derived-to-base conversion (false) +/// \param ForceCheck true if this check should be performed even if access +/// control is disabled; some things rely on this for semantics +/// \param ForceUnprivileged true if this check should proceed as if the +/// context had no special privileges +/// \param ADK controls the kind of diagnostics that are used +Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, + QualType Base, + QualType Derived, + const CXXBasePath &Path, + unsigned DiagID, + bool ForceCheck, + bool ForceUnprivileged) { + if (!ForceCheck && !getLangOptions().AccessControl) + return AR_accessible; + + if (Path.Access == AS_public) + return AR_accessible; + + CXXRecordDecl *BaseD, *DerivedD; + BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); + DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); + + AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, + Path.Access); + if (DiagID) + Entity.setDiag(DiagID) << Derived << Base; + + if (ForceUnprivileged) { + switch (CheckEffectiveAccess(*this, EffectiveContext(), + AccessLoc, Entity)) { + case ::AR_accessible: return Sema::AR_accessible; + case ::AR_inaccessible: return Sema::AR_inaccessible; + case ::AR_dependent: return Sema::AR_dependent; + } + llvm_unreachable("unexpected result from CheckEffectiveAccess"); + } + return CheckAccess(*this, AccessLoc, Entity); +} + +/// Checks access to all the declarations in the given result set. +void Sema::CheckLookupAccess(const LookupResult &R) { + assert(getLangOptions().AccessControl + && "performing access check without access control"); + assert(R.getNamingClass() && "performing access check without naming class"); + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + if (I.getAccess() != AS_public) { + AccessTarget Entity(Context, AccessedEntity::Member, + R.getNamingClass(), I.getPair(), + R.getBaseObjectType(), R.isUsingDeclaration()); + Entity.setDiag(diag::err_access); + CheckAccess(*this, R.getNameLoc(), Entity); + } + } +} + +void Sema::ActOnStartSuppressingAccessChecks() { + assert(!SuppressAccessChecking && + "Tried to start access check suppression when already started."); + SuppressAccessChecking = true; +} + +void Sema::ActOnStopSuppressingAccessChecks() { + assert(SuppressAccessChecking && + "Tried to stop access check suprression when already stopped."); + SuppressAccessChecking = false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp new file mode 100644 index 0000000..53dd297 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -0,0 +1,396 @@ +//===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for non-trivial attributes and +// pragmas. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/Attr.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" +using namespace clang; + +//===----------------------------------------------------------------------===// +// Pragma 'pack' and 'options align' +//===----------------------------------------------------------------------===// + +namespace { + struct PackStackEntry { + // We just use a sentinel to represent when the stack is set to mac68k + // alignment. + static const unsigned kMac68kAlignmentSentinel = ~0U; + + unsigned Alignment; + IdentifierInfo *Name; + }; + + /// PragmaPackStack - Simple class to wrap the stack used by #pragma + /// pack. + class PragmaPackStack { + typedef std::vector<PackStackEntry> stack_ty; + + /// Alignment - The current user specified alignment. + unsigned Alignment; + + /// Stack - Entries in the #pragma pack stack, consisting of saved + /// alignments and optional names. + stack_ty Stack; + + public: + PragmaPackStack() : Alignment(0) {} + + void setAlignment(unsigned A) { Alignment = A; } + unsigned getAlignment() { return Alignment; } + + /// push - Push the current alignment onto the stack, optionally + /// using the given \arg Name for the record, if non-zero. + void push(IdentifierInfo *Name) { + PackStackEntry PSE = { Alignment, Name }; + Stack.push_back(PSE); + } + + /// pop - Pop a record from the stack and restore the current + /// alignment to the previous value. If \arg Name is non-zero then + /// the first such named record is popped, otherwise the top record + /// is popped. Returns true if the pop succeeded. + bool pop(IdentifierInfo *Name, bool IsReset); + }; +} // end anonymous namespace. + +bool PragmaPackStack::pop(IdentifierInfo *Name, bool IsReset) { + // If name is empty just pop top. + if (!Name) { + // An empty stack is a special case... + if (Stack.empty()) { + // If this isn't a reset, it is always an error. + if (!IsReset) + return false; + + // Otherwise, it is an error only if some alignment has been set. + if (!Alignment) + return false; + + // Otherwise, reset to the default alignment. + Alignment = 0; + } else { + Alignment = Stack.back().Alignment; + Stack.pop_back(); + } + + return true; + } + + // Otherwise, find the named record. + for (unsigned i = Stack.size(); i != 0; ) { + --i; + if (Stack[i].Name == Name) { + // Found it, pop up to and including this record. + Alignment = Stack[i].Alignment; + Stack.erase(Stack.begin() + i, Stack.end()); + return true; + } + } + + return false; +} + + +/// FreePackedContext - Deallocate and null out PackContext. +void Sema::FreePackedContext() { + delete static_cast<PragmaPackStack*>(PackContext); + PackContext = 0; +} + +void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { + // If there is no pack context, we don't need any attributes. + if (!PackContext) + return; + + PragmaPackStack *Stack = static_cast<PragmaPackStack*>(PackContext); + + // Otherwise, check to see if we need a max field alignment attribute. + if (unsigned Alignment = Stack->getAlignment()) { + if (Alignment == PackStackEntry::kMac68kAlignmentSentinel) + RD->addAttr(::new (Context) AlignMac68kAttr(SourceLocation(), Context)); + else + RD->addAttr(::new (Context) MaxFieldAlignmentAttr(SourceLocation(), + Context, + Alignment * 8)); + } +} + +void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { + if (!MSStructPragmaOn) + return; + RD->addAttr(::new (Context) MsStructAttr(SourceLocation(), Context)); +} + +void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, + SourceLocation PragmaLoc, + SourceLocation KindLoc) { + if (PackContext == 0) + PackContext = new PragmaPackStack(); + + PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); + + // Reset just pops the top of the stack, or resets the current alignment to + // default. + if (Kind == Sema::POAK_Reset) { + if (!Context->pop(0, /*IsReset=*/true)) { + Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) + << "stack empty"; + } + return; + } + + switch (Kind) { + // For all targets we support native and natural are the same. + // + // FIXME: This is not true on Darwin/PPC. + case POAK_Native: + case POAK_Power: + case POAK_Natural: + Context->push(0); + Context->setAlignment(0); + break; + + // Note that '#pragma options align=packed' is not equivalent to attribute + // packed, it has a different precedence relative to attribute aligned. + case POAK_Packed: + Context->push(0); + Context->setAlignment(1); + break; + + case POAK_Mac68k: + // Check if the target supports this. + if (!PP.getTargetInfo().hasAlignMac68kSupport()) { + Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); + return; + } + Context->push(0); + Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); + break; + + default: + Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option) + << KindLoc; + break; + } +} + +void Sema::ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, + ExprTy *alignment, SourceLocation PragmaLoc, + SourceLocation LParenLoc, SourceLocation RParenLoc) { + Expr *Alignment = static_cast<Expr *>(alignment); + + // If specified then alignment must be a "small" power of two. + unsigned AlignmentVal = 0; + if (Alignment) { + llvm::APSInt Val; + + // pack(0) is like pack(), which just works out since that is what + // we use 0 for in PackAttr. + if (Alignment->isTypeDependent() || + Alignment->isValueDependent() || + !Alignment->isIntegerConstantExpr(Val, Context) || + !(Val == 0 || Val.isPowerOf2()) || + Val.getZExtValue() > 16) { + Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); + return; // Ignore + } + + AlignmentVal = (unsigned) Val.getZExtValue(); + } + + if (PackContext == 0) + PackContext = new PragmaPackStack(); + + PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); + + switch (Kind) { + case Sema::PPK_Default: // pack([n]) + Context->setAlignment(AlignmentVal); + break; + + case Sema::PPK_Show: // pack(show) + // Show the current alignment, making sure to show the right value + // for the default. + AlignmentVal = Context->getAlignment(); + // FIXME: This should come from the target. + if (AlignmentVal == 0) + AlignmentVal = 8; + if (AlignmentVal == PackStackEntry::kMac68kAlignmentSentinel) + Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; + else + Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; + break; + + case Sema::PPK_Push: // pack(push [, id] [, [n]) + Context->push(Name); + // Set the new alignment if specified. + if (Alignment) + Context->setAlignment(AlignmentVal); + break; + + case Sema::PPK_Pop: // pack(pop [, id] [, n]) + // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: + // "#pragma pack(pop, identifier, n) is undefined" + if (Alignment && Name) + Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifer_and_alignment); + + // Do the pop. + if (!Context->pop(Name, /*IsReset=*/false)) { + // If a name was specified then failure indicates the name + // wasn't found. Otherwise failure indicates the stack was + // empty. + Diag(PragmaLoc, diag::warn_pragma_pack_pop_failed) + << (Name ? "no record matching name" : "stack empty"); + + // FIXME: Warn about popping named records as MSVC does. + } else { + // Pop succeeded, set the new alignment if specified. + if (Alignment) + Context->setAlignment(AlignmentVal); + } + break; + + default: + assert(0 && "Invalid #pragma pack kind."); + } +} + +void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { + MSStructPragmaOn = (Kind == PMSST_ON); +} + +void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, + SourceLocation PragmaLoc) { + + IdentifierInfo *Name = IdTok.getIdentifierInfo(); + LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); + LookupParsedName(Lookup, curScope, NULL, true); + + if (Lookup.empty()) { + Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) + << Name << SourceRange(IdTok.getLocation()); + return; + } + + VarDecl *VD = Lookup.getAsSingle<VarDecl>(); + if (!VD) { + Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg) + << Name << SourceRange(IdTok.getLocation()); + return; + } + + // Warn if this was used before being marked unused. + if (VD->isUsed()) + Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; + + VD->addAttr(::new (Context) UnusedAttr(IdTok.getLocation(), Context)); +} + +typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; +enum { NoVisibility = (unsigned) -1 }; + +void Sema::AddPushedVisibilityAttribute(Decl *D) { + if (!VisContext) + return; + + if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility()) + return; + + VisStack *Stack = static_cast<VisStack*>(VisContext); + unsigned rawType = Stack->back().first; + if (rawType == NoVisibility) return; + + VisibilityAttr::VisibilityType type + = (VisibilityAttr::VisibilityType) rawType; + SourceLocation loc = Stack->back().second; + + D->addAttr(::new (Context) VisibilityAttr(loc, Context, type)); +} + +/// FreeVisContext - Deallocate and null out VisContext. +void Sema::FreeVisContext() { + delete static_cast<VisStack*>(VisContext); + VisContext = 0; +} + +static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { + // Put visibility on stack. + if (!S.VisContext) + S.VisContext = new VisStack; + + VisStack *Stack = static_cast<VisStack*>(S.VisContext); + Stack->push_back(std::make_pair(type, loc)); +} + +void Sema::ActOnPragmaVisibility(bool IsPush, const IdentifierInfo* VisType, + SourceLocation PragmaLoc) { + if (IsPush) { + // Compute visibility to use. + VisibilityAttr::VisibilityType type; + if (VisType->isStr("default")) + type = VisibilityAttr::Default; + else if (VisType->isStr("hidden")) + type = VisibilityAttr::Hidden; + else if (VisType->isStr("internal")) + type = VisibilityAttr::Hidden; // FIXME + else if (VisType->isStr("protected")) + type = VisibilityAttr::Protected; + else { + Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << + VisType->getName(); + return; + } + PushPragmaVisibility(*this, type, PragmaLoc); + } else { + PopPragmaVisibility(); + } +} + +void Sema::ActOnPragmaFPContract(tok::OnOffSwitch OOS) { + switch (OOS) { + case tok::OOS_ON: + FPFeatures.fp_contract = 1; + break; + case tok::OOS_OFF: + FPFeatures.fp_contract = 0; + break; + case tok::OOS_DEFAULT: + FPFeatures.fp_contract = getLangOptions().DefaultFPContract; + break; + } +} + +void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) { + // Visibility calculations will consider the namespace's visibility. + // Here we just want to note that we're in a visibility context + // which overrides any enclosing #pragma context, but doesn't itself + // contribute visibility. + PushPragmaVisibility(*this, NoVisibility, SourceLocation()); +} + +void Sema::PopPragmaVisibility() { + // Pop visibility from stack, if there is one on the stack. + if (VisContext) { + VisStack *Stack = static_cast<VisStack*>(VisContext); + + Stack->pop_back(); + // To simplify the implementation, never keep around an empty stack. + if (Stack->empty()) + FreeVisContext(); + } + // FIXME: Add diag for pop without push. +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp new file mode 100644 index 0000000..e46ad5b --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp @@ -0,0 +1,1720 @@ +//===--- SemaNamedCast.cpp - Semantic Analysis for Named Casts ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for C++ named casts. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/SmallVector.h" +#include <set> +using namespace clang; + + + +enum TryCastResult { + TC_NotApplicable, ///< The cast method is not applicable. + TC_Success, ///< The cast method is appropriate and successful. + TC_Failed ///< The cast method is appropriate, but failed. A + ///< diagnostic has been emitted. +}; + +enum CastType { + CT_Const, ///< const_cast + CT_Static, ///< static_cast + CT_Reinterpret, ///< reinterpret_cast + CT_Dynamic, ///< dynamic_cast + CT_CStyle, ///< (Type)expr + CT_Functional ///< Type(expr) +}; + + + + +static void CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + ExprValueKind &VK, + const SourceRange &OpRange, + const SourceRange &DestRange); +static void CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + ExprValueKind &VK, + const SourceRange &OpRange, + const SourceRange &DestRange, + CastKind &Kind); +static void CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + ExprValueKind &VK, + const SourceRange &OpRange, + CastKind &Kind, + CXXCastPath &BasePath); +static void CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + ExprValueKind &VK, + const SourceRange &OpRange, + const SourceRange &DestRange, + CastKind &Kind, + CXXCastPath &BasePath); + +static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType); + +// The Try functions attempt a specific way of casting. If they succeed, they +// return TC_Success. If their way of casting is not appropriate for the given +// arguments, they return TC_NotApplicable and *may* set diag to a diagnostic +// to emit if no other way succeeds. If their way of casting is appropriate but +// fails, they return TC_Failed and *must* set diag; they can set it to 0 if +// they emit a specialized diagnostic. +// All diagnostics returned by these functions must expect the same three +// arguments: +// %0: Cast Type (a value from the CastType enumeration) +// %1: Source Type +// %2: Destination Type +static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, + QualType DestType, bool CStyle, + CastKind &Kind, + CXXCastPath &BasePath, + unsigned &msg); +static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); +static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); +static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType, + CanQualType DestType, bool CStyle, + const SourceRange &OpRange, + QualType OrigSrcType, + QualType OrigDestType, unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); +static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, + QualType SrcType, + QualType DestType,bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); + +static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind); +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath); +static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, unsigned &msg); +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind); + + +/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. +ExprResult +Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, + SourceLocation LAngleBracketLoc, ParsedType Ty, + SourceLocation RAngleBracketLoc, + SourceLocation LParenLoc, Expr *E, + SourceLocation RParenLoc) { + + TypeSourceInfo *DestTInfo; + QualType DestType = GetTypeFromParser(Ty, &DestTInfo); + if (!DestTInfo) + DestTInfo = Context.getTrivialTypeSourceInfo(DestType, SourceLocation()); + + return BuildCXXNamedCast(OpLoc, Kind, DestTInfo, move(E), + SourceRange(LAngleBracketLoc, RAngleBracketLoc), + SourceRange(LParenLoc, RParenLoc)); +} + +ExprResult +Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, + TypeSourceInfo *DestTInfo, Expr *E, + SourceRange AngleBrackets, SourceRange Parens) { + ExprResult Ex = Owned(E); + QualType DestType = DestTInfo->getType(); + + SourceRange OpRange(OpLoc, Parens.getEnd()); + SourceRange DestRange = AngleBrackets; + + // If the type is dependent, we won't do the semantic analysis now. + // FIXME: should we check this in a more fine-grained manner? + bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent(); + + ExprValueKind VK = VK_RValue; + if (TypeDependent) + VK = Expr::getValueKindForType(DestType); + + switch (Kind) { + default: llvm_unreachable("Unknown C++ cast!"); + + case tok::kw_const_cast: + if (!TypeDependent) { + CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange); + if (Ex.isInvalid()) + return ExprError(); + } + return Owned(CXXConstCastExpr::Create(Context, + DestType.getNonLValueExprType(Context), + VK, Ex.take(), DestTInfo, OpLoc, + Parens.getEnd())); + + case tok::kw_dynamic_cast: { + CastKind Kind = CK_Dependent; + CXXCastPath BasePath; + if (!TypeDependent) { + CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange, + Kind, BasePath); + if (Ex.isInvalid()) + return ExprError(); + } + return Owned(CXXDynamicCastExpr::Create(Context, + DestType.getNonLValueExprType(Context), + VK, Kind, Ex.take(), &BasePath, DestTInfo, + OpLoc, Parens.getEnd())); + } + case tok::kw_reinterpret_cast: { + CastKind Kind = CK_Dependent; + if (!TypeDependent) { + CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind); + if (Ex.isInvalid()) + return ExprError(); + } + return Owned(CXXReinterpretCastExpr::Create(Context, + DestType.getNonLValueExprType(Context), + VK, Kind, Ex.take(), 0, + DestTInfo, OpLoc, Parens.getEnd())); + } + case tok::kw_static_cast: { + CastKind Kind = CK_Dependent; + CXXCastPath BasePath; + if (!TypeDependent) { + CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath); + if (Ex.isInvalid()) + return ExprError(); + } + + return Owned(CXXStaticCastExpr::Create(Context, + DestType.getNonLValueExprType(Context), + VK, Kind, Ex.take(), &BasePath, + DestTInfo, OpLoc, Parens.getEnd())); + } + } + + return ExprError(); +} + +/// Try to diagnose a failed overloaded cast. Returns true if +/// diagnostics were emitted. +static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, + SourceRange range, Expr *src, + QualType destType) { + switch (CT) { + // These cast kinds don't consider user-defined conversions. + case CT_Const: + case CT_Reinterpret: + case CT_Dynamic: + return false; + + // These do. + case CT_Static: + case CT_CStyle: + case CT_Functional: + break; + } + + QualType srcType = src->getType(); + if (!destType->isRecordType() && !srcType->isRecordType()) + return false; + + InitializedEntity entity = InitializedEntity::InitializeTemporary(destType); + InitializationKind initKind + = InitializationKind::CreateCast(/*type range?*/ range, + (CT == CT_CStyle || CT == CT_Functional)); + InitializationSequence sequence(S, entity, initKind, &src, 1); + + assert(sequence.Failed() && "initialization succeeded on second try?"); + switch (sequence.getFailureKind()) { + default: return false; + + case InitializationSequence::FK_ConstructorOverloadFailed: + case InitializationSequence::FK_UserConversionOverloadFailed: + break; + } + + OverloadCandidateSet &candidates = sequence.getFailedCandidateSet(); + + unsigned msg = 0; + OverloadCandidateDisplayKind howManyCandidates = OCD_AllCandidates; + + switch (sequence.getFailedOverloadResult()) { + case OR_Success: llvm_unreachable("successful failed overload"); + return false; + case OR_No_Viable_Function: + if (candidates.empty()) + msg = diag::err_ovl_no_conversion_in_cast; + else + msg = diag::err_ovl_no_viable_conversion_in_cast; + howManyCandidates = OCD_AllCandidates; + break; + + case OR_Ambiguous: + msg = diag::err_ovl_ambiguous_conversion_in_cast; + howManyCandidates = OCD_ViableCandidates; + break; + + case OR_Deleted: + msg = diag::err_ovl_deleted_conversion_in_cast; + howManyCandidates = OCD_ViableCandidates; + break; + } + + S.Diag(range.getBegin(), msg) + << CT << srcType << destType + << range << src->getSourceRange(); + + candidates.NoteCandidates(S, howManyCandidates, &src, 1); + + return true; +} + +/// Diagnose a failed cast. +static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType, + SourceRange opRange, Expr *src, QualType destType) { + if (src->getType() == S.Context.BoundMemberTy) { + (void) S.CheckPlaceholderExpr(src); // will always fail + return; + } + + if (msg == diag::err_bad_cxx_cast_generic && + tryDiagnoseOverloadedCast(S, castType, opRange, src, destType)) + return; + + S.Diag(opRange.getBegin(), msg) << castType + << src->getType() << destType << opRange << src->getSourceRange(); +} + +/// UnwrapDissimilarPointerTypes - Like Sema::UnwrapSimilarPointerTypes, +/// this removes one level of indirection from both types, provided that they're +/// the same kind of pointer (plain or to-member). Unlike the Sema function, +/// this one doesn't care if the two pointers-to-member don't point into the +/// same class. This is because CastsAwayConstness doesn't care. +static bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { + const PointerType *T1PtrType = T1->getAs<PointerType>(), + *T2PtrType = T2->getAs<PointerType>(); + if (T1PtrType && T2PtrType) { + T1 = T1PtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + const ObjCObjectPointerType *T1ObjCPtrType = + T1->getAs<ObjCObjectPointerType>(), + *T2ObjCPtrType = + T2->getAs<ObjCObjectPointerType>(); + if (T1ObjCPtrType) { + if (T2ObjCPtrType) { + T1 = T1ObjCPtrType->getPointeeType(); + T2 = T2ObjCPtrType->getPointeeType(); + return true; + } + else if (T2PtrType) { + T1 = T1ObjCPtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + } + else if (T2ObjCPtrType) { + if (T1PtrType) { + T2 = T2ObjCPtrType->getPointeeType(); + T1 = T1PtrType->getPointeeType(); + return true; + } + } + + const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(), + *T2MPType = T2->getAs<MemberPointerType>(); + if (T1MPType && T2MPType) { + T1 = T1MPType->getPointeeType(); + T2 = T2MPType->getPointeeType(); + return true; + } + + const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(), + *T2BPType = T2->getAs<BlockPointerType>(); + if (T1BPType && T2BPType) { + T1 = T1BPType->getPointeeType(); + T2 = T2BPType->getPointeeType(); + return true; + } + + return false; +} + +/// CastsAwayConstness - Check if the pointer conversion from SrcType to +/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by +/// the cast checkers. Both arguments must denote pointer (possibly to member) +/// types. +static bool +CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { + // Casting away constness is defined in C++ 5.2.11p8 with reference to + // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since + // the rules are non-trivial. So first we construct Tcv *...cv* as described + // in C++ 5.2.11p8. + assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() || + SrcType->isBlockPointerType()) && + "Source type is not pointer or pointer to member."); + assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() || + DestType->isBlockPointerType()) && + "Destination type is not pointer or pointer to member."); + + QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), + UnwrappedDestType = Self.Context.getCanonicalType(DestType); + llvm::SmallVector<Qualifiers, 8> cv1, cv2; + + // Find the qualifiers. We only care about cvr-qualifiers for the + // purpose of this check, because other qualifiers (address spaces, + // Objective-C GC, etc.) are part of the type's identity. + while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { + Qualifiers SrcQuals; + Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals); + cv1.push_back(Qualifiers::fromCVRMask(SrcQuals.getCVRQualifiers())); + + Qualifiers DestQuals; + Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals); + cv2.push_back(Qualifiers::fromCVRMask(DestQuals.getCVRQualifiers())); + } + if (cv1.empty()) + return false; + + // Construct void pointers with those qualifiers (in reverse order of + // unwrapping, of course). + QualType SrcConstruct = Self.Context.VoidTy; + QualType DestConstruct = Self.Context.VoidTy; + ASTContext &Context = Self.Context; + for (llvm::SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(), + i2 = cv2.rbegin(); + i1 != cv1.rend(); ++i1, ++i2) { + SrcConstruct + = Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1)); + DestConstruct + = Context.getPointerType(Context.getQualifiedType(DestConstruct, *i2)); + } + + // Test if they're compatible. + return SrcConstruct != DestConstruct && + !Self.IsQualificationConversion(SrcConstruct, DestConstruct, false); +} + +/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid. +/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime- +/// checked downcasts in class hierarchies. +static void +CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + ExprValueKind &VK, const SourceRange &OpRange, + const SourceRange &DestRange, CastKind &Kind, + CXXCastPath &BasePath) { + QualType OrigDestType = DestType, OrigSrcType = SrcExpr.get()->getType(); + DestType = Self.Context.getCanonicalType(DestType); + + // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type, + // or "pointer to cv void". + + QualType DestPointee; + const PointerType *DestPointer = DestType->getAs<PointerType>(); + const ReferenceType *DestReference = 0; + if (DestPointer) { + DestPointee = DestPointer->getPointeeType(); + } else if ((DestReference = DestType->getAs<ReferenceType>())) { + DestPointee = DestReference->getPointeeType(); + VK = isa<LValueReferenceType>(DestReference) ? VK_LValue + : isa<RValueReferenceType>(DestReference) ? VK_XValue + : VK_RValue; + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr) + << OrigDestType << DestRange; + return; + } + + const RecordType *DestRecord = DestPointee->getAs<RecordType>(); + if (DestPointee->isVoidType()) { + assert(DestPointer && "Reference to void is not possible"); + } else if (DestRecord) { + if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee, + Self.PDiag(diag::err_bad_dynamic_cast_incomplete) + << DestRange)) + return; + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) + << DestPointee.getUnqualifiedType() << DestRange; + return; + } + + // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to + // complete class type, [...]. If T is an lvalue reference type, v shall be + // an lvalue of a complete class type, [...]. If T is an rvalue reference + // type, v shall be an expression having a complete class type, [...] + QualType SrcType = Self.Context.getCanonicalType(OrigSrcType); + QualType SrcPointee; + if (DestPointer) { + if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) { + SrcPointee = SrcPointer->getPointeeType(); + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr) + << OrigSrcType << SrcExpr.get()->getSourceRange(); + return; + } + } else if (DestReference->isLValueReferenceType()) { + if (!SrcExpr.get()->isLValue()) { + Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) + << CT_Dynamic << OrigSrcType << OrigDestType << OpRange; + } + SrcPointee = SrcType; + } else { + SrcPointee = SrcType; + } + + const RecordType *SrcRecord = SrcPointee->getAs<RecordType>(); + if (SrcRecord) { + if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, + Self.PDiag(diag::err_bad_dynamic_cast_incomplete) + << SrcExpr.get()->getSourceRange())) + return; + } else { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); + return; + } + + assert((DestPointer || DestReference) && + "Bad destination non-ptr/ref slipped through."); + assert((DestRecord || DestPointee->isVoidType()) && + "Bad destination pointee slipped through."); + assert(SrcRecord && "Bad source pointee slipped through."); + + // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness. + if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { + Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away) + << CT_Dynamic << OrigSrcType << OrigDestType << OpRange; + return; + } + + // C++ 5.2.7p3: If the type of v is the same as the required result type, + // [except for cv]. + if (DestRecord == SrcRecord) { + Kind = CK_NoOp; + return; + } + + // C++ 5.2.7p5 + // Upcasts are resolved statically. + if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) { + if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee, + OpRange.getBegin(), OpRange, + &BasePath)) + return; + + Kind = CK_DerivedToBase; + + // If we are casting to or through a virtual base class, we need a + // vtable. + if (Self.BasePathInvolvesVirtualBase(BasePath)) + Self.MarkVTableUsed(OpRange.getBegin(), + cast<CXXRecordDecl>(SrcRecord->getDecl())); + return; + } + + // C++ 5.2.7p6: Otherwise, v shall be [polymorphic]. + const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(); + assert(SrcDecl && "Definition missing"); + if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) { + Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) + << SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange(); + } + Self.MarkVTableUsed(OpRange.getBegin(), + cast<CXXRecordDecl>(SrcRecord->getDecl())); + + // Done. Everything else is run-time checks. + Kind = CK_Dynamic; +} + +/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid. +/// Refer to C++ 5.2.11 for details. const_cast is typically used in code +/// like this: +/// const char *str = "literal"; +/// legacy_function(const_cast\<char*\>(str)); +void +CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK, + const SourceRange &OpRange, const SourceRange &DestRange) { + VK = Expr::getValueKindForType(DestType); + if (VK == VK_RValue) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + } + + unsigned msg = diag::err_bad_cxx_cast_generic; + if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success + && msg != 0) + Self.Diag(OpRange.getBegin(), msg) << CT_Const + << SrcExpr.get()->getType() << DestType << OpRange; +} + +/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is +/// valid. +/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code +/// like this: +/// char *bytes = reinterpret_cast\<char*\>(int_ptr); +void +CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + ExprValueKind &VK, const SourceRange &OpRange, + const SourceRange &DestRange, CastKind &Kind) { + VK = Expr::getValueKindForType(DestType); + if (VK == VK_RValue) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + } + + unsigned msg = diag::err_bad_cxx_cast_generic; + if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, + msg, Kind) + != TC_Success && msg != 0) + { + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + //FIXME: &f<int>; is overloaded and resolvable + Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_overload) + << OverloadExpr::find(SrcExpr.get()).Expression->getName() + << DestType << OpRange; + Self.NoteAllOverloadCandidates(SrcExpr.get()); + + } else { + diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType); + } + } +} + + +/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid. +/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making +/// implicit conversions explicit and getting rid of data loss warnings. +void +CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + ExprValueKind &VK, const SourceRange &OpRange, + CastKind &Kind, CXXCastPath &BasePath) { + // This test is outside everything else because it's the only case where + // a non-lvalue-reference target type does not lead to decay. + // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". + if (DestType->isVoidType()) { + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + ExprResult SingleFunctionExpression = + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), + false, // Decay Function to ptr + true, // Complain + OpRange, DestType, diag::err_bad_static_cast_overload); + if (SingleFunctionExpression.isUsable()) + { + SrcExpr = SingleFunctionExpression; + Kind = CK_ToVoid; + } + } + else + Kind = CK_ToVoid; + return; + } + + VK = Expr::getValueKindForType(DestType); + if (VK == VK_RValue && !DestType->isRecordType()) { + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) // if conversion failed, don't report another error + return; + } + + unsigned msg = diag::err_bad_cxx_cast_generic; + if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, + Kind, BasePath) != TC_Success && msg != 0) { + if (SrcExpr.isInvalid()) + return; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + OverloadExpr* oe = OverloadExpr::find(SrcExpr.get()).Expression; + Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload) + << oe->getName() << DestType << OpRange + << oe->getQualifierLoc().getSourceRange(); + Self.NoteAllOverloadCandidates(SrcExpr.get()); + } else { + diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType); + } + } + else if (Kind == CK_BitCast) + Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); +} + +/// TryStaticCast - Check if a static cast can be performed, and do so if +/// possible. If @p CStyle, ignore access restrictions on hierarchy casting +/// and casting away constness. +static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, unsigned &msg, + CastKind &Kind, + CXXCastPath &BasePath) { + // The order the tests is not entirely arbitrary. There is one conversion + // that can be handled in two different ways. Given: + // struct A {}; + // struct B : public A { + // B(); B(const A&); + // }; + // const A &a = B(); + // the cast static_cast<const B&>(a) could be seen as either a static + // reference downcast, or an explicit invocation of the user-defined + // conversion using B's conversion constructor. + // DR 427 specifies that the downcast is to be applied here. + + // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". + // Done outside this function. + + TryCastResult tcr; + + // C++ 5.2.9p5, reference downcast. + // See the function for details. + // DR 427 specifies that this is to be applied before paragraph 2. + tcr = TryStaticReferenceDowncast(Self, SrcExpr.get(), DestType, CStyle, OpRange, + msg, Kind, BasePath); + if (tcr != TC_NotApplicable) + return tcr; + + // C++0x [expr.static.cast]p3: + // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2 + // T2" if "cv2 T2" is reference-compatible with "cv1 T1". + tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind, BasePath, + msg); + if (tcr != TC_NotApplicable) + return tcr; + + // C++ 5.2.9p2: An expression e can be explicitly converted to a type T + // [...] if the declaration "T t(e);" is well-formed, [...]. + tcr = TryStaticImplicitCast(Self, SrcExpr, DestType, CStyle, OpRange, msg, + Kind); + if (SrcExpr.isInvalid()) + return TC_Failed; + if (tcr != TC_NotApplicable) + return tcr; + + // C++ 5.2.9p6: May apply the reverse of any standard conversion, except + // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean + // conversions, subject to further restrictions. + // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal + // of qualification conversions impossible. + // In the CStyle case, the earlier attempt to const_cast should have taken + // care of reverse qualification conversions. + + QualType SrcType = Self.Context.getCanonicalType(SrcExpr.get()->getType()); + + // C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly + // converted to an integral type. [...] A value of a scoped enumeration type + // can also be explicitly converted to a floating-point type [...]. + if (const EnumType *Enum = SrcType->getAs<EnumType>()) { + if (Enum->getDecl()->isScoped()) { + if (DestType->isBooleanType()) { + Kind = CK_IntegralToBoolean; + return TC_Success; + } else if (DestType->isIntegralType(Self.Context)) { + Kind = CK_IntegralCast; + return TC_Success; + } else if (DestType->isRealFloatingType()) { + Kind = CK_IntegralToFloating; + return TC_Success; + } + } + } + + // Reverse integral promotion/conversion. All such conversions are themselves + // again integral promotions or conversions and are thus already handled by + // p2 (TryDirectInitialization above). + // (Note: any data loss warnings should be suppressed.) + // The exception is the reverse of enum->integer, i.e. integer->enum (and + // enum->enum). See also C++ 5.2.9p7. + // The same goes for reverse floating point promotion/conversion and + // floating-integral conversions. Again, only floating->enum is relevant. + if (DestType->isEnumeralType()) { + if (SrcType->isComplexType() || SrcType->isVectorType()) { + // Fall through - these cannot be converted. + } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) { + Kind = CK_IntegralCast; + return TC_Success; + } + } + + // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast. + // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance. + tcr = TryStaticPointerDowncast(Self, SrcType, DestType, CStyle, OpRange, msg, + Kind, BasePath); + if (tcr != TC_NotApplicable) + return tcr; + + // Reverse member pointer conversion. C++ 4.11 specifies member pointer + // conversion. C++ 5.2.9p9 has additional information. + // DR54's access restrictions apply here also. + tcr = TryStaticMemberPointerUpcast(Self, SrcExpr, SrcType, DestType, CStyle, + OpRange, msg, Kind, BasePath); + if (tcr != TC_NotApplicable) + return tcr; + + // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to + // void*. C++ 5.2.9p10 specifies additional restrictions, which really is + // just the usual constness stuff. + if (const PointerType *SrcPointer = SrcType->getAs<PointerType>()) { + QualType SrcPointee = SrcPointer->getPointeeType(); + if (SrcPointee->isVoidType()) { + if (const PointerType *DestPointer = DestType->getAs<PointerType>()) { + QualType DestPointee = DestPointer->getPointeeType(); + if (DestPointee->isIncompleteOrObjectType()) { + // This is definitely the intended conversion, but it might fail due + // to a const violation. + if (!CStyle && !DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + } + Kind = CK_BitCast; + return TC_Success; + } + } + else if (DestType->isObjCObjectPointerType()) { + // allow both c-style cast and static_cast of objective-c pointers as + // they are pervasive. + Kind = CK_AnyPointerToObjCPointerCast; + return TC_Success; + } + else if (CStyle && DestType->isBlockPointerType()) { + // allow c-style cast of void * to block pointers. + Kind = CK_AnyPointerToBlockPointerCast; + return TC_Success; + } + } + } + // Allow arbitray objective-c pointer conversion with static casts. + if (SrcType->isObjCObjectPointerType() && + DestType->isObjCObjectPointerType()) { + Kind = CK_BitCast; + return TC_Success; + } + + // We tried everything. Everything! Nothing works! :-( + return TC_NotApplicable; +} + +/// Tests whether a conversion according to N2844 is valid. +TryCastResult +TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, CastKind &Kind, CXXCastPath &BasePath, + unsigned &msg) { + // C++0x [expr.static.cast]p3: + // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to + // cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". + const RValueReferenceType *R = DestType->getAs<RValueReferenceType>(); + if (!R) + return TC_NotApplicable; + + if (!SrcExpr->isGLValue()) + return TC_NotApplicable; + + // Because we try the reference downcast before this function, from now on + // this is the only cast possibility, so we issue an error if we fail now. + // FIXME: Should allow casting away constness if CStyle. + bool DerivedToBase; + bool ObjCConversion; + QualType FromType = SrcExpr->getType(); + QualType ToType = R->getPointeeType(); + if (CStyle) { + FromType = FromType.getUnqualifiedType(); + ToType = ToType.getUnqualifiedType(); + } + + if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(), + ToType, FromType, + DerivedToBase, ObjCConversion) < + Sema::Ref_Compatible_With_Added_Qualification) { + msg = diag::err_bad_lvalue_to_rvalue_cast; + return TC_Failed; + } + + if (DerivedToBase) { + Kind = CK_DerivedToBase; + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + if (!Self.IsDerivedFrom(SrcExpr->getType(), R->getPointeeType(), Paths)) + return TC_NotApplicable; + + Self.BuildBasePathArray(Paths, BasePath); + } else + Kind = CK_NoOp; + + return TC_Success; +} + +/// Tests whether a conversion according to C++ 5.2.9p5 is valid. +TryCastResult +TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, const SourceRange &OpRange, + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath) { + // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be + // cast to type "reference to cv2 D", where D is a class derived from B, + // if a valid standard conversion from "pointer to D" to "pointer to B" + // exists, cv2 >= cv1, and B is not a virtual base class of D. + // In addition, DR54 clarifies that the base must be accessible in the + // current context. Although the wording of DR54 only applies to the pointer + // variant of this rule, the intent is clearly for it to apply to the this + // conversion as well. + + const ReferenceType *DestReference = DestType->getAs<ReferenceType>(); + if (!DestReference) { + return TC_NotApplicable; + } + bool RValueRef = DestReference->isRValueReferenceType(); + if (!RValueRef && !SrcExpr->isLValue()) { + // We know the left side is an lvalue reference, so we can suggest a reason. + msg = diag::err_bad_cxx_cast_rvalue; + return TC_NotApplicable; + } + + QualType DestPointee = DestReference->getPointeeType(); + + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcExpr->getType()), + Self.Context.getCanonicalType(DestPointee), CStyle, + OpRange, SrcExpr->getType(), DestType, msg, Kind, + BasePath); +} + +/// Tests whether a conversion according to C++ 5.2.9p8 is valid. +TryCastResult +TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, + bool CStyle, const SourceRange &OpRange, + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath) { + // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class + // type, can be converted to an rvalue of type "pointer to cv2 D", where D + // is a class derived from B, if a valid standard conversion from "pointer + // to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base + // class of D. + // In addition, DR54 clarifies that the base must be accessible in the + // current context. + + const PointerType *DestPointer = DestType->getAs<PointerType>(); + if (!DestPointer) { + return TC_NotApplicable; + } + + const PointerType *SrcPointer = SrcType->getAs<PointerType>(); + if (!SrcPointer) { + msg = diag::err_bad_static_cast_pointer_nonpointer; + return TC_NotApplicable; + } + + return TryStaticDowncast(Self, + Self.Context.getCanonicalType(SrcPointer->getPointeeType()), + Self.Context.getCanonicalType(DestPointer->getPointeeType()), + CStyle, OpRange, SrcType, DestType, msg, Kind, + BasePath); +} + +/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and +/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to +/// DestType is possible and allowed. +TryCastResult +TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, + bool CStyle, const SourceRange &OpRange, QualType OrigSrcType, + QualType OrigDestType, unsigned &msg, + CastKind &Kind, CXXCastPath &BasePath) { + // We can only work with complete types. But don't complain if it doesn't work + if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, Self.PDiag(0)) || + Self.RequireCompleteType(OpRange.getBegin(), DestType, Self.PDiag(0))) + return TC_NotApplicable; + + // Downcast can only happen in class hierarchies, so we need classes. + if (!DestType->getAs<RecordType>() || !SrcType->getAs<RecordType>()) { + return TC_NotApplicable; + } + + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) { + return TC_NotApplicable; + } + + // Target type does derive from source type. Now we're serious. If an error + // appears now, it's not ignored. + // This may not be entirely in line with the standard. Take for example: + // struct A {}; + // struct B : virtual A { + // B(A&); + // }; + // + // void f() + // { + // (void)static_cast<const B&>(*((A*)0)); + // } + // As far as the standard is concerned, p5 does not apply (A is virtual), so + // p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid. + // However, both GCC and Comeau reject this example, and accepting it would + // mean more complex code if we're to preserve the nice error message. + // FIXME: Being 100% compliant here would be nice to have. + + // Must preserve cv, as always, unless we're in C-style mode. + if (!CStyle && !DestType.isAtLeastAsQualifiedAs(SrcType)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + } + + if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) { + // This code is analoguous to that in CheckDerivedToBaseConversion, except + // that it builds the paths in reverse order. + // To sum up: record all paths to the base and build a nice string from + // them. Use it to spice up the error message. + if (!Paths.isRecordingPaths()) { + Paths.clear(); + Paths.setRecordingPaths(true); + Self.IsDerivedFrom(DestType, SrcType, Paths); + } + std::string PathDisplayStr; + std::set<unsigned> DisplayedPaths; + for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); + PI != PE; ++PI) { + if (DisplayedPaths.insert(PI->back().SubobjectNumber).second) { + // We haven't displayed a path to this particular base + // class subobject yet. + PathDisplayStr += "\n "; + for (CXXBasePath::const_reverse_iterator EI = PI->rbegin(), + EE = PI->rend(); + EI != EE; ++EI) + PathDisplayStr += EI->Base->getType().getAsString() + " -> "; + PathDisplayStr += QualType(DestType).getAsString(); + } + } + + Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast) + << QualType(SrcType).getUnqualifiedType() + << QualType(DestType).getUnqualifiedType() + << PathDisplayStr << OpRange; + msg = 0; + return TC_Failed; + } + + if (Paths.getDetectedVirtual() != 0) { + QualType VirtualBase(Paths.getDetectedVirtual(), 0); + Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual) + << OrigSrcType << OrigDestType << VirtualBase << OpRange; + msg = 0; + return TC_Failed; + } + + if (!CStyle) { + switch (Self.CheckBaseClassAccess(OpRange.getBegin(), + SrcType, DestType, + Paths.front(), + diag::err_downcast_from_inaccessible_base)) { + case Sema::AR_accessible: + case Sema::AR_delayed: // be optimistic + case Sema::AR_dependent: // be optimistic + break; + + case Sema::AR_inaccessible: + msg = 0; + return TC_Failed; + } + } + + Self.BuildBasePathArray(Paths, BasePath); + Kind = CK_BaseToDerived; + return TC_Success; +} + +/// TryStaticMemberPointerUpcast - Tests whether a conversion according to +/// C++ 5.2.9p9 is valid: +/// +/// An rvalue of type "pointer to member of D of type cv1 T" can be +/// converted to an rvalue of type "pointer to member of B of type cv2 T", +/// where B is a base class of D [...]. +/// +TryCastResult +TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, CastKind &Kind, + CXXCastPath &BasePath) { + const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(); + if (!DestMemPtr) + return TC_NotApplicable; + + bool WasOverloadedFunction = false; + DeclAccessPair FoundOverload; + if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + if (FunctionDecl *Fn + = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), DestType, false, + FoundOverload)) { + CXXMethodDecl *M = cast<CXXMethodDecl>(Fn); + SrcType = Self.Context.getMemberPointerType(Fn->getType(), + Self.Context.getTypeDeclType(M->getParent()).getTypePtr()); + WasOverloadedFunction = true; + } + } + + const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>(); + if (!SrcMemPtr) { + msg = diag::err_bad_static_cast_member_pointer_nonmp; + return TC_NotApplicable; + } + + // T == T, modulo cv + if (!Self.Context.hasSameUnqualifiedType(SrcMemPtr->getPointeeType(), + DestMemPtr->getPointeeType())) + return TC_NotApplicable; + + // B base of D + QualType SrcClass(SrcMemPtr->getClass(), 0); + QualType DestClass(DestMemPtr->getClass(), 0); + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) { + return TC_NotApplicable; + } + + // B is a base of D. But is it an allowed base? If not, it's a hard error. + if (Paths.isAmbiguous(Self.Context.getCanonicalType(DestClass))) { + Paths.clear(); + Paths.setRecordingPaths(true); + bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths); + assert(StillOkay); + (void)StillOkay; + std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths); + Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv) + << 1 << SrcClass << DestClass << PathDisplayStr << OpRange; + msg = 0; + return TC_Failed; + } + + if (const RecordType *VBase = Paths.getDetectedVirtual()) { + Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual) + << SrcClass << DestClass << QualType(VBase, 0) << OpRange; + msg = 0; + return TC_Failed; + } + + if (!CStyle) { + switch (Self.CheckBaseClassAccess(OpRange.getBegin(), + DestClass, SrcClass, + Paths.front(), + diag::err_upcast_to_inaccessible_base)) { + case Sema::AR_accessible: + case Sema::AR_delayed: + case Sema::AR_dependent: + // Optimistically assume that the delayed and dependent cases + // will work out. + break; + + case Sema::AR_inaccessible: + msg = 0; + return TC_Failed; + } + } + + if (WasOverloadedFunction) { + // Resolve the address of the overloaded function again, this time + // allowing complaints if something goes wrong. + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), + DestType, + true, + FoundOverload); + if (!Fn) { + msg = 0; + return TC_Failed; + } + + SrcExpr = Self.FixOverloadedFunctionReference(SrcExpr, FoundOverload, Fn); + if (!SrcExpr.isUsable()) { + msg = 0; + return TC_Failed; + } + } + + Self.BuildBasePathArray(Paths, BasePath); + Kind = CK_DerivedToBaseMemberPointer; + return TC_Success; +} + +/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2 +/// is valid: +/// +/// An expression e can be explicitly converted to a type T using a +/// @c static_cast if the declaration "T t(e);" is well-formed [...]. +TryCastResult +TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, + bool CStyle, const SourceRange &OpRange, unsigned &msg, + CastKind &Kind) { + if (DestType->isRecordType()) { + if (Self.RequireCompleteType(OpRange.getBegin(), DestType, + diag::err_bad_dynamic_cast_incomplete)) { + msg = 0; + return TC_Failed; + } + } + + InitializedEntity Entity = InitializedEntity::InitializeTemporary(DestType); + InitializationKind InitKind + = InitializationKind::CreateCast(/*FIXME:*/OpRange, CStyle); + Expr *SrcExprRaw = SrcExpr.get(); + InitializationSequence InitSeq(Self, Entity, InitKind, &SrcExprRaw, 1); + + // At this point of CheckStaticCast, if the destination is a reference, + // or the expression is an overload expression this has to work. + // There is no other way that works. + // On the other hand, if we're checking a C-style cast, we've still got + // the reinterpret_cast way. + + if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType())) + return TC_NotApplicable; + + ExprResult Result + = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExprRaw, 1)); + if (Result.isInvalid()) { + msg = 0; + return TC_Failed; + } + + if (InitSeq.isConstructorInitialization()) + Kind = CK_ConstructorConversion; + else + Kind = CK_NoOp; + + SrcExpr = move(Result); + return TC_Success; +} + +/// TryConstCast - See if a const_cast from source to destination is allowed, +/// and perform it if it is. +static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, + bool CStyle, unsigned &msg) { + DestType = Self.Context.getCanonicalType(DestType); + QualType SrcType = SrcExpr->getType(); + if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) { + if (DestTypeTmp->isLValueReferenceType() && !SrcExpr->isLValue()) { + // Cannot const_cast non-lvalue to lvalue reference type. But if this + // is C-style, static_cast might find a way, so we simply suggest a + // message and tell the parent to keep searching. + msg = diag::err_bad_cxx_cast_rvalue; + return TC_NotApplicable; + } + + // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2 + // [...] if a pointer to T1 can be [cast] to the type pointer to T2. + DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); + SrcType = Self.Context.getPointerType(SrcType); + } + + // C++ 5.2.11p5: For a const_cast involving pointers to data members [...] + // the rules for const_cast are the same as those used for pointers. + + if (!DestType->isPointerType() && + !DestType->isMemberPointerType() && + !DestType->isObjCObjectPointerType()) { + // Cannot cast to non-pointer, non-reference type. Note that, if DestType + // was a reference type, we converted it to a pointer above. + // The status of rvalue references isn't entirely clear, but it looks like + // conversion to them is simply invalid. + // C++ 5.2.11p3: For two pointer types [...] + if (!CStyle) + msg = diag::err_bad_const_cast_dest; + return TC_NotApplicable; + } + if (DestType->isFunctionPointerType() || + DestType->isMemberFunctionPointerType()) { + // Cannot cast direct function pointers. + // C++ 5.2.11p2: [...] where T is any object type or the void type [...] + // T is the ultimate pointee of source and target type. + if (!CStyle) + msg = diag::err_bad_const_cast_dest; + return TC_NotApplicable; + } + SrcType = Self.Context.getCanonicalType(SrcType); + + // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are + // completely equal. + // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers + // in multi-level pointers may change, but the level count must be the same, + // as must be the final pointee type. + while (SrcType != DestType && + Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) { + Qualifiers SrcQuals, DestQuals; + SrcType = Self.Context.getUnqualifiedArrayType(SrcType, SrcQuals); + DestType = Self.Context.getUnqualifiedArrayType(DestType, DestQuals); + + // const_cast is permitted to strip cvr-qualifiers, only. Make sure that + // the other qualifiers (e.g., address spaces) are identical. + SrcQuals.removeCVRQualifiers(); + DestQuals.removeCVRQualifiers(); + if (SrcQuals != DestQuals) + return TC_NotApplicable; + } + + // Since we're dealing in canonical types, the remainder must be the same. + if (SrcType != DestType) + return TC_NotApplicable; + + return TC_Success; +} + +// Checks for undefined behavior in reinterpret_cast. +// The cases that is checked for is: +// *reinterpret_cast<T*>(&a) +// reinterpret_cast<T&>(a) +// where accessing 'a' as type 'T' will result in undefined behavior. +void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, + bool IsDereference, + SourceRange Range) { + unsigned DiagID = IsDereference ? + diag::warn_pointer_indirection_from_incompatible_type : + diag::warn_undefined_reinterpret_cast; + + if (Diags.getDiagnosticLevel(DiagID, Range.getBegin()) == + Diagnostic::Ignored) { + return; + } + + QualType SrcTy, DestTy; + if (IsDereference) { + if (!SrcType->getAs<PointerType>() || !DestType->getAs<PointerType>()) { + return; + } + SrcTy = SrcType->getPointeeType(); + DestTy = DestType->getPointeeType(); + } else { + if (!DestType->getAs<ReferenceType>()) { + return; + } + SrcTy = SrcType; + DestTy = DestType->getPointeeType(); + } + + // Cast is compatible if the types are the same. + if (Context.hasSameUnqualifiedType(DestTy, SrcTy)) { + return; + } + // or one of the types is a char or void type + if (DestTy->isAnyCharacterType() || DestTy->isVoidType() || + SrcTy->isAnyCharacterType() || SrcTy->isVoidType()) { + return; + } + // or one of the types is a tag type. + if (SrcTy->getAs<TagType>() || DestTy->getAs<TagType>()) { + return; + } + + // FIXME: Scoped enums? + if ((SrcTy->isUnsignedIntegerType() && DestTy->isSignedIntegerType()) || + (SrcTy->isSignedIntegerType() && DestTy->isUnsignedIntegerType())) { + if (Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) { + return; + } + } + + Diag(Range.getBegin(), DiagID) << SrcType << DestType << Range; +} + +static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, + QualType DestType, bool CStyle, + const SourceRange &OpRange, + unsigned &msg, + CastKind &Kind) { + bool IsLValueCast = false; + + DestType = Self.Context.getCanonicalType(DestType); + QualType SrcType = SrcExpr.get()->getType(); + + // Is the source an overloaded name? (i.e. &foo) + // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ... + if (SrcType == Self.Context.OverloadTy) { + // ... unless foo<int> resolves to an lvalue unambiguously + ExprResult SingleFunctionExpr = + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), + Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr + ); + if (SingleFunctionExpr.isUsable()) { + SrcExpr = move(SingleFunctionExpr); + SrcType = SrcExpr.get()->getType(); + } + else + return TC_NotApplicable; + } + + if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) { + bool LValue = DestTypeTmp->isLValueReferenceType(); + if (LValue && !SrcExpr.get()->isLValue()) { + // Cannot cast non-lvalue to lvalue reference type. See the similar + // comment in const_cast. + msg = diag::err_bad_cxx_cast_rvalue; + return TC_NotApplicable; + } + + if (!CStyle) { + Self.CheckCompatibleReinterpretCast(SrcType, DestType, + /*isDereference=*/false, OpRange); + } + + // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the + // same effect as the conversion *reinterpret_cast<T*>(&x) with the + // built-in & and * operators. + + const char *inappropriate = 0; + switch (SrcExpr.get()->getObjectKind()) { + case OK_Ordinary: + break; + case OK_BitField: inappropriate = "bit-field"; break; + case OK_VectorComponent: inappropriate = "vector element"; break; + case OK_ObjCProperty: inappropriate = "property expression"; break; + } + if (inappropriate) { + Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_reference) + << inappropriate << DestType + << OpRange << SrcExpr.get()->getSourceRange(); + msg = 0; SrcExpr = ExprError(); + return TC_NotApplicable; + } + + // This code does this transformation for the checked types. + DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); + SrcType = Self.Context.getPointerType(SrcType); + + IsLValueCast = true; + } + + // Canonicalize source for comparison. + SrcType = Self.Context.getCanonicalType(SrcType); + + const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(), + *SrcMemPtr = SrcType->getAs<MemberPointerType>(); + if (DestMemPtr && SrcMemPtr) { + // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1" + // can be explicitly converted to an rvalue of type "pointer to member + // of Y of type T2" if T1 and T2 are both function types or both object + // types. + if (DestMemPtr->getPointeeType()->isFunctionType() != + SrcMemPtr->getPointeeType()->isFunctionType()) + return TC_NotApplicable; + + // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away + // constness. + // A reinterpret_cast followed by a const_cast can, though, so in C-style, + // we accept it. + if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + } + + // Don't allow casting between member pointers of different sizes. + if (Self.Context.getTypeSize(DestMemPtr) != + Self.Context.getTypeSize(SrcMemPtr)) { + msg = diag::err_bad_cxx_cast_member_pointer_size; + return TC_Failed; + } + + // A valid member pointer cast. + Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast; + return TC_Success; + } + + // See below for the enumeral issue. + if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) { + // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral + // type large enough to hold it. A value of std::nullptr_t can be + // converted to an integral type; the conversion has the same meaning + // and validity as a conversion of (void*)0 to the integral type. + if (Self.Context.getTypeSize(SrcType) > + Self.Context.getTypeSize(DestType)) { + msg = diag::err_bad_reinterpret_cast_small_int; + return TC_Failed; + } + Kind = CK_PointerToIntegral; + return TC_Success; + } + + bool destIsVector = DestType->isVectorType(); + bool srcIsVector = SrcType->isVectorType(); + if (srcIsVector || destIsVector) { + // FIXME: Should this also apply to floating point types? + bool srcIsScalar = SrcType->isIntegralType(Self.Context); + bool destIsScalar = DestType->isIntegralType(Self.Context); + + // Check if this is a cast between a vector and something else. + if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) && + !(srcIsVector && destIsVector)) + return TC_NotApplicable; + + // If both types have the same size, we can successfully cast. + if (Self.Context.getTypeSize(SrcType) + == Self.Context.getTypeSize(DestType)) { + Kind = CK_BitCast; + return TC_Success; + } + + if (destIsScalar) + msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size; + else if (srcIsScalar) + msg = diag::err_bad_cxx_cast_scalar_to_vector_different_size; + else + msg = diag::err_bad_cxx_cast_vector_to_vector_different_size; + + return TC_Failed; + } + + bool destIsPtr = DestType->isAnyPointerType() || + DestType->isBlockPointerType(); + bool srcIsPtr = SrcType->isAnyPointerType() || + SrcType->isBlockPointerType(); + if (!destIsPtr && !srcIsPtr) { + // Except for std::nullptr_t->integer and lvalue->reference, which are + // handled above, at least one of the two arguments must be a pointer. + return TC_NotApplicable; + } + + if (SrcType == DestType) { + // C++ 5.2.10p2 has a note that mentions that, subject to all other + // restrictions, a cast to the same type is allowed. The intent is not + // entirely clear here, since all other paragraphs explicitly forbid casts + // to the same type. However, the behavior of compilers is pretty consistent + // on this point: allow same-type conversion if the involved types are + // pointers, disallow otherwise. + Kind = CK_NoOp; + return TC_Success; + } + + if (DestType->isIntegralType(Self.Context)) { + assert(srcIsPtr && "One type must be a pointer"); + // C++ 5.2.10p4: A pointer can be explicitly converted to any integral + // type large enough to hold it; except in Microsoft mode, where the + // integral type size doesn't matter. + if ((Self.Context.getTypeSize(SrcType) > + Self.Context.getTypeSize(DestType)) && + !Self.getLangOptions().Microsoft) { + msg = diag::err_bad_reinterpret_cast_small_int; + return TC_Failed; + } + Kind = CK_PointerToIntegral; + return TC_Success; + } + + if (SrcType->isIntegralOrEnumerationType()) { + assert(destIsPtr && "One type must be a pointer"); + // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly + // converted to a pointer. + // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not + // necessarily converted to a null pointer value.] + Kind = CK_IntegralToPointer; + return TC_Success; + } + + if (!destIsPtr || !srcIsPtr) { + // With the valid non-pointer conversions out of the way, we can be even + // more stringent. + return TC_NotApplicable; + } + + // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. + // The C-style cast operator can. + if (!CStyle && CastsAwayConstness(Self, SrcType, DestType)) { + msg = diag::err_bad_cxx_cast_qualifiers_away; + return TC_Failed; + } + + // Cannot convert between block pointers and Objective-C object pointers. + if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) || + (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType())) + return TC_NotApplicable; + + // Any pointer can be cast to an Objective-C pointer type with a C-style + // cast. + if (CStyle && DestType->isObjCObjectPointerType()) { + Kind = CK_AnyPointerToObjCPointerCast; + return TC_Success; + } + + // Not casting away constness, so the only remaining check is for compatible + // pointer categories. + Kind = IsLValueCast? CK_LValueBitCast : CK_BitCast; + + if (SrcType->isFunctionPointerType()) { + if (DestType->isFunctionPointerType()) { + // C++ 5.2.10p6: A pointer to a function can be explicitly converted to + // a pointer to a function of a different type. + return TC_Success; + } + + // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to + // an object type or vice versa is conditionally-supported. + // Compilers support it in C++03 too, though, because it's necessary for + // casting the return value of dlsym() and GetProcAddress(). + // FIXME: Conditionally-supported behavior should be configurable in the + // TargetInfo or similar. + if (!Self.getLangOptions().CPlusPlus0x) + Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange; + return TC_Success; + } + + if (DestType->isFunctionPointerType()) { + // See above. + if (!Self.getLangOptions().CPlusPlus0x) + Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange; + return TC_Success; + } + + // C++ 5.2.10p7: A pointer to an object can be explicitly converted to + // a pointer to an object of different type. + // Void pointers are not specified, but supported by every compiler out there. + // So we finish by allowing everything that remains - it's got to be two + // object pointers. + return TC_Success; +} + +ExprResult +Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, + Expr *CastExpr, CastKind &Kind, + CXXCastPath &BasePath, + bool FunctionalStyle) { + // This test is outside everything else because it's the only case where + // a non-lvalue-reference target type does not lead to decay. + // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". + if (CastTy->isVoidType()) { + Kind = CK_ToVoid; + + ExprResult CastExprRes = IgnoredValueConversions(CastExpr); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); + + if (CastExpr->getType() == Context.BoundMemberTy) + return CheckPlaceholderExpr(CastExpr); // will always fail + + if (CastExpr->getType() == Context.OverloadTy) { + ExprResult SingleFunctionExpr = + ResolveAndFixSingleFunctionTemplateSpecialization( + CastExpr, /* Decay Function to ptr */ false, + /* Complain */ true, R, CastTy, + diag::err_bad_cstyle_cast_overload); + if (SingleFunctionExpr.isInvalid()) + return ExprError(); + CastExpr = SingleFunctionExpr.take(); + } + + assert(!CastExpr->getType()->isPlaceholderType()); + + return Owned(CastExpr); + } + + // Make sure we determine the value kind before we bail out for + // dependent types. + VK = Expr::getValueKindForType(CastTy); + + // If the type is dependent, we won't do any other semantic analysis now. + if (CastTy->isDependentType() || CastExpr->isTypeDependent()) { + Kind = CK_Dependent; + return Owned(CastExpr); + } + + if (VK == VK_RValue && !CastTy->isRecordType()) { + ExprResult CastExprRes = DefaultFunctionArrayLvalueConversion(CastExpr); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); + } + + // AltiVec vector initialization with a single literal. + if (const VectorType *vecTy = CastTy->getAs<VectorType>()) + if (vecTy->getVectorKind() == VectorType::AltiVecVector + && (CastExpr->getType()->isIntegerType() + || CastExpr->getType()->isFloatingType())) { + Kind = CK_VectorSplat; + return Owned(CastExpr); + } + + // C++ [expr.cast]p5: The conversions performed by + // - a const_cast, + // - a static_cast, + // - a static_cast followed by a const_cast, + // - a reinterpret_cast, or + // - a reinterpret_cast followed by a const_cast, + // can be performed using the cast notation of explicit type conversion. + // [...] If a conversion can be interpreted in more than one of the ways + // listed above, the interpretation that appears first in the list is used, + // even if a cast resulting from that interpretation is ill-formed. + // In plain language, this means trying a const_cast ... + unsigned msg = diag::err_bad_cxx_cast_generic; + TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true, + msg); + if (tcr == TC_Success) + Kind = CK_NoOp; + + if (tcr == TC_NotApplicable) { + // ... or if that is not possible, a static_cast, ignoring const, ... + ExprResult CastExprRes = Owned(CastExpr); + tcr = TryStaticCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, msg, + Kind, BasePath); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); + if (tcr == TC_NotApplicable) { + // ... and finally a reinterpret_cast, ignoring const. + CastExprRes = Owned(CastExpr); + tcr = TryReinterpretCast(*this, CastExprRes, CastTy, /*CStyle*/true, R, + msg, Kind); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = CastExprRes.take(); + } + } + + if (tcr != TC_Success && msg != 0) { + if (CastExpr->getType() == Context.OverloadTy) { + DeclAccessPair Found; + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr, + CastTy, + /* Complain */ true, + Found); + + assert(!Fn && "cast failed but able to resolve overload expression!!"); + (void)Fn; + + } else { + diagnoseBadCast(*this, msg, (FunctionalStyle ? CT_Functional : CT_CStyle), + R, CastExpr, CastTy); + } + } + else if (Kind == CK_BitCast) + CheckCastAlign(CastExpr, CastTy, R); + + if (tcr != TC_Success) + return ExprError(); + + return Owned(CastExpr); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp new file mode 100644 index 0000000..61d9e93 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -0,0 +1,859 @@ +//===--- SemaCXXScopeSpec.cpp - Semantic Analysis for C++ scope specifiers-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements C++ semantic analysis for scope specifiers. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Sema/DeclSpec.h" +#include "TypeLocBuilder.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/raw_ostream.h" +using namespace clang; + +/// \brief Find the current instantiation that associated with the given type. +static CXXRecordDecl *getCurrentInstantiationOf(QualType T, + DeclContext *CurContext) { + if (T.isNull()) + return 0; + + const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); + if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); + if (!T->isDependentType()) + return Record; + + // This may be a member of a class template or class template partial + // specialization. If it's part of the current semantic context, then it's + // an injected-class-name; + for (; !CurContext->isFileContext(); CurContext = CurContext->getParent()) + if (CurContext->Equals(Record)) + return Record; + + return 0; + } else if (isa<InjectedClassNameType>(Ty)) + return cast<InjectedClassNameType>(Ty)->getDecl(); + else + return 0; +} + +/// \brief Compute the DeclContext that is associated with the given type. +/// +/// \param T the type for which we are attempting to find a DeclContext. +/// +/// \returns the declaration context represented by the type T, +/// or NULL if the declaration context cannot be computed (e.g., because it is +/// dependent and not the current instantiation). +DeclContext *Sema::computeDeclContext(QualType T) { + if (!T->isDependentType()) + if (const TagType *Tag = T->getAs<TagType>()) + return Tag->getDecl(); + + return ::getCurrentInstantiationOf(T, CurContext); +} + +/// \brief Compute the DeclContext that is associated with the given +/// scope specifier. +/// +/// \param SS the C++ scope specifier as it appears in the source +/// +/// \param EnteringContext when true, we will be entering the context of +/// this scope specifier, so we can retrieve the declaration context of a +/// class template or class template partial specialization even if it is +/// not the current instantiation. +/// +/// \returns the declaration context represented by the scope specifier @p SS, +/// or NULL if the declaration context cannot be computed (e.g., because it is +/// dependent and not the current instantiation). +DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, + bool EnteringContext) { + if (!SS.isSet() || SS.isInvalid()) + return 0; + + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + if (NNS->isDependent()) { + // If this nested-name-specifier refers to the current + // instantiation, return its DeclContext. + if (CXXRecordDecl *Record = getCurrentInstantiationOf(NNS)) + return Record; + + if (EnteringContext) { + const Type *NNSType = NNS->getAsType(); + if (!NNSType) { + return 0; + } + + // Look through type alias templates, per C++0x [temp.dep.type]p1. + NNSType = Context.getCanonicalType(NNSType); + if (const TemplateSpecializationType *SpecType + = NNSType->getAs<TemplateSpecializationType>()) { + // We are entering the context of the nested name specifier, so try to + // match the nested name specifier to either a primary class template + // or a class template partial specialization. + if (ClassTemplateDecl *ClassTemplate + = dyn_cast_or_null<ClassTemplateDecl>( + SpecType->getTemplateName().getAsTemplateDecl())) { + QualType ContextType + = Context.getCanonicalType(QualType(SpecType, 0)); + + // If the type of the nested name specifier is the same as the + // injected class name of the named class template, we're entering + // into that class template definition. + QualType Injected + = ClassTemplate->getInjectedClassNameSpecialization(); + if (Context.hasSameType(Injected, ContextType)) + return ClassTemplate->getTemplatedDecl(); + + // If the type of the nested name specifier is the same as the + // type of one of the class template's class template partial + // specializations, we're entering into the definition of that + // class template partial specialization. + if (ClassTemplatePartialSpecializationDecl *PartialSpec + = ClassTemplate->findPartialSpecialization(ContextType)) + return PartialSpec; + } + } else if (const RecordType *RecordT = NNSType->getAs<RecordType>()) { + // The nested name specifier refers to a member of a class template. + return RecordT->getDecl(); + } + } + + return 0; + } + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + assert(false && "Dependent nested-name-specifier has no DeclContext"); + break; + + case NestedNameSpecifier::Namespace: + return NNS->getAsNamespace(); + + case NestedNameSpecifier::NamespaceAlias: + return NNS->getAsNamespaceAlias()->getNamespace(); + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + const TagType *Tag = NNS->getAsType()->getAs<TagType>(); + assert(Tag && "Non-tag type in nested-name-specifier"); + return Tag->getDecl(); + } break; + + case NestedNameSpecifier::Global: + return Context.getTranslationUnitDecl(); + } + + // Required to silence a GCC warning. + return 0; +} + +bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { + if (!SS.isSet() || SS.isInvalid()) + return false; + + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + return NNS->isDependent(); +} + +// \brief Determine whether this C++ scope specifier refers to an +// unknown specialization, i.e., a dependent type that is not the +// current instantiation. +bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { + if (!isDependentScopeSpecifier(SS)) + return false; + + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + return getCurrentInstantiationOf(NNS) == 0; +} + +/// \brief If the given nested name specifier refers to the current +/// instantiation, return the declaration that corresponds to that +/// current instantiation (C++0x [temp.dep.type]p1). +/// +/// \param NNS a dependent nested name specifier. +CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { + assert(getLangOptions().CPlusPlus && "Only callable in C++"); + assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed"); + + if (!NNS->getAsType()) + return 0; + + QualType T = QualType(NNS->getAsType(), 0); + return ::getCurrentInstantiationOf(T, CurContext); +} + +/// \brief Require that the context specified by SS be complete. +/// +/// If SS refers to a type, this routine checks whether the type is +/// complete enough (or can be made complete enough) for name lookup +/// into the DeclContext. A type that is not yet completed can be +/// considered "complete enough" if it is a class/struct/union/enum +/// that is currently being defined. Or, if we have a type that names +/// a class template specialization that is not a complete type, we +/// will attempt to instantiate that class template. +bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS, + DeclContext *DC) { + assert(DC != 0 && "given null context"); + + if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { + // If this is a dependent type, then we consider it complete. + if (Tag->isDependentContext()) + return false; + + // If we're currently defining this type, then lookup into the + // type is okay: don't complain that it isn't complete yet. + const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>(); + if (TagT && TagT->isBeingDefined()) + return false; + + // The type must be complete. + if (RequireCompleteType(SS.getRange().getBegin(), + Context.getTypeDeclType(Tag), + PDiag(diag::err_incomplete_nested_name_spec) + << SS.getRange())) { + SS.SetInvalid(SS.getRange()); + return true; + } + } + + return false; +} + +bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, + CXXScopeSpec &SS) { + SS.MakeGlobal(Context, CCLoc); + return false; +} + +/// \brief Determines whether the given declaration is an valid acceptable +/// result for name lookup of a nested-name-specifier. +bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { + if (!SD) + return false; + + // Namespace and namespace aliases are fine. + if (isa<NamespaceDecl>(SD) || isa<NamespaceAliasDecl>(SD)) + return true; + + if (!isa<TypeDecl>(SD)) + return false; + + // Determine whether we have a class (or, in C++0x, an enum) or + // a typedef thereof. If so, build the nested-name-specifier. + QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); + if (T->isDependentType()) + return true; + else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { + if (TD->getUnderlyingType()->isRecordType() || + (Context.getLangOptions().CPlusPlus0x && + TD->getUnderlyingType()->isEnumeralType())) + return true; + } else if (isa<RecordDecl>(SD) || + (Context.getLangOptions().CPlusPlus0x && isa<EnumDecl>(SD))) + return true; + + return false; +} + +/// \brief If the given nested-name-specifier begins with a bare identifier +/// (e.g., Base::), perform name lookup for that identifier as a +/// nested-name-specifier within the given scope, and return the result of that +/// name lookup. +NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { + if (!S || !NNS) + return 0; + + while (NNS->getPrefix()) + NNS = NNS->getPrefix(); + + if (NNS->getKind() != NestedNameSpecifier::Identifier) + return 0; + + LookupResult Found(*this, NNS->getAsIdentifier(), SourceLocation(), + LookupNestedNameSpecifierName); + LookupName(Found, S); + assert(!Found.isAmbiguous() && "Cannot handle ambiguities here yet"); + + if (!Found.isSingleResult()) + return 0; + + NamedDecl *Result = Found.getFoundDecl(); + if (isAcceptableNestedNameSpecifier(Result)) + return Result; + + return 0; +} + +bool Sema::isNonTypeNestedNameSpecifier(Scope *S, CXXScopeSpec &SS, + SourceLocation IdLoc, + IdentifierInfo &II, + ParsedType ObjectTypePtr) { + QualType ObjectType = GetTypeFromParser(ObjectTypePtr); + LookupResult Found(*this, &II, IdLoc, LookupNestedNameSpecifierName); + + // Determine where to perform name lookup + DeclContext *LookupCtx = 0; + bool isDependent = false; + if (!ObjectType.isNull()) { + // This nested-name-specifier occurs in a member access expression, e.g., + // x->B::f, and we are looking into the type of the object. + assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + } else if (SS.isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so long into the context associated with the prior nested-name-specifier. + LookupCtx = computeDeclContext(SS, false); + isDependent = isDependentScopeSpecifier(SS); + Found.setContextRange(SS.getRange()); + } + + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + + // The declaration context must be complete. + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(SS, LookupCtx)) + return false; + + LookupQualifiedName(Found, LookupCtx); + } else if (isDependent) { + return false; + } else { + LookupName(Found, S); + } + Found.suppressDiagnostics(); + + if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) + return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); + + return false; +} + +/// \brief Build a new nested-name-specifier for "identifier::", as described +/// by ActOnCXXNestedNameSpecifier. +/// +/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in +/// that it contains an extra parameter \p ScopeLookupResult, which provides +/// the result of name lookup within the scope of the nested-name-specifier +/// that was computed at template definition time. +/// +/// If ErrorRecoveryLookup is true, then this call is used to improve error +/// recovery. This means that it should not emit diagnostics, it should +/// just return true on failure. It also means it should only return a valid +/// scope if it *knows* that the result is correct. It should not return in a +/// dependent context, for example. Nor will it extend \p SS with the scope +/// specifier. +bool Sema::BuildCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + QualType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS, + NamedDecl *ScopeLookupResult, + bool ErrorRecoveryLookup) { + LookupResult Found(*this, &Identifier, IdentifierLoc, + LookupNestedNameSpecifierName); + + // Determine where to perform name lookup + DeclContext *LookupCtx = 0; + bool isDependent = false; + if (!ObjectType.isNull()) { + // This nested-name-specifier occurs in a member access expression, e.g., + // x->B::f, and we are looking into the type of the object. + assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + } else if (SS.isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so look into the context associated with the prior nested-name-specifier. + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = isDependentScopeSpecifier(SS); + Found.setContextRange(SS.getRange()); + } + + + bool ObjectTypeSearchedInScope = false; + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + + // The declaration context must be complete. + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(SS, LookupCtx)) + return true; + + LookupQualifiedName(Found, LookupCtx); + + if (!ObjectType.isNull() && Found.empty()) { + // C++ [basic.lookup.classref]p4: + // If the id-expression in a class member access is a qualified-id of + // the form + // + // class-name-or-namespace-name::... + // + // the class-name-or-namespace-name following the . or -> operator is + // looked up both in the context of the entire postfix-expression and in + // the scope of the class of the object expression. If the name is found + // only in the scope of the class of the object expression, the name + // shall refer to a class-name. If the name is found only in the + // context of the entire postfix-expression, the name shall refer to a + // class-name or namespace-name. [...] + // + // Qualified name lookup into a class will not find a namespace-name, + // so we do not need to diagnose that case specifically. However, + // this qualified name lookup may find nothing. In that case, perform + // unqualified name lookup in the given scope (if available) or + // reconstruct the result from when name lookup was performed at template + // definition time. + if (S) + LookupName(Found, S); + else if (ScopeLookupResult) + Found.addDecl(ScopeLookupResult); + + ObjectTypeSearchedInScope = true; + } + } else if (!isDependent) { + // Perform unqualified name lookup in the current scope. + LookupName(Found, S); + } + + // If we performed lookup into a dependent context and did not find anything, + // that's fine: just build a dependent nested-name-specifier. + if (Found.empty() && isDependent && + !(LookupCtx && LookupCtx->isRecord() && + (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() || + !cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()))) { + // Don't speculate if we're just trying to improve error recovery. + if (ErrorRecoveryLookup) + return true; + + // We were not able to compute the declaration context for a dependent + // base object type or prior nested-name-specifier, so this + // nested-name-specifier refers to an unknown specialization. Just build + // a dependent nested-name-specifier. + SS.Extend(Context, &Identifier, IdentifierLoc, CCLoc); + return false; + } + + // FIXME: Deal with ambiguities cleanly. + + if (Found.empty() && !ErrorRecoveryLookup) { + // We haven't found anything, and we're not recovering from a + // different kind of error, so look for typos. + DeclarationName Name = Found.getLookupName(); + if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext, + CTC_NoKeywords) && + Found.isSingleResult() && + isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) { + if (LookupCtx) + Diag(Found.getNameLoc(), diag::err_no_member_suggest) + << Name << LookupCtx << Found.getLookupName() << SS.getRange() + << FixItHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + else + Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest) + << Name << Found.getLookupName() + << FixItHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + + if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) + Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); + } else { + Found.clear(); + Found.setLookupName(&Identifier); + } + } + + NamedDecl *SD = Found.getAsSingle<NamedDecl>(); + if (isAcceptableNestedNameSpecifier(SD)) { + if (!ObjectType.isNull() && !ObjectTypeSearchedInScope) { + // C++ [basic.lookup.classref]p4: + // [...] If the name is found in both contexts, the + // class-name-or-namespace-name shall refer to the same entity. + // + // We already found the name in the scope of the object. Now, look + // into the current scope (the scope of the postfix-expression) to + // see if we can find the same name there. As above, if there is no + // scope, reconstruct the result from the template instantiation itself. + NamedDecl *OuterDecl; + if (S) { + LookupResult FoundOuter(*this, &Identifier, IdentifierLoc, + LookupNestedNameSpecifierName); + LookupName(FoundOuter, S); + OuterDecl = FoundOuter.getAsSingle<NamedDecl>(); + } else + OuterDecl = ScopeLookupResult; + + if (isAcceptableNestedNameSpecifier(OuterDecl) && + OuterDecl->getCanonicalDecl() != SD->getCanonicalDecl() && + (!isa<TypeDecl>(OuterDecl) || !isa<TypeDecl>(SD) || + !Context.hasSameType( + Context.getTypeDeclType(cast<TypeDecl>(OuterDecl)), + Context.getTypeDeclType(cast<TypeDecl>(SD))))) { + if (ErrorRecoveryLookup) + return true; + + Diag(IdentifierLoc, + diag::err_nested_name_member_ref_lookup_ambiguous) + << &Identifier; + Diag(SD->getLocation(), diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(OuterDecl->getLocation(), diag::note_ambig_member_ref_scope); + + // Fall through so that we'll pick the name we found in the object + // type, since that's probably what the user wanted anyway. + } + } + + // If we're just performing this lookup for error-recovery purposes, + // don't extend the nested-name-specifier. Just return now. + if (ErrorRecoveryLookup) + return false; + + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) { + SS.Extend(Context, Namespace, IdentifierLoc, CCLoc); + return false; + } + + if (NamespaceAliasDecl *Alias = dyn_cast<NamespaceAliasDecl>(SD)) { + SS.Extend(Context, Alias, IdentifierLoc, CCLoc); + return false; + } + + QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); + TypeLocBuilder TLB; + if (isa<InjectedClassNameType>(T)) { + InjectedClassNameTypeLoc InjectedTL + = TLB.push<InjectedClassNameTypeLoc>(T); + InjectedTL.setNameLoc(IdentifierLoc); + } else if (isa<RecordType>(T)) { + RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T); + RecordTL.setNameLoc(IdentifierLoc); + } else if (isa<TypedefType>(T)) { + TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T); + TypedefTL.setNameLoc(IdentifierLoc); + } else if (isa<EnumType>(T)) { + EnumTypeLoc EnumTL = TLB.push<EnumTypeLoc>(T); + EnumTL.setNameLoc(IdentifierLoc); + } else if (isa<TemplateTypeParmType>(T)) { + TemplateTypeParmTypeLoc TemplateTypeTL + = TLB.push<TemplateTypeParmTypeLoc>(T); + TemplateTypeTL.setNameLoc(IdentifierLoc); + } else if (isa<UnresolvedUsingType>(T)) { + UnresolvedUsingTypeLoc UnresolvedTL + = TLB.push<UnresolvedUsingTypeLoc>(T); + UnresolvedTL.setNameLoc(IdentifierLoc); + } else if (isa<SubstTemplateTypeParmType>(T)) { + SubstTemplateTypeParmTypeLoc TL + = TLB.push<SubstTemplateTypeParmTypeLoc>(T); + TL.setNameLoc(IdentifierLoc); + } else if (isa<SubstTemplateTypeParmPackType>(T)) { + SubstTemplateTypeParmPackTypeLoc TL + = TLB.push<SubstTemplateTypeParmPackTypeLoc>(T); + TL.setNameLoc(IdentifierLoc); + } else { + llvm_unreachable("Unhandled TypeDecl node in nested-name-specifier"); + } + + SS.Extend(Context, SourceLocation(), TLB.getTypeLocInContext(Context, T), + CCLoc); + return false; + } + + // Otherwise, we have an error case. If we don't want diagnostics, just + // return an error now. + if (ErrorRecoveryLookup) + return true; + + // If we didn't find anything during our lookup, try again with + // ordinary name lookup, which can help us produce better error + // messages. + if (Found.empty()) { + Found.clear(LookupOrdinaryName); + LookupName(Found, S); + } + + unsigned DiagID; + if (!Found.empty()) + DiagID = diag::err_expected_class_or_namespace; + else if (SS.isSet()) { + Diag(IdentifierLoc, diag::err_no_member) + << &Identifier << LookupCtx << SS.getRange(); + return true; + } else + DiagID = diag::err_undeclared_var_use; + + if (SS.isSet()) + Diag(IdentifierLoc, DiagID) << &Identifier << SS.getRange(); + else + Diag(IdentifierLoc, DiagID) << &Identifier; + + return true; +} + +bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation CCLoc, + ParsedType ObjectType, + bool EnteringContext, + CXXScopeSpec &SS) { + if (SS.isInvalid()) + return true; + + return BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, CCLoc, + GetTypeFromParser(ObjectType), + EnteringContext, SS, + /*ScopeLookupResult=*/0, false); +} + +/// IsInvalidUnlessNestedName - This method is used for error recovery +/// purposes to determine whether the specified identifier is only valid as +/// a nested name specifier, for example a namespace name. It is +/// conservatively correct to always return false from this method. +/// +/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. +bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, + IdentifierInfo &Identifier, + SourceLocation IdentifierLoc, + SourceLocation ColonLoc, + ParsedType ObjectType, + bool EnteringContext) { + if (SS.isInvalid()) + return false; + + return !BuildCXXNestedNameSpecifier(S, Identifier, IdentifierLoc, ColonLoc, + GetTypeFromParser(ObjectType), + EnteringContext, SS, + /*ScopeLookupResult=*/0, true); +} + +bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, + SourceLocation TemplateLoc, + CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, + SourceLocation CCLoc, + bool EnteringContext) { + if (SS.isInvalid()) + return true; + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + if (DependentTemplateName *DTN = Template.get().getAsDependentTemplateName()){ + // Handle a dependent template specialization for which we cannot resolve + // the template name. + assert(DTN->getQualifier() + == static_cast<NestedNameSpecifier*>(SS.getScopeRep())); + QualType T = Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Create source-location information for this type. + TypeLocBuilder Builder; + DependentTemplateSpecializationTypeLoc SpecTL + = Builder.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setKeywordLoc(SourceLocation()); + SpecTL.setNameLoc(TemplateNameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); + return false; + } + + + if (Template.get().getAsOverloadedTemplate() || + isa<FunctionTemplateDecl>(Template.get().getAsTemplateDecl())) { + SourceRange R(TemplateNameLoc, RAngleLoc); + if (SS.getRange().isValid()) + R.setBegin(SS.getRange().getBegin()); + + Diag(CCLoc, diag::err_non_type_template_in_nested_name_specifier) + << Template.get() << R; + NoteAllFoundTemplates(Template.get()); + return true; + } + + // We were able to resolve the template name to an actual template. + // Build an appropriate nested-name-specifier. + QualType T = CheckTemplateIdType(Template.get(), TemplateNameLoc, + TemplateArgs); + if (T.isNull()) + return true; + + // Alias template specializations can produce types which are not valid + // nested name specifiers. + if (!T->isDependentType() && !T->getAs<TagType>()) { + Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T; + NoteAllFoundTemplates(Template.get()); + return true; + } + + // Provide source-location information for the template specialization + // type. + TypeLocBuilder Builder; + TemplateSpecializationTypeLoc SpecTL + = Builder.push<TemplateSpecializationTypeLoc>(T); + + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + + SS.Extend(Context, TemplateLoc, Builder.getTypeLocInContext(Context, T), + CCLoc); + return false; +} + +namespace { + /// \brief A structure that stores a nested-name-specifier annotation, + /// including both the nested-name-specifier + struct NestedNameSpecifierAnnotation { + NestedNameSpecifier *NNS; + }; +} + +void *Sema::SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS) { + if (SS.isEmpty() || SS.isInvalid()) + return 0; + + void *Mem = Context.Allocate((sizeof(NestedNameSpecifierAnnotation) + + SS.location_size()), + llvm::alignOf<NestedNameSpecifierAnnotation>()); + NestedNameSpecifierAnnotation *Annotation + = new (Mem) NestedNameSpecifierAnnotation; + Annotation->NNS = SS.getScopeRep(); + memcpy(Annotation + 1, SS.location_data(), SS.location_size()); + return Annotation; +} + +void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, + SourceRange AnnotationRange, + CXXScopeSpec &SS) { + if (!AnnotationPtr) { + SS.SetInvalid(AnnotationRange); + return; + } + + NestedNameSpecifierAnnotation *Annotation + = static_cast<NestedNameSpecifierAnnotation *>(AnnotationPtr); + SS.Adopt(NestedNameSpecifierLoc(Annotation->NNS, Annotation + 1)); +} + +bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); + + NestedNameSpecifier *Qualifier = + static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + + // There are only two places a well-formed program may qualify a + // declarator: first, when defining a namespace or class member + // out-of-line, and second, when naming an explicitly-qualified + // friend function. The latter case is governed by + // C++03 [basic.lookup.unqual]p10: + // In a friend declaration naming a member function, a name used + // in the function declarator and not part of a template-argument + // in a template-id is first looked up in the scope of the member + // function's class. If it is not found, or if the name is part of + // a template-argument in a template-id, the look up is as + // described for unqualified names in the definition of the class + // granting friendship. + // i.e. we don't push a scope unless it's a class member. + + switch (Qualifier->getKind()) { + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + // These are always namespace scopes. We never want to enter a + // namespace scope from anything but a file context. + return CurContext->getRedeclContext()->isFileContext(); + + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + // These are never namespace scopes. + return true; + } + + // Silence bogus warning. + return false; +} + +/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global +/// scope or nested-name-specifier) is parsed, part of a declarator-id. +/// After this method is called, according to [C++ 3.4.3p3], names should be +/// looked up in the declarator-id's scope, until the declarator is parsed and +/// ActOnCXXExitDeclaratorScope is called. +/// The 'SS' should be a non-empty valid CXXScopeSpec. +bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { + assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); + + if (SS.isInvalid()) return true; + + DeclContext *DC = computeDeclContext(SS, true); + if (!DC) return true; + + // Before we enter a declarator's context, we need to make sure that + // it is a complete declaration context. + if (!DC->isDependentContext() && RequireCompleteDeclContext(SS, DC)) + return true; + + EnterDeclaratorContext(S, DC); + + // Rebuild the nested name specifier for the new scope. + if (DC->isDependentContext()) + RebuildNestedNameSpecifierInCurrentInstantiation(SS); + + return false; +} + +/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously +/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same +/// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. +/// Used to indicate that names should revert to being looked up in the +/// defining scope. +void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); + if (SS.isInvalid()) + return; + assert(!SS.isInvalid() && computeDeclContext(SS, true) && + "exiting declarator scope we never really entered"); + ExitDeclaratorContext(S); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp new file mode 100644 index 0000000..7e22b33 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -0,0 +1,3393 @@ +//===--- SemaChecking.cpp - Extra Semantic Checking -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements extra semantic analysis beyond what is enforced +// by the C type system. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Analysis/Analyses/FormatString.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/raw_ostream.h" +#include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/ConvertUTF.h" +#include <limits> +using namespace clang; +using namespace sema; + +SourceLocation Sema::getLocationOfStringLiteralByte(const StringLiteral *SL, + unsigned ByteNo) const { + return SL->getLocationOfByte(ByteNo, PP.getSourceManager(), + PP.getLangOptions(), PP.getTargetInfo()); +} + + +/// CheckablePrintfAttr - does a function call have a "printf" attribute +/// and arguments that merit checking? +bool Sema::CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall) { + if (Format->getType() == "printf") return true; + if (Format->getType() == "printf0") { + // printf0 allows null "format" string; if so don't check format/args + unsigned format_idx = Format->getFormatIdx() - 1; + // Does the index refer to the implicit object argument? + if (isa<CXXMemberCallExpr>(TheCall)) { + if (format_idx == 0) + return false; + --format_idx; + } + if (format_idx < TheCall->getNumArgs()) { + Expr *Format = TheCall->getArg(format_idx)->IgnoreParenCasts(); + if (!Format->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) + return true; + } + } + return false; +} + +/// Checks that a call expression's argument count is the desired number. +/// This is useful when doing custom type-checking. Returns true on error. +static bool checkArgCount(Sema &S, CallExpr *call, unsigned desiredArgCount) { + unsigned argCount = call->getNumArgs(); + if (argCount == desiredArgCount) return false; + + if (argCount < desiredArgCount) + return S.Diag(call->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 /*function call*/ << desiredArgCount << argCount + << call->getSourceRange(); + + // Highlight all the excess arguments. + SourceRange range(call->getArg(desiredArgCount)->getLocStart(), + call->getArg(argCount - 1)->getLocEnd()); + + return S.Diag(range.getBegin(), diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << desiredArgCount << argCount + << call->getArg(1)->getSourceRange(); +} + +ExprResult +Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + ExprResult TheCallResult(Owned(TheCall)); + + // Find out if any arguments are required to be integer constant expressions. + unsigned ICEArguments = 0; + ASTContext::GetBuiltinTypeError Error; + Context.GetBuiltinType(BuiltinID, Error, &ICEArguments); + if (Error != ASTContext::GE_None) + ICEArguments = 0; // Don't diagnose previously diagnosed errors. + + // If any arguments are required to be ICE's, check and diagnose. + for (unsigned ArgNo = 0; ICEArguments != 0; ++ArgNo) { + // Skip arguments not required to be ICE's. + if ((ICEArguments & (1 << ArgNo)) == 0) continue; + + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) + return true; + ICEArguments &= ~(1 << ArgNo); + } + + switch (BuiltinID) { + case Builtin::BI__builtin___CFStringMakeConstantString: + assert(TheCall->getNumArgs() == 1 && + "Wrong # arguments to builtin CFStringMakeConstantString"); + if (CheckObjCString(TheCall->getArg(0))) + return ExprError(); + break; + case Builtin::BI__builtin_stdarg_start: + case Builtin::BI__builtin_va_start: + if (SemaBuiltinVAStart(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_isgreater: + case Builtin::BI__builtin_isgreaterequal: + case Builtin::BI__builtin_isless: + case Builtin::BI__builtin_islessequal: + case Builtin::BI__builtin_islessgreater: + case Builtin::BI__builtin_isunordered: + if (SemaBuiltinUnorderedCompare(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_fpclassify: + if (SemaBuiltinFPClassification(TheCall, 6)) + return ExprError(); + break; + case Builtin::BI__builtin_isfinite: + case Builtin::BI__builtin_isinf: + case Builtin::BI__builtin_isinf_sign: + case Builtin::BI__builtin_isnan: + case Builtin::BI__builtin_isnormal: + if (SemaBuiltinFPClassification(TheCall, 1)) + return ExprError(); + break; + case Builtin::BI__builtin_shufflevector: + return SemaBuiltinShuffleVector(TheCall); + // TheCall will be freed by the smart pointer here, but that's fine, since + // SemaBuiltinShuffleVector guts it, but then doesn't release it. + case Builtin::BI__builtin_prefetch: + if (SemaBuiltinPrefetch(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_object_size: + if (SemaBuiltinObjectSize(TheCall)) + return ExprError(); + break; + case Builtin::BI__builtin_longjmp: + if (SemaBuiltinLongjmp(TheCall)) + return ExprError(); + break; + + case Builtin::BI__builtin_classify_type: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__builtin_constant_p: + if (checkArgCount(*this, TheCall, 1)) return true; + TheCall->setType(Context.IntTy); + break; + case Builtin::BI__sync_fetch_and_add: + case Builtin::BI__sync_fetch_and_sub: + case Builtin::BI__sync_fetch_and_or: + case Builtin::BI__sync_fetch_and_and: + case Builtin::BI__sync_fetch_and_xor: + case Builtin::BI__sync_add_and_fetch: + case Builtin::BI__sync_sub_and_fetch: + case Builtin::BI__sync_and_and_fetch: + case Builtin::BI__sync_or_and_fetch: + case Builtin::BI__sync_xor_and_fetch: + case Builtin::BI__sync_val_compare_and_swap: + case Builtin::BI__sync_bool_compare_and_swap: + case Builtin::BI__sync_lock_test_and_set: + case Builtin::BI__sync_lock_release: + case Builtin::BI__sync_swap: + return SemaBuiltinAtomicOverloaded(move(TheCallResult)); + } + + // Since the target specific builtins for each arch overlap, only check those + // of the arch we are compiling for. + if (BuiltinID >= Builtin::FirstTSBuiltin) { + switch (Context.Target.getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; + default: + break; + } + } + + return move(TheCallResult); +} + +// Get the valid immediate range for the specified NEON type code. +static unsigned RFT(unsigned t, bool shift = false) { + bool quad = t & 0x10; + + switch (t & 0x7) { + case 0: // i8 + return shift ? 7 : (8 << (int)quad) - 1; + case 1: // i16 + return shift ? 15 : (4 << (int)quad) - 1; + case 2: // i32 + return shift ? 31 : (2 << (int)quad) - 1; + case 3: // i64 + return shift ? 63 : (1 << (int)quad) - 1; + case 4: // f32 + assert(!shift && "cannot shift float types!"); + return (2 << (int)quad) - 1; + case 5: // poly8 + return shift ? 7 : (8 << (int)quad) - 1; + case 6: // poly16 + return shift ? 15 : (4 << (int)quad) - 1; + case 7: // float16 + assert(!shift && "cannot shift float types!"); + return (4 << (int)quad) - 1; + } + return 0; +} + +bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + llvm::APSInt Result; + + unsigned mask = 0; + unsigned TV = 0; + switch (BuiltinID) { +#define GET_NEON_OVERLOAD_CHECK +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_OVERLOAD_CHECK + } + + // For NEON intrinsics which are overloaded on vector element type, validate + // the immediate which specifies which variant to emit. + if (mask) { + unsigned ArgNo = TheCall->getNumArgs()-1; + if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) + return true; + + TV = Result.getLimitedValue(32); + if ((TV > 31) || (mask & (1 << TV)) == 0) + return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) + << TheCall->getArg(ArgNo)->getSourceRange(); + } + + // For NEON intrinsics which take an immediate value as part of the + // instruction, range check them here. + unsigned i = 0, l = 0, u = 0; + switch (BuiltinID) { + default: return false; + case ARM::BI__builtin_arm_ssat: i = 1; l = 1; u = 31; break; + case ARM::BI__builtin_arm_usat: i = 1; u = 31; break; + case ARM::BI__builtin_arm_vcvtr_f: + case ARM::BI__builtin_arm_vcvtr_d: i = 1; u = 1; break; +#define GET_NEON_IMMEDIATE_CHECK +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_IMMEDIATE_CHECK + }; + + // Check that the immediate argument is actually a constant. + if (SemaBuiltinConstantArg(TheCall, i, Result)) + return true; + + // Range check against the upper/lower values for this isntruction. + unsigned Val = Result.getZExtValue(); + if (Val < l || Val > (u + l)) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << l << u+l << TheCall->getArg(i)->getSourceRange(); + + // FIXME: VFP Intrinsics should error if VFP not present. + return false; +} + +/// CheckFunctionCall - Check a direct function call for various correctness +/// and safety properties not strictly enforced by the C type system. +bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { + // Get the IdentifierInfo* for the called function. + IdentifierInfo *FnInfo = FDecl->getIdentifier(); + + // None of the checks below are needed for functions that don't have + // simple names (e.g., C++ conversion functions). + if (!FnInfo) + return false; + + // FIXME: This mechanism should be abstracted to be less fragile and + // more efficient. For example, just map function ids to custom + // handlers. + + // Printf and scanf checking. + for (specific_attr_iterator<FormatAttr> + i = FDecl->specific_attr_begin<FormatAttr>(), + e = FDecl->specific_attr_end<FormatAttr>(); i != e ; ++i) { + + const FormatAttr *Format = *i; + const bool b = Format->getType() == "scanf"; + if (b || CheckablePrintfAttr(Format, TheCall)) { + bool HasVAListArg = Format->getFirstArg() == 0; + CheckPrintfScanfArguments(TheCall, HasVAListArg, + Format->getFormatIdx() - 1, + HasVAListArg ? 0 : Format->getFirstArg() - 1, + !b); + } + } + + for (specific_attr_iterator<NonNullAttr> + i = FDecl->specific_attr_begin<NonNullAttr>(), + e = FDecl->specific_attr_end<NonNullAttr>(); i != e; ++i) { + CheckNonNullArguments(*i, TheCall->getArgs(), + TheCall->getCallee()->getLocStart()); + } + + // Memset/memcpy/memmove handling + if (FDecl->getLinkage() == ExternalLinkage && + (!getLangOptions().CPlusPlus || FDecl->isExternC())) { + if (FnInfo->isStr("memset") || FnInfo->isStr("memcpy") || + FnInfo->isStr("memmove")) + CheckMemsetcpymoveArguments(TheCall, FnInfo); + } + + return false; +} + +bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { + // Printf checking. + const FormatAttr *Format = NDecl->getAttr<FormatAttr>(); + if (!Format) + return false; + + const VarDecl *V = dyn_cast<VarDecl>(NDecl); + if (!V) + return false; + + QualType Ty = V->getType(); + if (!Ty->isBlockPointerType()) + return false; + + const bool b = Format->getType() == "scanf"; + if (!b && !CheckablePrintfAttr(Format, TheCall)) + return false; + + bool HasVAListArg = Format->getFirstArg() == 0; + CheckPrintfScanfArguments(TheCall, HasVAListArg, Format->getFormatIdx() - 1, + HasVAListArg ? 0 : Format->getFirstArg() - 1, !b); + + return false; +} + +/// SemaBuiltinAtomicOverloaded - We have a call to a function like +/// __sync_fetch_and_add, which is an overloaded function based on the pointer +/// type of its first argument. The main ActOnCallExpr routines have already +/// promoted the types of arguments because all of these calls are prototyped as +/// void(...). +/// +/// This function goes through and does final semantic checking for these +/// builtins, +ExprResult +Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { + CallExpr *TheCall = (CallExpr *)TheCallResult.get(); + DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); + + // Ensure that we have at least one argument to do type inference from. + if (TheCall->getNumArgs() < 1) { + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1 << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } + + // Inspect the first argument of the atomic builtin. This should always be + // a pointer type, whose element is an integral scalar or pointer type. + // Because it is a pointer type, we don't have to worry about any implicit + // casts here. + // FIXME: We don't allow floating point scalars as input. + Expr *FirstArg = TheCall->getArg(0); + if (!FirstArg->getType()->isPointerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } + + QualType ValType = + FirstArg->getType()->getAs<PointerType>()->getPointeeType(); + if (!ValType->isIntegerType() && !ValType->isAnyPointerType() && + !ValType->isBlockPointerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } + + // The majority of builtins return a value, but a few have special return + // types, so allow them to override appropriately below. + QualType ResultType = ValType; + + // We need to figure out which concrete builtin this maps onto. For example, + // __sync_fetch_and_add with a 2 byte object turns into + // __sync_fetch_and_add_2. +#define BUILTIN_ROW(x) \ + { Builtin::BI##x##_1, Builtin::BI##x##_2, Builtin::BI##x##_4, \ + Builtin::BI##x##_8, Builtin::BI##x##_16 } + + static const unsigned BuiltinIndices[][5] = { + BUILTIN_ROW(__sync_fetch_and_add), + BUILTIN_ROW(__sync_fetch_and_sub), + BUILTIN_ROW(__sync_fetch_and_or), + BUILTIN_ROW(__sync_fetch_and_and), + BUILTIN_ROW(__sync_fetch_and_xor), + + BUILTIN_ROW(__sync_add_and_fetch), + BUILTIN_ROW(__sync_sub_and_fetch), + BUILTIN_ROW(__sync_and_and_fetch), + BUILTIN_ROW(__sync_or_and_fetch), + BUILTIN_ROW(__sync_xor_and_fetch), + + BUILTIN_ROW(__sync_val_compare_and_swap), + BUILTIN_ROW(__sync_bool_compare_and_swap), + BUILTIN_ROW(__sync_lock_test_and_set), + BUILTIN_ROW(__sync_lock_release), + BUILTIN_ROW(__sync_swap) + }; +#undef BUILTIN_ROW + + // Determine the index of the size. + unsigned SizeIndex; + switch (Context.getTypeSizeInChars(ValType).getQuantity()) { + case 1: SizeIndex = 0; break; + case 2: SizeIndex = 1; break; + case 4: SizeIndex = 2; break; + case 8: SizeIndex = 3; break; + case 16: SizeIndex = 4; break; + default: + Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } + + // Each of these builtins has one pointer argument, followed by some number of + // values (0, 1 or 2) followed by a potentially empty varags list of stuff + // that we ignore. Find out which row of BuiltinIndices to read from as well + // as the number of fixed args. + unsigned BuiltinID = FDecl->getBuiltinID(); + unsigned BuiltinIndex, NumFixed = 1; + switch (BuiltinID) { + default: assert(0 && "Unknown overloaded atomic builtin!"); + case Builtin::BI__sync_fetch_and_add: BuiltinIndex = 0; break; + case Builtin::BI__sync_fetch_and_sub: BuiltinIndex = 1; break; + case Builtin::BI__sync_fetch_and_or: BuiltinIndex = 2; break; + case Builtin::BI__sync_fetch_and_and: BuiltinIndex = 3; break; + case Builtin::BI__sync_fetch_and_xor: BuiltinIndex = 4; break; + + case Builtin::BI__sync_add_and_fetch: BuiltinIndex = 5; break; + case Builtin::BI__sync_sub_and_fetch: BuiltinIndex = 6; break; + case Builtin::BI__sync_and_and_fetch: BuiltinIndex = 7; break; + case Builtin::BI__sync_or_and_fetch: BuiltinIndex = 8; break; + case Builtin::BI__sync_xor_and_fetch: BuiltinIndex = 9; break; + + case Builtin::BI__sync_val_compare_and_swap: + BuiltinIndex = 10; + NumFixed = 2; + break; + case Builtin::BI__sync_bool_compare_and_swap: + BuiltinIndex = 11; + NumFixed = 2; + ResultType = Context.BoolTy; + break; + case Builtin::BI__sync_lock_test_and_set: BuiltinIndex = 12; break; + case Builtin::BI__sync_lock_release: + BuiltinIndex = 13; + NumFixed = 0; + ResultType = Context.VoidTy; + break; + case Builtin::BI__sync_swap: BuiltinIndex = 14; break; + } + + // Now that we know how many fixed arguments we expect, first check that we + // have at least that many. + if (TheCall->getNumArgs() < 1+NumFixed) { + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1+NumFixed << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } + + // Get the decl for the concrete builtin from this, we can tell what the + // concrete integer type we should convert to is. + unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex]; + const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID); + IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName); + FunctionDecl *NewBuiltinDecl = + cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID, + TUScope, false, DRE->getLocStart())); + + // The first argument --- the pointer --- has a fixed type; we + // deduce the types of the rest of the arguments accordingly. Walk + // the remaining arguments, converting them to the deduced value type. + for (unsigned i = 0; i != NumFixed; ++i) { + ExprResult Arg = TheCall->getArg(i+1); + + // If the argument is an implicit cast, then there was a promotion due to + // "...", just remove it now. + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg.get())) { + Arg = ICE->getSubExpr(); + ICE->setSubExpr(0); + TheCall->setArg(i+1, Arg.get()); + } + + // GCC does an implicit conversion to the pointer or integer ValType. This + // can fail in some cases (1i -> int**), check for this error case now. + CastKind Kind = CK_Invalid; + ExprValueKind VK = VK_RValue; + CXXCastPath BasePath; + Arg = CheckCastTypes(Arg.get()->getSourceRange(), ValType, Arg.take(), Kind, VK, BasePath); + if (Arg.isInvalid()) + return ExprError(); + + // Okay, we have something that *can* be converted to the right type. Check + // to see if there is a potentially weird extension going on here. This can + // happen when you do an atomic operation on something like an char* and + // pass in 42. The 42 gets converted to char. This is even more strange + // for things like 45.123 -> char, etc. + // FIXME: Do this check. + Arg = ImpCastExprToType(Arg.take(), ValType, Kind, VK, &BasePath); + TheCall->setArg(i+1, Arg.get()); + } + + // Switch the DeclRefExpr to refer to the new decl. + DRE->setDecl(NewBuiltinDecl); + DRE->setType(NewBuiltinDecl->getType()); + + // Set the callee in the CallExpr. + // FIXME: This leaks the original parens and implicit casts. + ExprResult PromotedCall = UsualUnaryConversions(DRE); + if (PromotedCall.isInvalid()) + return ExprError(); + TheCall->setCallee(PromotedCall.take()); + + // Change the result type of the call to match the original value type. This + // is arbitrary, but the codegen for these builtins ins design to handle it + // gracefully. + TheCall->setType(ResultType); + + return move(TheCallResult); +} + + +/// CheckObjCString - Checks that the argument to the builtin +/// CFString constructor is correct +/// Note: It might also make sense to do the UTF-16 conversion here (would +/// simplify the backend). +bool Sema::CheckObjCString(Expr *Arg) { + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Literal = dyn_cast<StringLiteral>(Arg); + + if (!Literal || Literal->isWide()) { + Diag(Arg->getLocStart(), diag::err_cfstring_literal_not_string_constant) + << Arg->getSourceRange(); + return true; + } + + if (Literal->containsNonAsciiOrNull()) { + llvm::StringRef String = Literal->getString(); + unsigned NumBytes = String.size(); + llvm::SmallVector<UTF16, 128> ToBuf(NumBytes); + const UTF8 *FromPtr = (UTF8 *)String.data(); + UTF16 *ToPtr = &ToBuf[0]; + + ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, + &ToPtr, ToPtr + NumBytes, + strictConversion); + // Check for conversion failure. + if (Result != conversionOK) + Diag(Arg->getLocStart(), + diag::warn_cfstring_truncated) << Arg->getSourceRange(); + } + return false; +} + +/// SemaBuiltinVAStart - Check the arguments to __builtin_va_start for validity. +/// Emit an error and return true on failure, return false on success. +bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { + Expr *Fn = TheCall->getCallee(); + if (TheCall->getNumArgs() > 2) { + Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << Fn->getSourceRange() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + return true; + } + + if (TheCall->getNumArgs() < 2) { + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs(); + } + + // Determine whether the current function is variadic or not. + BlockScopeInfo *CurBlock = getCurBlock(); + bool isVariadic; + if (CurBlock) + isVariadic = CurBlock->TheDecl->isVariadic(); + else if (FunctionDecl *FD = getCurFunctionDecl()) + isVariadic = FD->isVariadic(); + else + isVariadic = getCurMethodDecl()->isVariadic(); + + if (!isVariadic) { + Diag(Fn->getLocStart(), diag::err_va_start_used_in_non_variadic_function); + return true; + } + + // Verify that the second argument to the builtin is the last argument of the + // current function or method. + bool SecondArgIsLastNamedArgument = false; + const Expr *Arg = TheCall->getArg(1)->IgnoreParenCasts(); + + if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Arg)) { + if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(DR->getDecl())) { + // FIXME: This isn't correct for methods (results in bogus warning). + // Get the last formal in the current function. + const ParmVarDecl *LastArg; + if (CurBlock) + LastArg = *(CurBlock->TheDecl->param_end()-1); + else if (FunctionDecl *FD = getCurFunctionDecl()) + LastArg = *(FD->param_end()-1); + else + LastArg = *(getCurMethodDecl()->param_end()-1); + SecondArgIsLastNamedArgument = PV == LastArg; + } + } + + if (!SecondArgIsLastNamedArgument) + Diag(TheCall->getArg(1)->getLocStart(), + diag::warn_second_parameter_of_va_start_not_last_named_argument); + return false; +} + +/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isgreater and +/// friends. This is declared to take (...), so we have to check everything. +bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << 2 << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > 2) + return Diag(TheCall->getArg(2)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(2)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + ExprResult OrigArg0 = TheCall->getArg(0); + ExprResult OrigArg1 = TheCall->getArg(1); + + // Do standard promotions between the two arguments, returning their common + // type. + QualType Res = UsualArithmeticConversions(OrigArg0, OrigArg1, false); + if (OrigArg0.isInvalid() || OrigArg1.isInvalid()) + return true; + + // Make sure any conversions are pushed back into the call; this is + // type safe since unordered compare builtins are declared as "_Bool + // foo(...)". + TheCall->setArg(0, OrigArg0.get()); + TheCall->setArg(1, OrigArg1.get()); + + if (OrigArg0.get()->isTypeDependent() || OrigArg1.get()->isTypeDependent()) + return false; + + // If the common type isn't a real floating type, then the arguments were + // invalid for this operation. + if (!Res->isRealFloatingType()) + return Diag(OrigArg0.get()->getLocStart(), + diag::err_typecheck_call_invalid_ordered_compare) + << OrigArg0.get()->getType() << OrigArg1.get()->getType() + << SourceRange(OrigArg0.get()->getLocStart(), OrigArg1.get()->getLocEnd()); + + return false; +} + +/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like +/// __builtin_isnan and friends. This is declared to take (...), so we have +/// to check everything. We expect the last argument to be a floating point +/// value. +bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { + if (TheCall->getNumArgs() < NumArgs) + return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) + << 0 << NumArgs << TheCall->getNumArgs()/*function call*/; + if (TheCall->getNumArgs() > NumArgs) + return Diag(TheCall->getArg(NumArgs)->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 0 /*function call*/ << NumArgs << TheCall->getNumArgs() + << SourceRange(TheCall->getArg(NumArgs)->getLocStart(), + (*(TheCall->arg_end()-1))->getLocEnd()); + + Expr *OrigArg = TheCall->getArg(NumArgs-1); + + if (OrigArg->isTypeDependent()) + return false; + + // This operation requires a non-_Complex floating-point number. + if (!OrigArg->getType()->isRealFloatingType()) + return Diag(OrigArg->getLocStart(), + diag::err_typecheck_call_invalid_unary_fp) + << OrigArg->getType() << OrigArg->getSourceRange(); + + // If this is an implicit conversion from float -> double, remove it. + if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(OrigArg)) { + Expr *CastArg = Cast->getSubExpr(); + if (CastArg->getType()->isSpecificBuiltinType(BuiltinType::Float)) { + assert(Cast->getType()->isSpecificBuiltinType(BuiltinType::Double) && + "promotion from float to double is the only expected cast here"); + Cast->setSubExpr(0); + TheCall->setArg(NumArgs-1, CastArg); + OrigArg = CastArg; + } + } + + return false; +} + +/// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. +// This is declared to take (...), so we have to check everything. +ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { + if (TheCall->getNumArgs() < 2) + return ExprError(Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_few_args_at_least) + << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << TheCall->getSourceRange()); + + // Determine which of the following types of shufflevector we're checking: + // 1) unary, vector mask: (lhs, mask) + // 2) binary, vector mask: (lhs, rhs, mask) + // 3) binary, scalar mask: (lhs, rhs, index, ..., index) + QualType resType = TheCall->getArg(0)->getType(); + unsigned numElements = 0; + + if (!TheCall->getArg(0)->isTypeDependent() && + !TheCall->getArg(1)->isTypeDependent()) { + QualType LHSType = TheCall->getArg(0)->getType(); + QualType RHSType = TheCall->getArg(1)->getType(); + + if (!LHSType->isVectorType() || !RHSType->isVectorType()) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + return ExprError(); + } + + numElements = LHSType->getAs<VectorType>()->getNumElements(); + unsigned numResElements = TheCall->getNumArgs() - 2; + + // Check to see if we have a call with 2 vector arguments, the unary shuffle + // with mask. If so, verify that RHS is an integer vector type with the + // same number of elts as lhs. + if (TheCall->getNumArgs() == 2) { + if (!RHSType->hasIntegerRepresentation() || + RHSType->getAs<VectorType>()->getNumElements() != numElements) + Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(1)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + numResElements = numElements; + } + else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { + Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(0)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + return ExprError(); + } else if (numElements != numResElements) { + QualType eltType = LHSType->getAs<VectorType>()->getElementType(); + resType = Context.getVectorType(eltType, numResElements, + VectorType::GenericVector); + } + } + + for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { + if (TheCall->getArg(i)->isTypeDependent() || + TheCall->getArg(i)->isValueDependent()) + continue; + + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_nonconstant_argument) + << TheCall->getArg(i)->getSourceRange()); + + if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_argument_too_large) + << TheCall->getArg(i)->getSourceRange()); + } + + llvm::SmallVector<Expr*, 32> exprs; + + for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { + exprs.push_back(TheCall->getArg(i)); + TheCall->setArg(i, 0); + } + + return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(), + exprs.size(), resType, + TheCall->getCallee()->getLocStart(), + TheCall->getRParenLoc())); +} + +/// SemaBuiltinPrefetch - Handle __builtin_prefetch. +// This is declared to take (const void*, ...) and can take two +// optional constant int args. +bool Sema::SemaBuiltinPrefetch(CallExpr *TheCall) { + unsigned NumArgs = TheCall->getNumArgs(); + + if (NumArgs > 3) + return Diag(TheCall->getLocEnd(), + diag::err_typecheck_call_too_many_args_at_most) + << 0 /*function call*/ << 3 << NumArgs + << TheCall->getSourceRange(); + + // Argument 0 is checked for us and the remaining arguments must be + // constant integers. + for (unsigned i = 1; i != NumArgs; ++i) { + Expr *Arg = TheCall->getArg(i); + + llvm::APSInt Result; + if (SemaBuiltinConstantArg(TheCall, i, Result)) + return true; + + // FIXME: gcc issues a warning and rewrites these to 0. These + // seems especially odd for the third argument since the default + // is 3. + if (i == 1) { + if (Result.getLimitedValue() > 1) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << "0" << "1" << Arg->getSourceRange(); + } else { + if (Result.getLimitedValue() > 3) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << "0" << "3" << Arg->getSourceRange(); + } + } + + return false; +} + +/// SemaBuiltinConstantArg - Handle a check if argument ArgNum of CallExpr +/// TheCall is a constant expression. +bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, + llvm::APSInt &Result) { + Expr *Arg = TheCall->getArg(ArgNum); + DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); + FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); + + if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; + + if (!Arg->isIntegerConstantExpr(Result, Context)) + return Diag(TheCall->getLocStart(), diag::err_constant_integer_arg_type) + << FDecl->getDeclName() << Arg->getSourceRange(); + + return false; +} + +/// SemaBuiltinObjectSize - Handle __builtin_object_size(void *ptr, +/// int type). This simply type checks that type is one of the defined +/// constants (0-3). +// For compatibility check 0-3, llvm only handles 0 and 2. +bool Sema::SemaBuiltinObjectSize(CallExpr *TheCall) { + llvm::APSInt Result; + + // Check constant-ness first. + if (SemaBuiltinConstantArg(TheCall, 1, Result)) + return true; + + Expr *Arg = TheCall->getArg(1); + if (Result.getSExtValue() < 0 || Result.getSExtValue() > 3) { + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << "0" << "3" << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + } + + return false; +} + +/// SemaBuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). +/// This checks that val is a constant 1. +bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { + Expr *Arg = TheCall->getArg(1); + llvm::APSInt Result; + + // TODO: This is less than ideal. Overload this to take a value. + if (SemaBuiltinConstantArg(TheCall, 1, Result)) + return true; + + if (Result != 1) + return Diag(TheCall->getLocStart(), diag::err_builtin_longjmp_invalid_val) + << SourceRange(Arg->getLocStart(), Arg->getLocEnd()); + + return false; +} + +// Handle i > 1 ? "x" : "y", recursively. +bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, + bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + bool isPrintf) { + tryAgain: + if (E->isTypeDependent() || E->isValueDependent()) + return false; + + E = E->IgnoreParens(); + + switch (E->getStmtClass()) { + case Stmt::BinaryConditionalOperatorClass: + case Stmt::ConditionalOperatorClass: { + const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E); + return SemaCheckStringLiteral(C->getTrueExpr(), TheCall, HasVAListArg, + format_idx, firstDataArg, isPrintf) + && SemaCheckStringLiteral(C->getFalseExpr(), TheCall, HasVAListArg, + format_idx, firstDataArg, isPrintf); + } + + case Stmt::IntegerLiteralClass: + // Technically -Wformat-nonliteral does not warn about this case. + // The behavior of printf and friends in this case is implementation + // dependent. Ideally if the format string cannot be null then + // it should have a 'nonnull' attribute in the function prototype. + return true; + + case Stmt::ImplicitCastExprClass: { + E = cast<ImplicitCastExpr>(E)->getSubExpr(); + goto tryAgain; + } + + case Stmt::OpaqueValueExprClass: + if (const Expr *src = cast<OpaqueValueExpr>(E)->getSourceExpr()) { + E = src; + goto tryAgain; + } + return false; + + case Stmt::PredefinedExprClass: + // While __func__, etc., are technically not string literals, they + // cannot contain format specifiers and thus are not a security + // liability. + return true; + + case Stmt::DeclRefExprClass: { + const DeclRefExpr *DR = cast<DeclRefExpr>(E); + + // As an exception, do not flag errors for variables binding to + // const string literals. + if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { + bool isConstant = false; + QualType T = DR->getType(); + + if (const ArrayType *AT = Context.getAsArrayType(T)) { + isConstant = AT->getElementType().isConstant(Context); + } else if (const PointerType *PT = T->getAs<PointerType>()) { + isConstant = T.isConstant(Context) && + PT->getPointeeType().isConstant(Context); + } + + if (isConstant) { + if (const Expr *Init = VD->getAnyInitializer()) + return SemaCheckStringLiteral(Init, TheCall, + HasVAListArg, format_idx, firstDataArg, + isPrintf); + } + + // For vprintf* functions (i.e., HasVAListArg==true), we add a + // special check to see if the format string is a function parameter + // of the function calling the printf function. If the function + // has an attribute indicating it is a printf-like function, then we + // should suppress warnings concerning non-literals being used in a call + // to a vprintf function. For example: + // + // void + // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){ + // va_list ap; + // va_start(ap, fmt); + // vprintf(fmt, ap); // Do NOT emit a warning about "fmt". + // ... + // + // + // FIXME: We don't have full attribute support yet, so just check to see + // if the argument is a DeclRefExpr that references a parameter. We'll + // add proper support for checking the attribute later. + if (HasVAListArg) + if (isa<ParmVarDecl>(VD)) + return true; + } + + return false; + } + + case Stmt::CallExprClass: { + const CallExpr *CE = cast<CallExpr>(E); + if (const ImplicitCastExpr *ICE + = dyn_cast<ImplicitCastExpr>(CE->getCallee())) { + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { + if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>()) { + unsigned ArgIndex = FA->getFormatIdx(); + const Expr *Arg = CE->getArg(ArgIndex - 1); + + return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg, + format_idx, firstDataArg, isPrintf); + } + } + } + } + + return false; + } + case Stmt::ObjCStringLiteralClass: + case Stmt::StringLiteralClass: { + const StringLiteral *StrE = NULL; + + if (const ObjCStringLiteral *ObjCFExpr = dyn_cast<ObjCStringLiteral>(E)) + StrE = ObjCFExpr->getString(); + else + StrE = cast<StringLiteral>(E); + + if (StrE) { + CheckFormatString(StrE, E, TheCall, HasVAListArg, format_idx, + firstDataArg, isPrintf); + return true; + } + + return false; + } + + default: + return false; + } +} + +void +Sema::CheckNonNullArguments(const NonNullAttr *NonNull, + const Expr * const *ExprArgs, + SourceLocation CallSiteLoc) { + for (NonNullAttr::args_iterator i = NonNull->args_begin(), + e = NonNull->args_end(); + i != e; ++i) { + const Expr *ArgExpr = ExprArgs[*i]; + if (ArgExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull)) + Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); + } +} + +/// CheckPrintfScanfArguments - Check calls to printf and scanf (and similar +/// functions) for correct use of format strings. +void +Sema::CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + bool isPrintf) { + + const Expr *Fn = TheCall->getCallee(); + + // The way the format attribute works in GCC, the implicit this argument + // of member functions is counted. However, it doesn't appear in our own + // lists, so decrement format_idx in that case. + if (isa<CXXMemberCallExpr>(TheCall)) { + const CXXMethodDecl *method_decl = + dyn_cast<CXXMethodDecl>(TheCall->getCalleeDecl()); + if (method_decl && method_decl->isInstance()) { + // Catch a format attribute mistakenly referring to the object argument. + if (format_idx == 0) + return; + --format_idx; + if(firstDataArg != 0) + --firstDataArg; + } + } + + // CHECK: printf/scanf-like function is called with no format string. + if (format_idx >= TheCall->getNumArgs()) { + Diag(TheCall->getRParenLoc(), diag::warn_missing_format_string) + << Fn->getSourceRange(); + return; + } + + const Expr *OrigFormatExpr = TheCall->getArg(format_idx)->IgnoreParenCasts(); + + // CHECK: format string is not a string literal. + // + // Dynamically generated format strings are difficult to + // automatically vet at compile time. Requiring that format strings + // are string literals: (1) permits the checking of format strings by + // the compiler and thereby (2) can practically remove the source of + // many format string exploits. + + // Format string can be either ObjC string (e.g. @"%d") or + // C string (e.g. "%d") + // ObjC string uses the same format specifiers as C string, so we can use + // the same format string checking logic for both ObjC and C strings. + if (SemaCheckStringLiteral(OrigFormatExpr, TheCall, HasVAListArg, format_idx, + firstDataArg, isPrintf)) + return; // Literal format string found, check done! + + // If there are no arguments specified, warn with -Wformat-security, otherwise + // warn only with -Wformat-nonliteral. + if (TheCall->getNumArgs() == format_idx+1) + Diag(TheCall->getArg(format_idx)->getLocStart(), + diag::warn_format_nonliteral_noargs) + << OrigFormatExpr->getSourceRange(); + else + Diag(TheCall->getArg(format_idx)->getLocStart(), + diag::warn_format_nonliteral) + << OrigFormatExpr->getSourceRange(); +} + +namespace { +class CheckFormatHandler : public analyze_format_string::FormatStringHandler { +protected: + Sema &S; + const StringLiteral *FExpr; + const Expr *OrigFormatExpr; + const unsigned FirstDataArg; + const unsigned NumDataArgs; + const bool IsObjCLiteral; + const char *Beg; // Start of format string. + const bool HasVAListArg; + const CallExpr *TheCall; + unsigned FormatIdx; + llvm::BitVector CoveredArgs; + bool usesPositionalArgs; + bool atFirstArg; +public: + CheckFormatHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, bool isObjCLiteral, + const char *beg, bool hasVAListArg, + const CallExpr *theCall, unsigned formatIdx) + : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), + FirstDataArg(firstDataArg), + NumDataArgs(numDataArgs), + IsObjCLiteral(isObjCLiteral), Beg(beg), + HasVAListArg(hasVAListArg), + TheCall(theCall), FormatIdx(formatIdx), + usesPositionalArgs(false), atFirstArg(true) { + CoveredArgs.resize(numDataArgs); + CoveredArgs.reset(); + } + + void DoneProcessing(); + + void HandleIncompleteSpecifier(const char *startSpecifier, + unsigned specifierLen); + + virtual void HandleInvalidPosition(const char *startSpecifier, + unsigned specifierLen, + analyze_format_string::PositionContext p); + + virtual void HandleZeroPosition(const char *startPos, unsigned posLen); + + void HandleNullChar(const char *nullCharacter); + +protected: + bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, + const char *startSpec, + unsigned specifierLen, + const char *csStart, unsigned csLen); + + SourceRange getFormatStringRange(); + CharSourceRange getSpecifierRange(const char *startSpecifier, + unsigned specifierLen); + SourceLocation getLocationOfByte(const char *x); + + const Expr *getDataArg(unsigned i) const; + + bool CheckNumArgs(const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, + unsigned argIndex); +}; +} + +SourceRange CheckFormatHandler::getFormatStringRange() { + return OrigFormatExpr->getSourceRange(); +} + +CharSourceRange CheckFormatHandler:: +getSpecifierRange(const char *startSpecifier, unsigned specifierLen) { + SourceLocation Start = getLocationOfByte(startSpecifier); + SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1); + + // Advance the end SourceLocation by one due to half-open ranges. + End = End.getFileLocWithOffset(1); + + return CharSourceRange::getCharRange(Start, End); +} + +SourceLocation CheckFormatHandler::getLocationOfByte(const char *x) { + return S.getLocationOfStringLiteralByte(FExpr, x - Beg); +} + +void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier, + unsigned specifierLen){ + SourceLocation Loc = getLocationOfByte(startSpecifier); + S.Diag(Loc, diag::warn_printf_incomplete_specifier) + << getSpecifierRange(startSpecifier, specifierLen); +} + +void +CheckFormatHandler::HandleInvalidPosition(const char *startPos, unsigned posLen, + analyze_format_string::PositionContext p) { + SourceLocation Loc = getLocationOfByte(startPos); + S.Diag(Loc, diag::warn_format_invalid_positional_specifier) + << (unsigned) p << getSpecifierRange(startPos, posLen); +} + +void CheckFormatHandler::HandleZeroPosition(const char *startPos, + unsigned posLen) { + SourceLocation Loc = getLocationOfByte(startPos); + S.Diag(Loc, diag::warn_format_zero_positional_specifier) + << getSpecifierRange(startPos, posLen); +} + +void CheckFormatHandler::HandleNullChar(const char *nullCharacter) { + if (!IsObjCLiteral) { + // The presence of a null character is likely an error. + S.Diag(getLocationOfByte(nullCharacter), + diag::warn_printf_format_string_contains_null_char) + << getFormatStringRange(); + } +} + +const Expr *CheckFormatHandler::getDataArg(unsigned i) const { + return TheCall->getArg(FirstDataArg + i); +} + +void CheckFormatHandler::DoneProcessing() { + // Does the number of data arguments exceed the number of + // format conversions in the format string? + if (!HasVAListArg) { + // Find any arguments that weren't covered. + CoveredArgs.flip(); + signed notCoveredArg = CoveredArgs.find_first(); + if (notCoveredArg >= 0) { + assert((unsigned)notCoveredArg < NumDataArgs); + S.Diag(getDataArg((unsigned) notCoveredArg)->getLocStart(), + diag::warn_printf_data_arg_not_used) + << getFormatStringRange(); + } + } +} + +bool +CheckFormatHandler::HandleInvalidConversionSpecifier(unsigned argIndex, + SourceLocation Loc, + const char *startSpec, + unsigned specifierLen, + const char *csStart, + unsigned csLen) { + + bool keepGoing = true; + if (argIndex < NumDataArgs) { + // Consider the argument coverered, even though the specifier doesn't + // make sense. + CoveredArgs.set(argIndex); + } + else { + // If argIndex exceeds the number of data arguments we + // don't issue a warning because that is just a cascade of warnings (and + // they may have intended '%%' anyway). We don't want to continue processing + // the format string after this point, however, as we will like just get + // gibberish when trying to match arguments. + keepGoing = false; + } + + S.Diag(Loc, diag::warn_format_invalid_conversion) + << llvm::StringRef(csStart, csLen) + << getSpecifierRange(startSpec, specifierLen); + + return keepGoing; +} + +bool +CheckFormatHandler::CheckNumArgs( + const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, unsigned argIndex) { + + if (argIndex >= NumDataArgs) { + if (FS.usesPositionalArg()) { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_positional_arg_exceeds_data_args) + << (argIndex+1) << NumDataArgs + << getSpecifierRange(startSpecifier, specifierLen); + } + else { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_insufficient_data_args) + << getSpecifierRange(startSpecifier, specifierLen); + } + + return false; + } + return true; +} + +//===--- CHECK: Printf format string checking ------------------------------===// + +namespace { +class CheckPrintfHandler : public CheckFormatHandler { +public: + CheckPrintfHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, bool isObjCLiteral, + const char *beg, bool hasVAListArg, + const CallExpr *theCall, unsigned formatIdx) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, isObjCLiteral, beg, hasVAListArg, + theCall, formatIdx) {} + + + bool HandleInvalidPrintfConversionSpecifier( + const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + bool HandleAmount(const analyze_format_string::OptionalAmount &Amt, unsigned k, + const char *startSpecifier, unsigned specifierLen); + void HandleInvalidAmount(const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalAmount &Amt, + unsigned type, + const char *startSpecifier, unsigned specifierLen); + void HandleFlag(const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, unsigned specifierLen); + void HandleIgnoredFlag(const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalFlag &ignoredFlag, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, unsigned specifierLen); +}; +} + +bool CheckPrintfHandler::HandleInvalidPrintfConversionSpecifier( + const analyze_printf::PrintfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + const analyze_printf::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); + + return HandleInvalidConversionSpecifier(FS.getArgIndex(), + getLocationOfByte(CS.getStart()), + startSpecifier, specifierLen, + CS.getStart(), CS.getLength()); +} + +bool CheckPrintfHandler::HandleAmount( + const analyze_format_string::OptionalAmount &Amt, + unsigned k, const char *startSpecifier, + unsigned specifierLen) { + + if (Amt.hasDataArgument()) { + if (!HasVAListArg) { + unsigned argIndex = Amt.getArgIndex(); + if (argIndex >= NumDataArgs) { + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_printf_asterisk_missing_arg) + << k << getSpecifierRange(startSpecifier, specifierLen); + // Don't do any more checking. We will just emit + // spurious errors. + return false; + } + + // Type check the data argument. It should be an 'int'. + // Although not in conformance with C99, we also allow the argument to be + // an 'unsigned int' as that is a reasonably safe case. GCC also + // doesn't emit a warning for that case. + CoveredArgs.set(argIndex); + const Expr *Arg = getDataArg(argIndex); + QualType T = Arg->getType(); + + const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context); + assert(ATR.isValid()); + + if (!ATR.matchesType(S.Context, T)) { + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_printf_asterisk_wrong_type) + << k + << ATR.getRepresentativeType(S.Context) << T + << getSpecifierRange(startSpecifier, specifierLen) + << Arg->getSourceRange(); + // Don't do any more checking. We will just emit + // spurious errors. + return false; + } + } + } + return true; +} + +void CheckPrintfHandler::HandleInvalidAmount( + const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalAmount &Amt, + unsigned type, + const char *startSpecifier, + unsigned specifierLen) { + const analyze_printf::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); + switch (Amt.getHowSpecified()) { + case analyze_printf::OptionalAmount::Constant: + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_printf_nonsensical_optional_amount) + << type + << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(Amt.getStart(), + Amt.getConstantLength())); + break; + + default: + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_printf_nonsensical_optional_amount) + << type + << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen); + break; + } +} + +void CheckPrintfHandler::HandleFlag(const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, + unsigned specifierLen) { + // Warn about pointless flag with a fixit removal. + const analyze_printf::PrintfConversionSpecifier &CS = + FS.getConversionSpecifier(); + S.Diag(getLocationOfByte(flag.getPosition()), + diag::warn_printf_nonsensical_flag) + << flag.toString() << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(flag.getPosition(), 1)); +} + +void CheckPrintfHandler::HandleIgnoredFlag( + const analyze_printf::PrintfSpecifier &FS, + const analyze_printf::OptionalFlag &ignoredFlag, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, + unsigned specifierLen) { + // Warn about ignored flag with a fixit removal. + S.Diag(getLocationOfByte(ignoredFlag.getPosition()), + diag::warn_printf_ignored_flag) + << ignoredFlag.toString() << flag.toString() + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange( + ignoredFlag.getPosition(), 1)); +} + +bool +CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier + &FS, + const char *startSpecifier, + unsigned specifierLen) { + + using namespace analyze_format_string; + using namespace analyze_printf; + const PrintfConversionSpecifier &CS = FS.getConversionSpecifier(); + + if (FS.consumesDataArgument()) { + if (atFirstArg) { + atFirstArg = false; + usesPositionalArgs = FS.usesPositionalArg(); + } + else if (usesPositionalArgs != FS.usesPositionalArg()) { + // Cannot mix-and-match positional and non-positional arguments. + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_format_mix_positional_nonpositional_args) + << getSpecifierRange(startSpecifier, specifierLen); + return false; + } + } + + // First check if the field width, precision, and conversion specifier + // have matching data arguments. + if (!HandleAmount(FS.getFieldWidth(), /* field width */ 0, + startSpecifier, specifierLen)) { + return false; + } + + if (!HandleAmount(FS.getPrecision(), /* precision */ 1, + startSpecifier, specifierLen)) { + return false; + } + + if (!CS.consumesDataArgument()) { + // FIXME: Technically specifying a precision or field width here + // makes no sense. Worth issuing a warning at some point. + return true; + } + + // Consume the argument. + unsigned argIndex = FS.getArgIndex(); + if (argIndex < NumDataArgs) { + // The check to see if the argIndex is valid will come later. + // We set the bit here because we may exit early from this + // function if we encounter some other error. + CoveredArgs.set(argIndex); + } + + // FreeBSD extensions + if (CS.getKind() == ConversionSpecifier::bArg || CS.getKind() == ConversionSpecifier::DArg) { + // claim the second argument + CoveredArgs.set(argIndex + 1); + + // Now type check the data expression that matches the + // format specifier. + const Expr *Ex = getDataArg(argIndex); + const analyze_printf::ArgTypeResult &ATR = + (CS.getKind() == ConversionSpecifier::bArg) ? + ArgTypeResult(S.Context.IntTy) : ArgTypeResult::CStrTy; + if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeType(S.Context) << Ex->getType() + << getSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange(); + + // Now type check the data expression that matches the + // format specifier. + Ex = getDataArg(argIndex + 1); + const analyze_printf::ArgTypeResult &ATR2 = ArgTypeResult::CStrTy; + if (ATR2.isValid() && !ATR2.matchesType(S.Context, Ex->getType())) + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_conversion_argument_type_mismatch) + << ATR2.getRepresentativeType(S.Context) << Ex->getType() + << getSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange(); + + return true; + } + // END OF FREEBSD EXTENSIONS + + // Check for using an Objective-C specific conversion specifier + // in a non-ObjC literal. + if (!IsObjCLiteral && CS.isObjCArg()) { + return HandleInvalidPrintfConversionSpecifier(FS, startSpecifier, + specifierLen); + } + + // Check for invalid use of field width + if (!FS.hasValidFieldWidth()) { + HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0, + startSpecifier, specifierLen); + } + + // Check for invalid use of precision + if (!FS.hasValidPrecision()) { + HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1, + startSpecifier, specifierLen); + } + + // Check each flag does not conflict with any other component. + if (!FS.hasValidThousandsGroupingPrefix()) + HandleFlag(FS, FS.hasThousandsGrouping(), startSpecifier, specifierLen); + if (!FS.hasValidLeadingZeros()) + HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen); + if (!FS.hasValidPlusPrefix()) + HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen); + if (!FS.hasValidSpacePrefix()) + HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen); + if (!FS.hasValidAlternativeForm()) + HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen); + if (!FS.hasValidLeftJustified()) + HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen); + + // Check that flags are not ignored by another flag + if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+' + HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(), + startSpecifier, specifierLen); + if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-' + HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(), + startSpecifier, specifierLen); + + // Check the length modifier is valid with the given conversion specifier. + const LengthModifier &LM = FS.getLengthModifier(); + if (!FS.hasValidLengthModifier()) + S.Diag(getLocationOfByte(LM.getStart()), + diag::warn_format_nonsensical_length) + << LM.toString() << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(), + LM.getLength())); + + // Are we using '%n'? + if (CS.getKind() == ConversionSpecifier::nArg) { + // Issue a warning about this being a possible security issue. + S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back) + << getSpecifierRange(startSpecifier, specifierLen); + // Continue checking the other format specifiers. + return true; + } + + // The remaining checks depend on the data arguments. + if (HasVAListArg) + return true; + + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) + return false; + + // Now type check the data expression that matches the + // format specifier. + const Expr *Ex = getDataArg(argIndex); + const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context); + if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) { + // Check if we didn't match because of an implicit cast from a 'char' + // or 'short' to an 'int'. This is done because printf is a varargs + // function. + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex)) + if (ICE->getType() == S.Context.IntTy) { + // All further checking is done on the subexpression. + Ex = ICE->getSubExpr(); + if (ATR.matchesType(S.Context, Ex->getType())) + return true; + } + + // We may be able to offer a FixItHint if it is a supported type. + PrintfSpecifier fixedFS = FS; + bool success = fixedFS.fixType(Ex->getType()); + + if (success) { + // Get the fix string from the fixed format specifier + llvm::SmallString<128> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + // FIXME: getRepresentativeType() perhaps should return a string + // instead of a QualType to better handle when the representative + // type is 'wint_t' (which is defined in the system headers). + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeType(S.Context) << Ex->getType() + << getSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange() + << FixItHint::CreateReplacement( + getSpecifierRange(startSpecifier, specifierLen), + os.str()); + } + else { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeType(S.Context) << Ex->getType() + << getSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange(); + } + } + + return true; +} + +//===--- CHECK: Scanf format string checking ------------------------------===// + +namespace { +class CheckScanfHandler : public CheckFormatHandler { +public: + CheckScanfHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, unsigned firstDataArg, + unsigned numDataArgs, bool isObjCLiteral, + const char *beg, bool hasVAListArg, + const CallExpr *theCall, unsigned formatIdx) + : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, + numDataArgs, isObjCLiteral, beg, hasVAListArg, + theCall, formatIdx) {} + + bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + bool HandleInvalidScanfConversionSpecifier( + const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + void HandleIncompleteScanList(const char *start, const char *end); +}; +} + +void CheckScanfHandler::HandleIncompleteScanList(const char *start, + const char *end) { + S.Diag(getLocationOfByte(end), diag::warn_scanf_scanlist_incomplete) + << getSpecifierRange(start, end - start); +} + +bool CheckScanfHandler::HandleInvalidScanfConversionSpecifier( + const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + + const analyze_scanf::ScanfConversionSpecifier &CS = + FS.getConversionSpecifier(); + + return HandleInvalidConversionSpecifier(FS.getArgIndex(), + getLocationOfByte(CS.getStart()), + startSpecifier, specifierLen, + CS.getStart(), CS.getLength()); +} + +bool CheckScanfHandler::HandleScanfSpecifier( + const analyze_scanf::ScanfSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + + using namespace analyze_scanf; + using namespace analyze_format_string; + + const ScanfConversionSpecifier &CS = FS.getConversionSpecifier(); + + // Handle case where '%' and '*' don't consume an argument. These shouldn't + // be used to decide if we are using positional arguments consistently. + if (FS.consumesDataArgument()) { + if (atFirstArg) { + atFirstArg = false; + usesPositionalArgs = FS.usesPositionalArg(); + } + else if (usesPositionalArgs != FS.usesPositionalArg()) { + // Cannot mix-and-match positional and non-positional arguments. + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_format_mix_positional_nonpositional_args) + << getSpecifierRange(startSpecifier, specifierLen); + return false; + } + } + + // Check if the field with is non-zero. + const OptionalAmount &Amt = FS.getFieldWidth(); + if (Amt.getHowSpecified() == OptionalAmount::Constant) { + if (Amt.getConstantAmount() == 0) { + const CharSourceRange &R = getSpecifierRange(Amt.getStart(), + Amt.getConstantLength()); + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_scanf_nonzero_width) + << R << FixItHint::CreateRemoval(R); + } + } + + if (!FS.consumesDataArgument()) { + // FIXME: Technically specifying a precision or field width here + // makes no sense. Worth issuing a warning at some point. + return true; + } + + // Consume the argument. + unsigned argIndex = FS.getArgIndex(); + if (argIndex < NumDataArgs) { + // The check to see if the argIndex is valid will come later. + // We set the bit here because we may exit early from this + // function if we encounter some other error. + CoveredArgs.set(argIndex); + } + + // Check the length modifier is valid with the given conversion specifier. + const LengthModifier &LM = FS.getLengthModifier(); + if (!FS.hasValidLengthModifier()) { + S.Diag(getLocationOfByte(LM.getStart()), + diag::warn_format_nonsensical_length) + << LM.toString() << CS.toString() + << getSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getSpecifierRange(LM.getStart(), + LM.getLength())); + } + + // The remaining checks depend on the data arguments. + if (HasVAListArg) + return true; + + if (!CheckNumArgs(FS, CS, startSpecifier, specifierLen, argIndex)) + return false; + + // FIXME: Check that the argument type matches the format specifier. + + return true; +} + +void Sema::CheckFormatString(const StringLiteral *FExpr, + const Expr *OrigFormatExpr, + const CallExpr *TheCall, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg, + bool isPrintf) { + + // CHECK: is the format string a wide literal? + if (FExpr->isWide()) { + Diag(FExpr->getLocStart(), + diag::warn_format_string_is_wide_literal) + << OrigFormatExpr->getSourceRange(); + return; + } + + // Str - The format string. NOTE: this is NOT null-terminated! + llvm::StringRef StrRef = FExpr->getString(); + const char *Str = StrRef.data(); + unsigned StrLen = StrRef.size(); + + // CHECK: empty format string? + if (StrLen == 0) { + Diag(FExpr->getLocStart(), diag::warn_empty_format_string) + << OrigFormatExpr->getSourceRange(); + return; + } + + if (isPrintf) { + CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, + TheCall->getNumArgs() - firstDataArg, + isa<ObjCStringLiteral>(OrigFormatExpr), Str, + HasVAListArg, TheCall, format_idx); + + bool FormatExtensions = getLangOptions().FormatExtensions; + if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, + FormatExtensions)) + H.DoneProcessing(); + } + else { + CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, + TheCall->getNumArgs() - firstDataArg, + isa<ObjCStringLiteral>(OrigFormatExpr), Str, + HasVAListArg, TheCall, format_idx); + + if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen)) + H.DoneProcessing(); + } +} + +//===--- CHECK: Standard memory functions ---------------------------------===// + +/// \brief Determine whether the given type is a dynamic class type (e.g., +/// whether it has a vtable). +static bool isDynamicClassType(QualType T) { + if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) + if (CXXRecordDecl *Definition = Record->getDefinition()) + if (Definition->isDynamicClass()) + return true; + + return false; +} + +/// \brief Check for dangerous or invalid arguments to memset(). +/// +/// This issues warnings on known problematic, dangerous or unspecified +/// arguments to the standard 'memset', 'memcpy', and 'memmove' function calls. +/// +/// \param Call The call expression to diagnose. +void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call, + const IdentifierInfo *FnName) { + // It is possible to have a non-standard definition of memset. Validate + // we have the proper number of arguments, and if not, abort further + // checking. + if (Call->getNumArgs() != 3) + return; + + unsigned LastArg = FnName->isStr("memset")? 1 : 2; + for (unsigned ArgIdx = 0; ArgIdx != LastArg; ++ArgIdx) { + const Expr *Dest = Call->getArg(ArgIdx)->IgnoreParenImpCasts(); + + QualType DestTy = Dest->getType(); + if (const PointerType *DestPtrTy = DestTy->getAs<PointerType>()) { + QualType PointeeTy = DestPtrTy->getPointeeType(); + if (PointeeTy->isVoidType()) + continue; + + // Always complain about dynamic classes. + if (isDynamicClassType(PointeeTy)) { + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::warn_dyn_class_memaccess) + << ArgIdx << FnName << PointeeTy + << Call->getCallee()->getSourceRange()); + } else { + continue; + } + + SourceRange ArgRange = Call->getArg(0)->getSourceRange(); + DiagRuntimeBehavior( + Dest->getExprLoc(), Dest, + PDiag(diag::note_bad_memaccess_silence) + << FixItHint::CreateInsertion(ArgRange.getBegin(), "(void*)")); + break; + } + } +} + +//===--- CHECK: Return Address of Stack Variable --------------------------===// + +static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars); +static Expr *EvalAddr(Expr* E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars); + +/// CheckReturnStackAddr - Check if a return statement returns the address +/// of a stack variable. +void +Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, + SourceLocation ReturnLoc) { + + Expr *stackE = 0; + llvm::SmallVector<DeclRefExpr *, 8> refVars; + + // Perform checking for returned stack addresses, local blocks, + // label addresses or references to temporaries. + if (lhsType->isPointerType() || lhsType->isBlockPointerType()) { + stackE = EvalAddr(RetValExp, refVars); + } else if (lhsType->isReferenceType()) { + stackE = EvalVal(RetValExp, refVars); + } + + if (stackE == 0) + return; // Nothing suspicious was found. + + SourceLocation diagLoc; + SourceRange diagRange; + if (refVars.empty()) { + diagLoc = stackE->getLocStart(); + diagRange = stackE->getSourceRange(); + } else { + // We followed through a reference variable. 'stackE' contains the + // problematic expression but we will warn at the return statement pointing + // at the reference variable. We will later display the "trail" of + // reference variables using notes. + diagLoc = refVars[0]->getLocStart(); + diagRange = refVars[0]->getSourceRange(); + } + + if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(stackE)) { //address of local var. + Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_stack_ref + : diag::warn_ret_stack_addr) + << DR->getDecl()->getDeclName() << diagRange; + } else if (isa<BlockExpr>(stackE)) { // local block. + Diag(diagLoc, diag::err_ret_local_block) << diagRange; + } else if (isa<AddrLabelExpr>(stackE)) { // address of label. + Diag(diagLoc, diag::warn_ret_addr_label) << diagRange; + } else { // local temporary. + Diag(diagLoc, lhsType->isReferenceType() ? diag::warn_ret_local_temp_ref + : diag::warn_ret_local_temp_addr) + << diagRange; + } + + // Display the "trail" of reference variables that we followed until we + // found the problematic expression using notes. + for (unsigned i = 0, e = refVars.size(); i != e; ++i) { + VarDecl *VD = cast<VarDecl>(refVars[i]->getDecl()); + // If this var binds to another reference var, show the range of the next + // var, otherwise the var binds to the problematic expression, in which case + // show the range of the expression. + SourceRange range = (i < e-1) ? refVars[i+1]->getSourceRange() + : stackE->getSourceRange(); + Diag(VD->getLocation(), diag::note_ref_var_local_bind) + << VD->getDeclName() << range; + } +} + +/// EvalAddr - EvalAddr and EvalVal are mutually recursive functions that +/// check if the expression in a return statement evaluates to an address +/// to a location on the stack, a local block, an address of a label, or a +/// reference to local temporary. The recursion is used to traverse the +/// AST of the return expression, with recursion backtracking when we +/// encounter a subexpression that (1) clearly does not lead to one of the +/// above problematic expressions (2) is something we cannot determine leads to +/// a problematic expression based on such local checking. +/// +/// Both EvalAddr and EvalVal follow through reference variables to evaluate +/// the expression that they point to. Such variables are added to the +/// 'refVars' vector so that we know what the reference variable "trail" was. +/// +/// EvalAddr processes expressions that are pointers that are used as +/// references (and not L-values). EvalVal handles all other values. +/// At the base case of the recursion is a check for the above problematic +/// expressions. +/// +/// This implementation handles: +/// +/// * pointer-to-pointer casts +/// * implicit conversions from array references to pointers +/// * taking the address of fields +/// * arbitrary interplay between "&" and "*" operators +/// * pointer arithmetic from an address of a stack variable +/// * taking the address of an array element where the array is on the stack +static Expr *EvalAddr(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) { + if (E->isTypeDependent()) + return NULL; + + // We should only be called for evaluating pointer expressions. + assert((E->getType()->isAnyPointerType() || + E->getType()->isBlockPointerType() || + E->getType()->isObjCQualifiedIdType()) && + "EvalAddr only works on pointers"); + + E = E->IgnoreParens(); + + // Our "symbolic interpreter" is just a dispatch off the currently + // viewed AST node. We then recursively traverse the AST by calling + // EvalAddr and EvalVal appropriately. + switch (E->getStmtClass()) { + case Stmt::DeclRefExprClass: { + DeclRefExpr *DR = cast<DeclRefExpr>(E); + + if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) + // If this is a reference variable, follow through to the expression that + // it points to. + if (V->hasLocalStorage() && + V->getType()->isReferenceType() && V->hasInit()) { + // Add the reference variable to the "trail". + refVars.push_back(DR); + return EvalAddr(V->getInit(), refVars); + } + + return NULL; + } + + case Stmt::UnaryOperatorClass: { + // The only unary operator that make sense to handle here + // is AddrOf. All others don't make sense as pointers. + UnaryOperator *U = cast<UnaryOperator>(E); + + if (U->getOpcode() == UO_AddrOf) + return EvalVal(U->getSubExpr(), refVars); + else + return NULL; + } + + case Stmt::BinaryOperatorClass: { + // Handle pointer arithmetic. All other binary operators are not valid + // in this context. + BinaryOperator *B = cast<BinaryOperator>(E); + BinaryOperatorKind op = B->getOpcode(); + + if (op != BO_Add && op != BO_Sub) + return NULL; + + Expr *Base = B->getLHS(); + + // Determine which argument is the real pointer base. It could be + // the RHS argument instead of the LHS. + if (!Base->getType()->isPointerType()) Base = B->getRHS(); + + assert (Base->getType()->isPointerType()); + return EvalAddr(Base, refVars); + } + + // For conditional operators we need to see if either the LHS or RHS are + // valid DeclRefExpr*s. If one of them is valid, we return it. + case Stmt::ConditionalOperatorClass: { + ConditionalOperator *C = cast<ConditionalOperator>(E); + + // Handle the GNU extension for missing LHS. + if (Expr *lhsExpr = C->getLHS()) { + // In C++, we can have a throw-expression, which has 'void' type. + if (!lhsExpr->getType()->isVoidType()) + if (Expr* LHS = EvalAddr(lhsExpr, refVars)) + return LHS; + } + + // In C++, we can have a throw-expression, which has 'void' type. + if (C->getRHS()->getType()->isVoidType()) + return NULL; + + return EvalAddr(C->getRHS(), refVars); + } + + case Stmt::BlockExprClass: + if (cast<BlockExpr>(E)->getBlockDecl()->hasCaptures()) + return E; // local block. + return NULL; + + case Stmt::AddrLabelExprClass: + return E; // address of label. + + // For casts, we need to handle conversions from arrays to + // pointer values, and pointer-to-pointer conversions. + case Stmt::ImplicitCastExprClass: + case Stmt::CStyleCastExprClass: + case Stmt::CXXFunctionalCastExprClass: { + Expr* SubExpr = cast<CastExpr>(E)->getSubExpr(); + QualType T = SubExpr->getType(); + + if (SubExpr->getType()->isPointerType() || + SubExpr->getType()->isBlockPointerType() || + SubExpr->getType()->isObjCQualifiedIdType()) + return EvalAddr(SubExpr, refVars); + else if (T->isArrayType()) + return EvalVal(SubExpr, refVars); + else + return 0; + } + + // C++ casts. For dynamic casts, static casts, and const casts, we + // are always converting from a pointer-to-pointer, so we just blow + // through the cast. In the case the dynamic cast doesn't fail (and + // return NULL), we take the conservative route and report cases + // where we return the address of a stack variable. For Reinterpre + // FIXME: The comment about is wrong; we're not always converting + // from pointer to pointer. I'm guessing that this code should also + // handle references to objects. + case Stmt::CXXStaticCastExprClass: + case Stmt::CXXDynamicCastExprClass: + case Stmt::CXXConstCastExprClass: + case Stmt::CXXReinterpretCastExprClass: { + Expr *S = cast<CXXNamedCastExpr>(E)->getSubExpr(); + if (S->getType()->isPointerType() || S->getType()->isBlockPointerType()) + return EvalAddr(S, refVars); + else + return NULL; + } + + // Everything else: we simply don't reason about them. + default: + return NULL; + } +} + + +/// EvalVal - This function is complements EvalAddr in the mutual recursion. +/// See the comments for EvalAddr for more details. +static Expr *EvalVal(Expr *E, llvm::SmallVectorImpl<DeclRefExpr *> &refVars) { +do { + // We should only be called for evaluating non-pointer expressions, or + // expressions with a pointer type that are not used as references but instead + // are l-values (e.g., DeclRefExpr with a pointer type). + + // Our "symbolic interpreter" is just a dispatch off the currently + // viewed AST node. We then recursively traverse the AST by calling + // EvalAddr and EvalVal appropriately. + + E = E->IgnoreParens(); + switch (E->getStmtClass()) { + case Stmt::ImplicitCastExprClass: { + ImplicitCastExpr *IE = cast<ImplicitCastExpr>(E); + if (IE->getValueKind() == VK_LValue) { + E = IE->getSubExpr(); + continue; + } + return NULL; + } + + case Stmt::DeclRefExprClass: { + // When we hit a DeclRefExpr we are looking at code that refers to a + // variable's name. If it's not a reference variable we check if it has + // local storage within the function, and if so, return the expression. + DeclRefExpr *DR = cast<DeclRefExpr>(E); + + if (VarDecl *V = dyn_cast<VarDecl>(DR->getDecl())) + if (V->hasLocalStorage()) { + if (!V->getType()->isReferenceType()) + return DR; + + // Reference variable, follow through to the expression that + // it points to. + if (V->hasInit()) { + // Add the reference variable to the "trail". + refVars.push_back(DR); + return EvalVal(V->getInit(), refVars); + } + } + + return NULL; + } + + case Stmt::UnaryOperatorClass: { + // The only unary operator that make sense to handle here + // is Deref. All others don't resolve to a "name." This includes + // handling all sorts of rvalues passed to a unary operator. + UnaryOperator *U = cast<UnaryOperator>(E); + + if (U->getOpcode() == UO_Deref) + return EvalAddr(U->getSubExpr(), refVars); + + return NULL; + } + + case Stmt::ArraySubscriptExprClass: { + // Array subscripts are potential references to data on the stack. We + // retrieve the DeclRefExpr* for the array variable if it indeed + // has local storage. + return EvalAddr(cast<ArraySubscriptExpr>(E)->getBase(), refVars); + } + + case Stmt::ConditionalOperatorClass: { + // For conditional operators we need to see if either the LHS or RHS are + // non-NULL Expr's. If one is non-NULL, we return it. + ConditionalOperator *C = cast<ConditionalOperator>(E); + + // Handle the GNU extension for missing LHS. + if (Expr *lhsExpr = C->getLHS()) + if (Expr *LHS = EvalVal(lhsExpr, refVars)) + return LHS; + + return EvalVal(C->getRHS(), refVars); + } + + // Accesses to members are potential references to data on the stack. + case Stmt::MemberExprClass: { + MemberExpr *M = cast<MemberExpr>(E); + + // Check for indirect access. We only want direct field accesses. + if (M->isArrow()) + return NULL; + + // Check whether the member type is itself a reference, in which case + // we're not going to refer to the member, but to what the member refers to. + if (M->getMemberDecl()->getType()->isReferenceType()) + return NULL; + + return EvalVal(M->getBase(), refVars); + } + + default: + // Check that we don't return or take the address of a reference to a + // temporary. This is only useful in C++. + if (!E->isTypeDependent() && E->isRValue()) + return E; + + // Everything else: we simply don't reason about them. + return NULL; + } +} while (true); +} + +//===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// + +/// Check for comparisons of floating point operands using != and ==. +/// Issue a warning if these are no self-comparisons, as they are not likely +/// to do what the programmer intended. +void Sema::CheckFloatComparison(SourceLocation loc, Expr* lex, Expr *rex) { + bool EmitWarning = true; + + Expr* LeftExprSansParen = lex->IgnoreParenImpCasts(); + Expr* RightExprSansParen = rex->IgnoreParenImpCasts(); + + // Special case: check for x == x (which is OK). + // Do not emit warnings for such cases. + if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LeftExprSansParen)) + if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RightExprSansParen)) + if (DRL->getDecl() == DRR->getDecl()) + EmitWarning = false; + + + // Special case: check for comparisons against literals that can be exactly + // represented by APFloat. In such cases, do not emit a warning. This + // is a heuristic: often comparison against such literals are used to + // detect if a value in a variable has not changed. This clearly can + // lead to false negatives. + if (EmitWarning) { + if (FloatingLiteral* FLL = dyn_cast<FloatingLiteral>(LeftExprSansParen)) { + if (FLL->isExact()) + EmitWarning = false; + } else + if (FloatingLiteral* FLR = dyn_cast<FloatingLiteral>(RightExprSansParen)){ + if (FLR->isExact()) + EmitWarning = false; + } + } + + // Check for comparisons with builtin types. + if (EmitWarning) + if (CallExpr* CL = dyn_cast<CallExpr>(LeftExprSansParen)) + if (CL->isBuiltinCall(Context)) + EmitWarning = false; + + if (EmitWarning) + if (CallExpr* CR = dyn_cast<CallExpr>(RightExprSansParen)) + if (CR->isBuiltinCall(Context)) + EmitWarning = false; + + // Emit the diagnostic. + if (EmitWarning) + Diag(loc, diag::warn_floatingpoint_eq) + << lex->getSourceRange() << rex->getSourceRange(); +} + +//===--- CHECK: Integer mixed-sign comparisons (-Wsign-compare) --------===// +//===--- CHECK: Lossy implicit conversions (-Wconversion) --------------===// + +namespace { + +/// Structure recording the 'active' range of an integer-valued +/// expression. +struct IntRange { + /// The number of bits active in the int. + unsigned Width; + + /// True if the int is known not to have negative values. + bool NonNegative; + + IntRange(unsigned Width, bool NonNegative) + : Width(Width), NonNegative(NonNegative) + {} + + /// Returns the range of the bool type. + static IntRange forBoolType() { + return IntRange(1, true); + } + + /// Returns the range of an opaque value of the given integral type. + static IntRange forValueOfType(ASTContext &C, QualType T) { + return forValueOfCanonicalType(C, + T->getCanonicalTypeInternal().getTypePtr()); + } + + /// Returns the range of an opaque value of a canonical integral type. + static IntRange forValueOfCanonicalType(ASTContext &C, const Type *T) { + assert(T->isCanonicalUnqualified()); + + if (const VectorType *VT = dyn_cast<VectorType>(T)) + T = VT->getElementType().getTypePtr(); + if (const ComplexType *CT = dyn_cast<ComplexType>(T)) + T = CT->getElementType().getTypePtr(); + + // For enum types, use the known bit width of the enumerators. + if (const EnumType *ET = dyn_cast<EnumType>(T)) { + EnumDecl *Enum = ET->getDecl(); + if (!Enum->isDefinition()) + return IntRange(C.getIntWidth(QualType(T, 0)), false); + + unsigned NumPositive = Enum->getNumPositiveBits(); + unsigned NumNegative = Enum->getNumNegativeBits(); + + return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0); + } + + const BuiltinType *BT = cast<BuiltinType>(T); + assert(BT->isInteger()); + + return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger()); + } + + /// Returns the "target" range of a canonical integral type, i.e. + /// the range of values expressible in the type. + /// + /// This matches forValueOfCanonicalType except that enums have the + /// full range of their type, not the range of their enumerators. + static IntRange forTargetOfCanonicalType(ASTContext &C, const Type *T) { + assert(T->isCanonicalUnqualified()); + + if (const VectorType *VT = dyn_cast<VectorType>(T)) + T = VT->getElementType().getTypePtr(); + if (const ComplexType *CT = dyn_cast<ComplexType>(T)) + T = CT->getElementType().getTypePtr(); + if (const EnumType *ET = dyn_cast<EnumType>(T)) + T = ET->getDecl()->getIntegerType().getTypePtr(); + + const BuiltinType *BT = cast<BuiltinType>(T); + assert(BT->isInteger()); + + return IntRange(C.getIntWidth(QualType(T, 0)), BT->isUnsignedInteger()); + } + + /// Returns the supremum of two ranges: i.e. their conservative merge. + static IntRange join(IntRange L, IntRange R) { + return IntRange(std::max(L.Width, R.Width), + L.NonNegative && R.NonNegative); + } + + /// Returns the infinum of two ranges: i.e. their aggressive merge. + static IntRange meet(IntRange L, IntRange R) { + return IntRange(std::min(L.Width, R.Width), + L.NonNegative || R.NonNegative); + } +}; + +IntRange GetValueRange(ASTContext &C, llvm::APSInt &value, unsigned MaxWidth) { + if (value.isSigned() && value.isNegative()) + return IntRange(value.getMinSignedBits(), false); + + if (value.getBitWidth() > MaxWidth) + value = value.trunc(MaxWidth); + + // isNonNegative() just checks the sign bit without considering + // signedness. + return IntRange(value.getActiveBits(), true); +} + +IntRange GetValueRange(ASTContext &C, APValue &result, QualType Ty, + unsigned MaxWidth) { + if (result.isInt()) + return GetValueRange(C, result.getInt(), MaxWidth); + + if (result.isVector()) { + IntRange R = GetValueRange(C, result.getVectorElt(0), Ty, MaxWidth); + for (unsigned i = 1, e = result.getVectorLength(); i != e; ++i) { + IntRange El = GetValueRange(C, result.getVectorElt(i), Ty, MaxWidth); + R = IntRange::join(R, El); + } + return R; + } + + if (result.isComplexInt()) { + IntRange R = GetValueRange(C, result.getComplexIntReal(), MaxWidth); + IntRange I = GetValueRange(C, result.getComplexIntImag(), MaxWidth); + return IntRange::join(R, I); + } + + // This can happen with lossless casts to intptr_t of "based" lvalues. + // Assume it might use arbitrary bits. + // FIXME: The only reason we need to pass the type in here is to get + // the sign right on this one case. It would be nice if APValue + // preserved this. + assert(result.isLValue()); + return IntRange(MaxWidth, Ty->isUnsignedIntegerOrEnumerationType()); +} + +/// Pseudo-evaluate the given integer expression, estimating the +/// range of values it might take. +/// +/// \param MaxWidth - the width to which the value will be truncated +IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { + E = E->IgnoreParens(); + + // Try a full evaluation first. + Expr::EvalResult result; + if (E->Evaluate(result, C)) + return GetValueRange(C, result.Val, E->getType(), MaxWidth); + + // I think we only want to look through implicit casts here; if the + // user has an explicit widening cast, we should treat the value as + // being of the new, wider type. + if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) { + if (CE->getCastKind() == CK_NoOp) + return GetExprRange(C, CE->getSubExpr(), MaxWidth); + + IntRange OutputTypeRange = IntRange::forValueOfType(C, CE->getType()); + + bool isIntegerCast = (CE->getCastKind() == CK_IntegralCast); + + // Assume that non-integer casts can span the full range of the type. + if (!isIntegerCast) + return OutputTypeRange; + + IntRange SubRange + = GetExprRange(C, CE->getSubExpr(), + std::min(MaxWidth, OutputTypeRange.Width)); + + // Bail out if the subexpr's range is as wide as the cast type. + if (SubRange.Width >= OutputTypeRange.Width) + return OutputTypeRange; + + // Otherwise, we take the smaller width, and we're non-negative if + // either the output type or the subexpr is. + return IntRange(SubRange.Width, + SubRange.NonNegative || OutputTypeRange.NonNegative); + } + + if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { + // If we can fold the condition, just take that operand. + bool CondResult; + if (CO->getCond()->EvaluateAsBooleanCondition(CondResult, C)) + return GetExprRange(C, CondResult ? CO->getTrueExpr() + : CO->getFalseExpr(), + MaxWidth); + + // Otherwise, conservatively merge. + IntRange L = GetExprRange(C, CO->getTrueExpr(), MaxWidth); + IntRange R = GetExprRange(C, CO->getFalseExpr(), MaxWidth); + return IntRange::join(L, R); + } + + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + switch (BO->getOpcode()) { + + // Boolean-valued operations are single-bit and positive. + case BO_LAnd: + case BO_LOr: + case BO_LT: + case BO_GT: + case BO_LE: + case BO_GE: + case BO_EQ: + case BO_NE: + return IntRange::forBoolType(); + + // The type of these compound assignments is the type of the LHS, + // so the RHS is not necessarily an integer. + case BO_MulAssign: + case BO_DivAssign: + case BO_RemAssign: + case BO_AddAssign: + case BO_SubAssign: + return IntRange::forValueOfType(C, E->getType()); + + // Operations with opaque sources are black-listed. + case BO_PtrMemD: + case BO_PtrMemI: + return IntRange::forValueOfType(C, E->getType()); + + // Bitwise-and uses the *infinum* of the two source ranges. + case BO_And: + case BO_AndAssign: + return IntRange::meet(GetExprRange(C, BO->getLHS(), MaxWidth), + GetExprRange(C, BO->getRHS(), MaxWidth)); + + // Left shift gets black-listed based on a judgement call. + case BO_Shl: + // ...except that we want to treat '1 << (blah)' as logically + // positive. It's an important idiom. + if (IntegerLiteral *I + = dyn_cast<IntegerLiteral>(BO->getLHS()->IgnoreParenCasts())) { + if (I->getValue() == 1) { + IntRange R = IntRange::forValueOfType(C, E->getType()); + return IntRange(R.Width, /*NonNegative*/ true); + } + } + // fallthrough + + case BO_ShlAssign: + return IntRange::forValueOfType(C, E->getType()); + + // Right shift by a constant can narrow its left argument. + case BO_Shr: + case BO_ShrAssign: { + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); + + // If the shift amount is a positive constant, drop the width by + // that much. + llvm::APSInt shift; + if (BO->getRHS()->isIntegerConstantExpr(shift, C) && + shift.isNonNegative()) { + unsigned zext = shift.getZExtValue(); + if (zext >= L.Width) + L.Width = (L.NonNegative ? 0 : 1); + else + L.Width -= zext; + } + + return L; + } + + // Comma acts as its right operand. + case BO_Comma: + return GetExprRange(C, BO->getRHS(), MaxWidth); + + // Black-list pointer subtractions. + case BO_Sub: + if (BO->getLHS()->getType()->isPointerType()) + return IntRange::forValueOfType(C, E->getType()); + // fallthrough + + default: + break; + } + + // Treat every other operator as if it were closed on the + // narrowest type that encompasses both operands. + IntRange L = GetExprRange(C, BO->getLHS(), MaxWidth); + IntRange R = GetExprRange(C, BO->getRHS(), MaxWidth); + return IntRange::join(L, R); + } + + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { + switch (UO->getOpcode()) { + // Boolean-valued operations are white-listed. + case UO_LNot: + return IntRange::forBoolType(); + + // Operations with opaque sources are black-listed. + case UO_Deref: + case UO_AddrOf: // should be impossible + return IntRange::forValueOfType(C, E->getType()); + + default: + return GetExprRange(C, UO->getSubExpr(), MaxWidth); + } + } + + if (dyn_cast<OffsetOfExpr>(E)) { + IntRange::forValueOfType(C, E->getType()); + } + + FieldDecl *BitField = E->getBitField(); + if (BitField) { + llvm::APSInt BitWidthAP = BitField->getBitWidth()->EvaluateAsInt(C); + unsigned BitWidth = BitWidthAP.getZExtValue(); + + return IntRange(BitWidth, + BitField->getType()->isUnsignedIntegerOrEnumerationType()); + } + + return IntRange::forValueOfType(C, E->getType()); +} + +IntRange GetExprRange(ASTContext &C, Expr *E) { + return GetExprRange(C, E, C.getIntWidth(E->getType())); +} + +/// Checks whether the given value, which currently has the given +/// source semantics, has the same value when coerced through the +/// target semantics. +bool IsSameFloatAfterCast(const llvm::APFloat &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { + llvm::APFloat truncated = value; + + bool ignored; + truncated.convert(Src, llvm::APFloat::rmNearestTiesToEven, &ignored); + truncated.convert(Tgt, llvm::APFloat::rmNearestTiesToEven, &ignored); + + return truncated.bitwiseIsEqual(value); +} + +/// Checks whether the given value, which currently has the given +/// source semantics, has the same value when coerced through the +/// target semantics. +/// +/// The value might be a vector of floats (or a complex number). +bool IsSameFloatAfterCast(const APValue &value, + const llvm::fltSemantics &Src, + const llvm::fltSemantics &Tgt) { + if (value.isFloat()) + return IsSameFloatAfterCast(value.getFloat(), Src, Tgt); + + if (value.isVector()) { + for (unsigned i = 0, e = value.getVectorLength(); i != e; ++i) + if (!IsSameFloatAfterCast(value.getVectorElt(i), Src, Tgt)) + return false; + return true; + } + + assert(value.isComplexFloat()); + return (IsSameFloatAfterCast(value.getComplexFloatReal(), Src, Tgt) && + IsSameFloatAfterCast(value.getComplexFloatImag(), Src, Tgt)); +} + +void AnalyzeImplicitConversions(Sema &S, Expr *E, SourceLocation CC); + +static bool IsZero(Sema &S, Expr *E) { + // Suppress cases where we are comparing against an enum constant. + if (const DeclRefExpr *DR = + dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) + if (isa<EnumConstantDecl>(DR->getDecl())) + return false; + + // Suppress cases where the '0' value is expanded from a macro. + if (E->getLocStart().isMacroID()) + return false; + + llvm::APSInt Value; + return E->isIntegerConstantExpr(Value, S.Context) && Value == 0; +} + +static bool HasEnumType(Expr *E) { + // Strip off implicit integral promotions. + while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + if (ICE->getCastKind() != CK_IntegralCast && + ICE->getCastKind() != CK_NoOp) + break; + E = ICE->getSubExpr(); + } + + return E->getType()->isEnumeralType(); +} + +void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { + BinaryOperatorKind op = E->getOpcode(); + if (E->isValueDependent()) + return; + + if (op == BO_LT && IsZero(S, E->getRHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) + << "< 0" << "false" << HasEnumType(E->getLHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } else if (op == BO_GE && IsZero(S, E->getRHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_lunsigned_always_true_comparison) + << ">= 0" << "true" << HasEnumType(E->getLHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } else if (op == BO_GT && IsZero(S, E->getLHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) + << "0 >" << "false" << HasEnumType(E->getRHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } else if (op == BO_LE && IsZero(S, E->getLHS())) { + S.Diag(E->getOperatorLoc(), diag::warn_runsigned_always_true_comparison) + << "0 <=" << "true" << HasEnumType(E->getRHS()) + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + } +} + +/// Analyze the operands of the given comparison. Implements the +/// fallback case from AnalyzeComparison. +void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { + AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); + AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); +} + +/// \brief Implements -Wsign-compare. +/// +/// \param lex the left-hand expression +/// \param rex the right-hand expression +/// \param OpLoc the location of the joining operator +/// \param BinOpc binary opcode or 0 +void AnalyzeComparison(Sema &S, BinaryOperator *E) { + // The type the comparison is being performed in. + QualType T = E->getLHS()->getType(); + assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()) + && "comparison with mismatched types"); + + // We don't do anything special if this isn't an unsigned integral + // comparison: we're only interested in integral comparisons, and + // signed comparisons only happen in cases we don't care to warn about. + // + // We also don't care about value-dependent expressions or expressions + // whose result is a constant. + if (!T->hasUnsignedIntegerRepresentation() + || E->isValueDependent() || E->isIntegerConstantExpr(S.Context)) + return AnalyzeImpConvsInComparison(S, E); + + Expr *lex = E->getLHS()->IgnoreParenImpCasts(); + Expr *rex = E->getRHS()->IgnoreParenImpCasts(); + + // Check to see if one of the (unmodified) operands is of different + // signedness. + Expr *signedOperand, *unsignedOperand; + if (lex->getType()->hasSignedIntegerRepresentation()) { + assert(!rex->getType()->hasSignedIntegerRepresentation() && + "unsigned comparison between two signed integer expressions?"); + signedOperand = lex; + unsignedOperand = rex; + } else if (rex->getType()->hasSignedIntegerRepresentation()) { + signedOperand = rex; + unsignedOperand = lex; + } else { + CheckTrivialUnsignedComparison(S, E); + return AnalyzeImpConvsInComparison(S, E); + } + + // Otherwise, calculate the effective range of the signed operand. + IntRange signedRange = GetExprRange(S.Context, signedOperand); + + // Go ahead and analyze implicit conversions in the operands. Note + // that we skip the implicit conversions on both sides. + AnalyzeImplicitConversions(S, lex, E->getOperatorLoc()); + AnalyzeImplicitConversions(S, rex, E->getOperatorLoc()); + + // If the signed range is non-negative, -Wsign-compare won't fire, + // but we should still check for comparisons which are always true + // or false. + if (signedRange.NonNegative) + return CheckTrivialUnsignedComparison(S, E); + + // For (in)equality comparisons, if the unsigned operand is a + // constant which cannot collide with a overflowed signed operand, + // then reinterpreting the signed operand as unsigned will not + // change the result of the comparison. + if (E->isEqualityOp()) { + unsigned comparisonWidth = S.Context.getIntWidth(T); + IntRange unsignedRange = GetExprRange(S.Context, unsignedOperand); + + // We should never be unable to prove that the unsigned operand is + // non-negative. + assert(unsignedRange.NonNegative && "unsigned range includes negative?"); + + if (unsignedRange.Width < comparisonWidth) + return; + } + + S.Diag(E->getOperatorLoc(), diag::warn_mixed_sign_comparison) + << lex->getType() << rex->getType() + << lex->getSourceRange() << rex->getSourceRange(); +} + +/// Analyzes an attempt to assign the given value to a bitfield. +/// +/// Returns true if there was something fishy about the attempt. +bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, + SourceLocation InitLoc) { + assert(Bitfield->isBitField()); + if (Bitfield->isInvalidDecl()) + return false; + + // White-list bool bitfields. + if (Bitfield->getType()->isBooleanType()) + return false; + + // Ignore value- or type-dependent expressions. + if (Bitfield->getBitWidth()->isValueDependent() || + Bitfield->getBitWidth()->isTypeDependent() || + Init->isValueDependent() || + Init->isTypeDependent()) + return false; + + Expr *OriginalInit = Init->IgnoreParenImpCasts(); + + llvm::APSInt Width(32); + Expr::EvalResult InitValue; + if (!Bitfield->getBitWidth()->isIntegerConstantExpr(Width, S.Context) || + !OriginalInit->Evaluate(InitValue, S.Context) || + !InitValue.Val.isInt()) + return false; + + const llvm::APSInt &Value = InitValue.Val.getInt(); + unsigned OriginalWidth = Value.getBitWidth(); + unsigned FieldWidth = Width.getZExtValue(); + + if (OriginalWidth <= FieldWidth) + return false; + + llvm::APSInt TruncatedValue = Value.trunc(FieldWidth); + + // It's fairly common to write values into signed bitfields + // that, if sign-extended, would end up becoming a different + // value. We don't want to warn about that. + if (Value.isSigned() && Value.isNegative()) + TruncatedValue = TruncatedValue.sext(OriginalWidth); + else + TruncatedValue = TruncatedValue.zext(OriginalWidth); + + if (Value == TruncatedValue) + return false; + + std::string PrettyValue = Value.toString(10); + std::string PrettyTrunc = TruncatedValue.toString(10); + + S.Diag(InitLoc, diag::warn_impcast_bitfield_precision_constant) + << PrettyValue << PrettyTrunc << OriginalInit->getType() + << Init->getSourceRange(); + + return true; +} + +/// Analyze the given simple or compound assignment for warning-worthy +/// operations. +void AnalyzeAssignment(Sema &S, BinaryOperator *E) { + // Just recurse on the LHS. + AnalyzeImplicitConversions(S, E->getLHS(), E->getOperatorLoc()); + + // We want to recurse on the RHS as normal unless we're assigning to + // a bitfield. + if (FieldDecl *Bitfield = E->getLHS()->getBitField()) { + if (AnalyzeBitFieldAssignment(S, Bitfield, E->getRHS(), + E->getOperatorLoc())) { + // Recurse, ignoring any implicit conversions on the RHS. + return AnalyzeImplicitConversions(S, E->getRHS()->IgnoreParenImpCasts(), + E->getOperatorLoc()); + } + } + + AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); +} + +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag) { + S.Diag(E->getExprLoc(), diag) + << SourceType << T << E->getSourceRange() << SourceRange(CContext); +} + +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, + unsigned diag) { + DiagnoseImpCast(S, E, E->getType(), T, CContext, diag); +} + +/// Diagnose an implicit cast from a literal expression. Also attemps to supply +/// fixit hints when the cast wouldn't lose information to simply write the +/// expression with the expected type. +void DiagnoseFloatingLiteralImpCast(Sema &S, FloatingLiteral *FL, QualType T, + SourceLocation CContext) { + // Emit the primary warning first, then try to emit a fixit hint note if + // reasonable. + S.Diag(FL->getExprLoc(), diag::warn_impcast_literal_float_to_integer) + << FL->getType() << T << FL->getSourceRange() << SourceRange(CContext); + + const llvm::APFloat &Value = FL->getValue(); + + // Don't attempt to fix PPC double double literals. + if (&Value.getSemantics() == &llvm::APFloat::PPCDoubleDouble) + return; + + // Try to convert this exactly to an 64-bit integer. FIXME: It would be + // nice to support arbitrarily large integers here. + bool isExact = false; + uint64_t IntegerPart; + if (Value.convertToInteger(&IntegerPart, 64, /*isSigned=*/true, + llvm::APFloat::rmTowardZero, &isExact) + != llvm::APFloat::opOK || !isExact) + return; + + llvm::APInt IntegerValue(64, IntegerPart, /*isSigned=*/true); + + std::string LiteralValue = IntegerValue.toString(10, /*isSigned=*/true); + S.Diag(FL->getExprLoc(), diag::note_fix_integral_float_as_integer) + << FixItHint::CreateReplacement(FL->getSourceRange(), LiteralValue); +} + +std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { + if (!Range.Width) return "0"; + + llvm::APSInt ValueInRange = Value; + ValueInRange.setIsSigned(!Range.NonNegative); + ValueInRange = ValueInRange.trunc(Range.Width); + return ValueInRange.toString(10); +} + +static bool isFromSystemMacro(Sema &S, SourceLocation loc) { + SourceManager &smgr = S.Context.getSourceManager(); + return loc.isMacroID() && smgr.isInSystemHeader(smgr.getSpellingLoc(loc)); +} + +void CheckImplicitConversion(Sema &S, Expr *E, QualType T, + SourceLocation CC, bool *ICContext = 0) { + if (E->isTypeDependent() || E->isValueDependent()) return; + + const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr(); + const Type *Target = S.Context.getCanonicalType(T).getTypePtr(); + if (Source == Target) return; + if (Target->isDependentType()) return; + + // If the conversion context location is invalid don't complain. + // We also don't want to emit a warning if the issue occurs from the + // instantiation of a system macro. The problem is that 'getSpellingLoc()' + // is slow, so we delay this check as long as possible. Once we detect + // we are in that scenario, we just return. + if (CC.isInvalid()) + return; + + // Never diagnose implicit casts to bool. + if (Target->isSpecificBuiltinType(BuiltinType::Bool)) + return; + + // Strip vector types. + if (isa<VectorType>(Source)) { + if (!isa<VectorType>(Target)) { + if (isFromSystemMacro(S, CC)) + return; + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); + } + + Source = cast<VectorType>(Source)->getElementType().getTypePtr(); + Target = cast<VectorType>(Target)->getElementType().getTypePtr(); + } + + // Strip complex types. + if (isa<ComplexType>(Source)) { + if (!isa<ComplexType>(Target)) { + if (isFromSystemMacro(S, CC)) + return; + + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_complex_scalar); + } + + Source = cast<ComplexType>(Source)->getElementType().getTypePtr(); + Target = cast<ComplexType>(Target)->getElementType().getTypePtr(); + } + + const BuiltinType *SourceBT = dyn_cast<BuiltinType>(Source); + const BuiltinType *TargetBT = dyn_cast<BuiltinType>(Target); + + // If the source is floating point... + if (SourceBT && SourceBT->isFloatingPoint()) { + // ...and the target is floating point... + if (TargetBT && TargetBT->isFloatingPoint()) { + // ...then warn if we're dropping FP rank. + + // Builtin FP kinds are ordered by increasing FP rank. + if (SourceBT->getKind() > TargetBT->getKind()) { + // Don't warn about float constants that are precisely + // representable in the target type. + Expr::EvalResult result; + if (E->Evaluate(result, S.Context)) { + // Value might be a float, a float vector, or a float complex. + if (IsSameFloatAfterCast(result.Val, + S.Context.getFloatTypeSemantics(QualType(TargetBT, 0)), + S.Context.getFloatTypeSemantics(QualType(SourceBT, 0)))) + return; + } + + if (isFromSystemMacro(S, CC)) + return; + + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_precision); + } + return; + } + + // If the target is integral, always warn. + if ((TargetBT && TargetBT->isInteger())) { + if (isFromSystemMacro(S, CC)) + return; + + Expr *InnerE = E->IgnoreParenImpCasts(); + if (FloatingLiteral *FL = dyn_cast<FloatingLiteral>(InnerE)) { + DiagnoseFloatingLiteralImpCast(S, FL, T, CC); + } else { + DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_float_integer); + } + } + + return; + } + + if (!Source->isIntegerType() || !Target->isIntegerType()) + return; + + if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) + == Expr::NPCK_GNUNull) && Target->isIntegerType()) { + S.Diag(E->getExprLoc(), diag::warn_impcast_null_pointer_to_integer) + << E->getSourceRange() << clang::SourceRange(CC); + return; + } + + IntRange SourceRange = GetExprRange(S.Context, E); + IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target); + + if (SourceRange.Width > TargetRange.Width) { + // If the source is a constant, use a default-on diagnostic. + // TODO: this should happen for bitfield stores, too. + llvm::APSInt Value(32); + if (E->isIntegerConstantExpr(Value, S.Context)) { + if (isFromSystemMacro(S, CC)) + return; + + std::string PrettySourceValue = Value.toString(10); + std::string PrettyTargetValue = PrettyPrintInRange(Value, TargetRange); + + S.Diag(E->getExprLoc(), diag::warn_impcast_integer_precision_constant) + << PrettySourceValue << PrettyTargetValue + << E->getType() << T << E->getSourceRange() << clang::SourceRange(CC); + return; + } + + // People want to build with -Wshorten-64-to-32 and not -Wconversion + // and by god we'll let them. + + if (isFromSystemMacro(S, CC)) + return; + + if (SourceRange.Width == 64 && TargetRange.Width == 32) + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32); + return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_precision); + } + + if ((TargetRange.NonNegative && !SourceRange.NonNegative) || + (!TargetRange.NonNegative && SourceRange.NonNegative && + SourceRange.Width == TargetRange.Width)) { + + if (isFromSystemMacro(S, CC)) + return; + + unsigned DiagID = diag::warn_impcast_integer_sign; + + // Traditionally, gcc has warned about this under -Wsign-compare. + // We also want to warn about it in -Wconversion. + // So if -Wconversion is off, use a completely identical diagnostic + // in the sign-compare group. + // The conditional-checking code will + if (ICContext) { + DiagID = diag::warn_impcast_integer_sign_conditional; + *ICContext = true; + } + + return DiagnoseImpCast(S, E, T, CC, DiagID); + } + + // Diagnose conversions between different enumeration types. + // In C, we pretend that the type of an EnumConstantDecl is its enumeration + // type, to give us better diagnostics. + QualType SourceType = E->getType(); + if (!S.getLangOptions().CPlusPlus) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + if (EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext()); + SourceType = S.Context.getTypeDeclType(Enum); + Source = S.Context.getCanonicalType(SourceType).getTypePtr(); + } + } + + if (const EnumType *SourceEnum = Source->getAs<EnumType>()) + if (const EnumType *TargetEnum = Target->getAs<EnumType>()) + if ((SourceEnum->getDecl()->getIdentifier() || + SourceEnum->getDecl()->getTypedefNameForAnonDecl()) && + (TargetEnum->getDecl()->getIdentifier() || + TargetEnum->getDecl()->getTypedefNameForAnonDecl()) && + SourceEnum != TargetEnum) { + if (isFromSystemMacro(S, CC)) + return; + + return DiagnoseImpCast(S, E, SourceType, T, CC, + diag::warn_impcast_different_enum_types); + } + + return; +} + +void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T); + +void CheckConditionalOperand(Sema &S, Expr *E, QualType T, + SourceLocation CC, bool &ICContext) { + E = E->IgnoreParenImpCasts(); + + if (isa<ConditionalOperator>(E)) + return CheckConditionalOperator(S, cast<ConditionalOperator>(E), T); + + AnalyzeImplicitConversions(S, E, CC); + if (E->getType() != T) + return CheckImplicitConversion(S, E, T, CC, &ICContext); + return; +} + +void CheckConditionalOperator(Sema &S, ConditionalOperator *E, QualType T) { + SourceLocation CC = E->getQuestionLoc(); + + AnalyzeImplicitConversions(S, E->getCond(), CC); + + bool Suspicious = false; + CheckConditionalOperand(S, E->getTrueExpr(), T, CC, Suspicious); + CheckConditionalOperand(S, E->getFalseExpr(), T, CC, Suspicious); + + // If -Wconversion would have warned about either of the candidates + // for a signedness conversion to the context type... + if (!Suspicious) return; + + // ...but it's currently ignored... + if (S.Diags.getDiagnosticLevel(diag::warn_impcast_integer_sign_conditional, + CC)) + return; + + // ...and -Wsign-compare isn't... + if (!S.Diags.getDiagnosticLevel(diag::warn_mixed_sign_conditional, CC)) + return; + + // ...then check whether it would have warned about either of the + // candidates for a signedness conversion to the condition type. + if (E->getType() != T) { + Suspicious = false; + CheckImplicitConversion(S, E->getTrueExpr()->IgnoreParenImpCasts(), + E->getType(), CC, &Suspicious); + if (!Suspicious) + CheckImplicitConversion(S, E->getFalseExpr()->IgnoreParenImpCasts(), + E->getType(), CC, &Suspicious); + if (!Suspicious) + return; + } + + // If so, emit a diagnostic under -Wsign-compare. + Expr *lex = E->getTrueExpr()->IgnoreParenImpCasts(); + Expr *rex = E->getFalseExpr()->IgnoreParenImpCasts(); + S.Diag(E->getQuestionLoc(), diag::warn_mixed_sign_conditional) + << lex->getType() << rex->getType() + << lex->getSourceRange() << rex->getSourceRange(); +} + +/// AnalyzeImplicitConversions - Find and report any interesting +/// implicit conversions in the given expression. There are a couple +/// of competing diagnostics here, -Wconversion and -Wsign-compare. +void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { + QualType T = OrigE->getType(); + Expr *E = OrigE->IgnoreParenImpCasts(); + + // For conditional operators, we analyze the arguments as if they + // were being fed directly into the output. + if (isa<ConditionalOperator>(E)) { + ConditionalOperator *CO = cast<ConditionalOperator>(E); + CheckConditionalOperator(S, CO, T); + return; + } + + // Go ahead and check any implicit conversions we might have skipped. + // The non-canonical typecheck is just an optimization; + // CheckImplicitConversion will filter out dead implicit conversions. + if (E->getType() != T) + CheckImplicitConversion(S, E, T, CC); + + // Now continue drilling into this expression. + + // Skip past explicit casts. + if (isa<ExplicitCastExpr>(E)) { + E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts(); + return AnalyzeImplicitConversions(S, E, CC); + } + + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + // Do a somewhat different check with comparison operators. + if (BO->isComparisonOp()) + return AnalyzeComparison(S, BO); + + // And with assignments and compound assignments. + if (BO->isAssignmentOp()) + return AnalyzeAssignment(S, BO); + } + + // These break the otherwise-useful invariant below. Fortunately, + // we don't really need to recurse into them, because any internal + // expressions should have been analyzed already when they were + // built into statements. + if (isa<StmtExpr>(E)) return; + + // Don't descend into unevaluated contexts. + if (isa<UnaryExprOrTypeTraitExpr>(E)) return; + + // Now just recurse over the expression's children. + CC = E->getExprLoc(); + for (Stmt::child_range I = E->children(); I; ++I) + AnalyzeImplicitConversions(S, cast<Expr>(*I), CC); +} + +} // end anonymous namespace + +/// Diagnoses "dangerous" implicit conversions within the given +/// expression (which is a full expression). Implements -Wconversion +/// and -Wsign-compare. +/// +/// \param CC the "context" location of the implicit conversion, i.e. +/// the most location of the syntactic entity requiring the implicit +/// conversion +void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { + // Don't diagnose in unevaluated contexts. + if (ExprEvalContexts.back().Context == Sema::Unevaluated) + return; + + // Don't diagnose for value- or type-dependent expressions. + if (E->isTypeDependent() || E->isValueDependent()) + return; + + // This is not the right CC for (e.g.) a variable initialization. + AnalyzeImplicitConversions(*this, E, CC); +} + +void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, + FieldDecl *BitField, + Expr *Init) { + (void) AnalyzeBitFieldAssignment(*this, BitField, Init, InitLoc); +} + +/// CheckParmsForFunctionDef - Check that the parameters of the given +/// function are appropriate for the definition of a function. This +/// takes care of any checks that cannot be performed on the +/// declaration itself, e.g., that the types of each of the function +/// parameters are complete. +bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, + bool CheckParameterNames) { + bool HasInvalidParm = false; + for (; P != PEnd; ++P) { + ParmVarDecl *Param = *P; + + // C99 6.7.5.3p4: the parameters in a parameter type list in a + // function declarator that is part of a function definition of + // that function shall not have incomplete type. + // + // This is also C++ [dcl.fct]p6. + if (!Param->isInvalidDecl() && + RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) { + Param->setInvalidDecl(); + HasInvalidParm = true; + } + + // C99 6.9.1p5: If the declarator includes a parameter type list, the + // declaration of each parameter shall include an identifier. + if (CheckParameterNames && + Param->getIdentifier() == 0 && + !Param->isImplicit() && + !getLangOptions().CPlusPlus) + Diag(Param->getLocation(), diag::err_parameter_name_omitted); + + // C99 6.7.5.3p12: + // If the function declarator is not part of a definition of that + // function, parameters may have incomplete type and may use the [*] + // notation in their sequences of declarator specifiers to specify + // variable length array types. + QualType PType = Param->getOriginalType(); + if (const ArrayType *AT = Context.getAsArrayType(PType)) { + if (AT->getSizeModifier() == ArrayType::Star) { + // FIXME: This diagnosic should point the the '[*]' if source-location + // information is added for it. + Diag(Param->getLocation(), diag::err_array_star_in_function_definition); + } + } + } + + return HasInvalidParm; +} + +/// CheckCastAlign - Implements -Wcast-align, which warns when a +/// pointer cast increases the alignment requirements. +void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { + // This is actually a lot of work to potentially be doing on every + // cast; don't do it if we're ignoring -Wcast_align (as is the default). + if (getDiagnostics().getDiagnosticLevel(diag::warn_cast_align, + TRange.getBegin()) + == Diagnostic::Ignored) + return; + + // Ignore dependent types. + if (T->isDependentType() || Op->getType()->isDependentType()) + return; + + // Require that the destination be a pointer type. + const PointerType *DestPtr = T->getAs<PointerType>(); + if (!DestPtr) return; + + // If the destination has alignment 1, we're done. + QualType DestPointee = DestPtr->getPointeeType(); + if (DestPointee->isIncompleteType()) return; + CharUnits DestAlign = Context.getTypeAlignInChars(DestPointee); + if (DestAlign.isOne()) return; + + // Require that the source be a pointer type. + const PointerType *SrcPtr = Op->getType()->getAs<PointerType>(); + if (!SrcPtr) return; + QualType SrcPointee = SrcPtr->getPointeeType(); + + // Whitelist casts from cv void*. We already implicitly + // whitelisted casts to cv void*, since they have alignment 1. + // Also whitelist casts involving incomplete types, which implicitly + // includes 'void'. + if (SrcPointee->isIncompleteType()) return; + + CharUnits SrcAlign = Context.getTypeAlignInChars(SrcPointee); + if (SrcAlign >= DestAlign) return; + + Diag(TRange.getBegin(), diag::warn_cast_align) + << Op->getType() << T + << static_cast<unsigned>(SrcAlign.getQuantity()) + << static_cast<unsigned>(DestAlign.getQuantity()) + << TRange << Op->getSourceRange(); +} + +static void CheckArrayAccess_Check(Sema &S, + const clang::ArraySubscriptExpr *E) { + const Expr *BaseExpr = E->getBase()->IgnoreParenImpCasts(); + const ConstantArrayType *ArrayTy = + S.Context.getAsConstantArrayType(BaseExpr->getType()); + if (!ArrayTy) + return; + + const Expr *IndexExpr = E->getIdx(); + if (IndexExpr->isValueDependent()) + return; + llvm::APSInt index; + if (!IndexExpr->isIntegerConstantExpr(index, S.Context)) + return; + + if (index.isUnsigned() || !index.isNegative()) { + llvm::APInt size = ArrayTy->getSize(); + if (!size.isStrictlyPositive()) + return; + if (size.getBitWidth() > index.getBitWidth()) + index = index.sext(size.getBitWidth()); + else if (size.getBitWidth() < index.getBitWidth()) + size = size.sext(index.getBitWidth()); + + if (index.slt(size)) + return; + + S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + S.PDiag(diag::warn_array_index_exceeds_bounds) + << index.toString(10, true) + << size.toString(10, true) + << IndexExpr->getSourceRange()); + } else { + S.DiagRuntimeBehavior(E->getBase()->getLocStart(), BaseExpr, + S.PDiag(diag::warn_array_index_precedes_bounds) + << index.toString(10, true) + << IndexExpr->getSourceRange()); + } + + const NamedDecl *ND = NULL; + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BaseExpr)) + ND = dyn_cast<NamedDecl>(DRE->getDecl()); + if (const MemberExpr *ME = dyn_cast<MemberExpr>(BaseExpr)) + ND = dyn_cast<NamedDecl>(ME->getMemberDecl()); + if (ND) + S.DiagRuntimeBehavior(ND->getLocStart(), BaseExpr, + S.PDiag(diag::note_array_index_out_of_bounds) + << ND->getDeclName()); +} + +void Sema::CheckArrayAccess(const Expr *expr) { + while (true) { + expr = expr->IgnoreParens(); + switch (expr->getStmtClass()) { + case Stmt::ArraySubscriptExprClass: + CheckArrayAccess_Check(*this, cast<ArraySubscriptExpr>(expr)); + return; + case Stmt::ConditionalOperatorClass: { + const ConditionalOperator *cond = cast<ConditionalOperator>(expr); + if (const Expr *lhs = cond->getLHS()) + CheckArrayAccess(lhs); + if (const Expr *rhs = cond->getRHS()) + CheckArrayAccess(rhs); + return; + } + default: + return; + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp new file mode 100644 index 0000000..e328eeb --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -0,0 +1,6702 @@ +//===---------------- SemaCodeComplete.cpp - Code Completion ----*- 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 the code-completion semantic actions. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" +#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" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Twine.h" +#include <list> +#include <map> +#include <vector> + +using namespace clang; +using namespace sema; + +namespace { + /// \brief A container of code-completion results. + class ResultBuilder { + public: + /// \brief The type of a name-lookup filter, which can be provided to the + /// name-lookup routines to specify which declarations should be included in + /// the result set (when it returns true) and which declarations should be + /// filtered out (returns false). + typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const; + + typedef CodeCompletionResult Result; + + private: + /// \brief The actual results we have found. + std::vector<Result> Results; + + /// \brief A record of all of the declarations we have found and placed + /// into the result set, used to ensure that no declaration ever gets into + /// the result set twice. + llvm::SmallPtrSet<Decl*, 16> AllDeclsFound; + + typedef std::pair<NamedDecl *, unsigned> DeclIndexPair; + + /// \brief An entry in the shadow map, which is optimized to store + /// a single (declaration, index) mapping (the common case) but + /// can also store a list of (declaration, index) mappings. + class ShadowMapEntry { + typedef llvm::SmallVector<DeclIndexPair, 4> DeclIndexPairVector; + + /// \brief Contains either the solitary NamedDecl * or a vector + /// of (declaration, index) pairs. + llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector; + + /// \brief When the entry contains a single declaration, this is + /// the index associated with that entry. + unsigned SingleDeclIndex; + + public: + ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { } + + void Add(NamedDecl *ND, unsigned Index) { + if (DeclOrVector.isNull()) { + // 0 - > 1 elements: just set the single element information. + DeclOrVector = ND; + SingleDeclIndex = Index; + return; + } + + if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) { + // 1 -> 2 elements: create the vector of results and push in the + // existing declaration. + DeclIndexPairVector *Vec = new DeclIndexPairVector; + Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); + DeclOrVector = Vec; + } + + // Add the new element to the end of the vector. + DeclOrVector.get<DeclIndexPairVector*>()->push_back( + DeclIndexPair(ND, Index)); + } + + void Destroy() { + if (DeclIndexPairVector *Vec + = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { + delete Vec; + DeclOrVector = ((NamedDecl *)0); + } + } + + // Iteration. + class iterator; + iterator begin() const; + iterator end() const; + }; + + /// \brief A mapping from declaration names to the declarations that have + /// this name within a particular scope and their index within the list of + /// results. + typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; + + /// \brief The semantic analysis object for which results are being + /// produced. + Sema &SemaRef; + + /// \brief The allocator used to allocate new code-completion strings. + CodeCompletionAllocator &Allocator; + + /// \brief If non-NULL, a filter function used to remove any code-completion + /// results that are not desirable. + LookupFilter Filter; + + /// \brief Whether we should allow declarations as + /// nested-name-specifiers that would otherwise be filtered out. + bool AllowNestedNameSpecifiers; + + /// \brief If set, the type that we would prefer our resulting value + /// declarations to have. + /// + /// Closely matching the preferred type gives a boost to a result's + /// priority. + CanQualType PreferredType; + + /// \brief A list of shadow maps, which is used to model name hiding at + /// different levels of, e.g., the inheritance hierarchy. + std::list<ShadowMap> ShadowMaps; + + /// \brief If we're potentially referring to a C++ member function, the set + /// of qualifiers applied to the object type. + Qualifiers ObjectTypeQualifiers; + + /// \brief Whether the \p ObjectTypeQualifiers field is active. + bool HasObjectTypeQualifiers; + + /// \brief The selector that we prefer. + Selector PreferredSelector; + + /// \brief The completion context in which we are gathering results. + CodeCompletionContext CompletionContext; + + /// \brief If we are in an instance method definition, the @implementation + /// object. + ObjCImplementationDecl *ObjCImplementation; + + void AdjustResultPriorityForDecl(Result &R); + + void MaybeAddConstructorResults(Result R); + + public: + explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, + const CodeCompletionContext &CompletionContext, + LookupFilter Filter = 0) + : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter), + AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), + CompletionContext(CompletionContext), + ObjCImplementation(0) + { + // If this is an Objective-C instance method definition, dig out the + // corresponding implementation. + switch (CompletionContext.getKind()) { + case CodeCompletionContext::CCC_Expression: + case CodeCompletionContext::CCC_ObjCMessageReceiver: + case CodeCompletionContext::CCC_ParenthesizedExpression: + case CodeCompletionContext::CCC_Statement: + case CodeCompletionContext::CCC_Recovery: + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) + if (Method->isInstanceMethod()) + if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) + ObjCImplementation = Interface->getImplementation(); + break; + + default: + break; + } + } + + /// \brief Whether we should include code patterns in the completion + /// results. + bool includeCodePatterns() const { + return SemaRef.CodeCompleter && + SemaRef.CodeCompleter->includeCodePatterns(); + } + + /// \brief Set the filter used for code-completion results. + void setFilter(LookupFilter Filter) { + this->Filter = Filter; + } + + Result *data() { return Results.empty()? 0 : &Results.front(); } + unsigned size() const { return Results.size(); } + bool empty() const { return Results.empty(); } + + /// \brief Specify the preferred type. + void setPreferredType(QualType T) { + PreferredType = SemaRef.Context.getCanonicalType(T); + } + + /// \brief Set the cv-qualifiers on the object type, for us in filtering + /// calls to member functions. + /// + /// When there are qualifiers in this set, they will be used to filter + /// out member functions that aren't available (because there will be a + /// cv-qualifier mismatch) or prefer functions with an exact qualifier + /// match. + void setObjectTypeQualifiers(Qualifiers Quals) { + ObjectTypeQualifiers = Quals; + HasObjectTypeQualifiers = true; + } + + /// \brief Set the preferred selector. + /// + /// When an Objective-C method declaration result is added, and that + /// method's selector matches this preferred selector, we give that method + /// a slight priority boost. + void setPreferredSelector(Selector Sel) { + PreferredSelector = Sel; + } + + /// \brief Retrieve the code-completion context for which results are + /// being collected. + const CodeCompletionContext &getCompletionContext() const { + return CompletionContext; + } + + /// \brief Specify whether nested-name-specifiers are allowed. + void allowNestedNameSpecifiers(bool Allow = true) { + AllowNestedNameSpecifiers = Allow; + } + + /// \brief Return the semantic analysis object for which we are collecting + /// code completion results. + Sema &getSema() const { return SemaRef; } + + /// \brief Retrieve the allocator used to allocate code completion strings. + CodeCompletionAllocator &getAllocator() const { return Allocator; } + + /// \brief Determine whether the given declaration is at all interesting + /// as a code-completion result. + /// + /// \param ND the declaration that we are inspecting. + /// + /// \param AsNestedNameSpecifier will be set true if this declaration is + /// only interesting when it is a nested-name-specifier. + bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const; + + /// \brief Check whether the result is hidden by the Hiding declaration. + /// + /// \returns true if the result is hidden and cannot be found, false if + /// the hidden result could still be found. When false, \p R may be + /// modified to describe how the result can be found (e.g., via extra + /// qualification). + bool CheckHiddenResult(Result &R, DeclContext *CurContext, + NamedDecl *Hiding); + + /// \brief Add a new result to this result set (if it isn't already in one + /// of the shadow maps), or replace an existing result (for, e.g., a + /// redeclaration). + /// + /// \param CurContext the result to add (if it is unique). + /// + /// \param R the context in which this result will be named. + void MaybeAddResult(Result R, DeclContext *CurContext = 0); + + /// \brief Add a new result to this result set, where we already know + /// the hiding declation (if any). + /// + /// \param R the result to add (if it is unique). + /// + /// \param CurContext the context in which this result will be named. + /// + /// \param Hiding the declaration that hides the result. + /// + /// \param InBaseClass whether the result was found in a base + /// class of the searched context. + void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, + bool InBaseClass); + + /// \brief Add a new non-declaration result to this result set. + void AddResult(Result R); + + /// \brief Enter into a new scope. + void EnterNewScope(); + + /// \brief Exit from the current scope. + void ExitScope(); + + /// \brief Ignore this declaration, if it is seen again. + void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } + + /// \name Name lookup predicates + /// + /// These predicates can be passed to the name lookup functions to filter the + /// results of name lookup. All of the predicates have the same type, so that + /// + //@{ + bool IsOrdinaryName(NamedDecl *ND) const; + bool IsOrdinaryNonTypeName(NamedDecl *ND) const; + bool IsIntegralConstantValue(NamedDecl *ND) const; + bool IsOrdinaryNonValueName(NamedDecl *ND) const; + bool IsNestedNameSpecifier(NamedDecl *ND) const; + bool IsEnum(NamedDecl *ND) const; + bool IsClassOrStruct(NamedDecl *ND) const; + bool IsUnion(NamedDecl *ND) const; + bool IsNamespace(NamedDecl *ND) const; + bool IsNamespaceOrAlias(NamedDecl *ND) const; + bool IsType(NamedDecl *ND) const; + bool IsMember(NamedDecl *ND) const; + bool IsObjCIvar(NamedDecl *ND) const; + bool IsObjCMessageReceiver(NamedDecl *ND) const; + bool IsObjCCollection(NamedDecl *ND) const; + bool IsImpossibleToSatisfy(NamedDecl *ND) const; + //@} + }; +} + +class ResultBuilder::ShadowMapEntry::iterator { + llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator; + unsigned SingleDeclIndex; + +public: + typedef DeclIndexPair value_type; + typedef value_type reference; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + + class pointer { + DeclIndexPair Value; + + public: + pointer(const DeclIndexPair &Value) : Value(Value) { } + + const DeclIndexPair *operator->() const { + return &Value; + } + }; + + iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { } + + iterator(NamedDecl *SingleDecl, unsigned Index) + : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { } + + iterator(const DeclIndexPair *Iterator) + : DeclOrIterator(Iterator), SingleDeclIndex(0) { } + + iterator &operator++() { + if (DeclOrIterator.is<NamedDecl *>()) { + DeclOrIterator = (NamedDecl *)0; + SingleDeclIndex = 0; + return *this; + } + + const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>(); + ++I; + DeclOrIterator = I; + return *this; + } + + /*iterator operator++(int) { + iterator tmp(*this); + ++(*this); + return tmp; + }*/ + + reference operator*() const { + if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>()) + return reference(ND, SingleDeclIndex); + + return *DeclOrIterator.get<const DeclIndexPair*>(); + } + + pointer operator->() const { + return pointer(**this); + } + + friend bool operator==(const iterator &X, const iterator &Y) { + return X.DeclOrIterator.getOpaqueValue() + == Y.DeclOrIterator.getOpaqueValue() && + X.SingleDeclIndex == Y.SingleDeclIndex; + } + + friend bool operator!=(const iterator &X, const iterator &Y) { + return !(X == Y); + } +}; + +ResultBuilder::ShadowMapEntry::iterator +ResultBuilder::ShadowMapEntry::begin() const { + if (DeclOrVector.isNull()) + return iterator(); + + if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>()) + return iterator(ND, SingleDeclIndex); + + return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin()); +} + +ResultBuilder::ShadowMapEntry::iterator +ResultBuilder::ShadowMapEntry::end() const { + if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull()) + return iterator(); + + return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end()); +} + +/// \brief Compute the qualification required to get from the current context +/// (\p CurContext) to the target context (\p TargetContext). +/// +/// \param Context the AST context in which the qualification will be used. +/// +/// \param CurContext the context where an entity is being named, which is +/// typically based on the current scope. +/// +/// \param TargetContext the context in which the named entity actually +/// resides. +/// +/// \returns a nested name specifier that refers into the target context, or +/// NULL if no qualification is needed. +static NestedNameSpecifier * +getRequiredQualification(ASTContext &Context, + DeclContext *CurContext, + DeclContext *TargetContext) { + llvm::SmallVector<DeclContext *, 4> TargetParents; + + for (DeclContext *CommonAncestor = TargetContext; + CommonAncestor && !CommonAncestor->Encloses(CurContext); + CommonAncestor = CommonAncestor->getLookupParent()) { + if (CommonAncestor->isTransparentContext() || + CommonAncestor->isFunctionOrMethod()) + continue; + + TargetParents.push_back(CommonAncestor); + } + + NestedNameSpecifier *Result = 0; + while (!TargetParents.empty()) { + DeclContext *Parent = TargetParents.back(); + TargetParents.pop_back(); + + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) { + if (!Namespace->getIdentifier()) + continue; + + Result = NestedNameSpecifier::Create(Context, Result, Namespace); + } + else if (TagDecl *TD = dyn_cast<TagDecl>(Parent)) + Result = NestedNameSpecifier::Create(Context, Result, + false, + Context.getTypeDeclType(TD).getTypePtr()); + } + return Result; +} + +bool ResultBuilder::isInterestingDecl(NamedDecl *ND, + bool &AsNestedNameSpecifier) const { + AsNestedNameSpecifier = false; + + ND = ND->getUnderlyingDecl(); + unsigned IDNS = ND->getIdentifierNamespace(); + + // Skip unnamed entities. + if (!ND->getDeclName()) + return false; + + // Friend declarations and declarations introduced due to friends are never + // added as results. + if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)) + return false; + + // Class template (partial) specializations are never added as results. + if (isa<ClassTemplateSpecializationDecl>(ND) || + isa<ClassTemplatePartialSpecializationDecl>(ND)) + return false; + + // Using declarations themselves are never added as results. + if (isa<UsingDecl>(ND)) + return false; + + // Some declarations have reserved names that we don't want to ever show. + if (const IdentifierInfo *Id = ND->getIdentifier()) { + // __va_list_tag is a freak of nature. Find it and skip it. + if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list")) + return false; + + // Filter out names reserved for the implementation (C99 7.1.3, + // C++ [lib.global.names]) if they come from a system header. + // + // FIXME: Add predicate for this. + if (Id->getLength() >= 2) { + const char *Name = Id->getNameStart(); + if (Name[0] == '_' && + (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) && + (ND->getLocation().isInvalid() || + SemaRef.SourceMgr.isInSystemHeader( + SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))) + return false; + } + } + + // Skip out-of-line declarations and definitions. + // NOTE: Unless it's an Objective-C property, method, or ivar, where + // the contexts can be messy. + if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) && + !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) || + isa<ObjCMethodDecl>(ND))) + return false; + + if (Filter == &ResultBuilder::IsNestedNameSpecifier || + ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) && + Filter != &ResultBuilder::IsNamespace && + Filter != &ResultBuilder::IsNamespaceOrAlias && + Filter != 0)) + AsNestedNameSpecifier = true; + + // Filter out any unwanted results. + if (Filter && !(this->*Filter)(ND)) { + // Check whether it is interesting as a nested-name-specifier. + if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus && + IsNestedNameSpecifier(ND) && + (Filter != &ResultBuilder::IsMember || + (isa<CXXRecordDecl>(ND) && + cast<CXXRecordDecl>(ND)->isInjectedClassName()))) { + AsNestedNameSpecifier = true; + return true; + } + + return false; + } + // ... then it must be interesting! + return true; +} + +bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, + NamedDecl *Hiding) { + // In C, there is no way to refer to a hidden name. + // FIXME: This isn't true; we can find a tag name hidden by an ordinary + // name if we introduce the tag type. + if (!SemaRef.getLangOptions().CPlusPlus) + return true; + + DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext(); + + // There is no way to qualify a name declared in a function or method. + if (HiddenCtx->isFunctionOrMethod()) + return true; + + if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext()) + return true; + + // We can refer to the result with the appropriate qualification. Do it. + R.Hidden = true; + R.QualifierIsInformative = false; + + if (!R.Qualifier) + R.Qualifier = getRequiredQualification(SemaRef.Context, + CurContext, + R.Declaration->getDeclContext()); + return false; +} + +/// \brief A simplified classification of types used to determine whether two +/// types are "similar enough" when adjusting priorities. +SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { + switch (T->getTypeClass()) { + case Type::Builtin: + switch (cast<BuiltinType>(T)->getKind()) { + case BuiltinType::Void: + return STC_Void; + + case BuiltinType::NullPtr: + return STC_Pointer; + + case BuiltinType::Overload: + case BuiltinType::Dependent: + return STC_Other; + + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return STC_ObjectiveC; + + default: + return STC_Arithmetic; + } + return STC_Other; + + case Type::Complex: + return STC_Arithmetic; + + case Type::Pointer: + return STC_Pointer; + + case Type::BlockPointer: + return STC_Block; + + case Type::LValueReference: + case Type::RValueReference: + return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType()); + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + return STC_Array; + + case Type::DependentSizedExtVector: + case Type::Vector: + case Type::ExtVector: + return STC_Arithmetic; + + case Type::FunctionProto: + case Type::FunctionNoProto: + return STC_Function; + + case Type::Record: + return STC_Record; + + case Type::Enum: + return STC_Arithmetic; + + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + return STC_ObjectiveC; + + default: + return STC_Other; + } +} + +/// \brief Get the type that a given expression will have if this declaration +/// is used as an expression in its "typical" code-completion form. +QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + + if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + return C.getTypeDeclType(Type); + if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) + return C.getObjCInterfaceType(Iface); + + QualType T; + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + T = Function->getCallResultType(); + else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + T = Method->getSendResultType(); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) + T = FunTmpl->getTemplatedDecl()->getCallResultType(); + else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); + else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + T = Property->getType(); + else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) + T = Value->getType(); + else + return QualType(); + + // Dig through references, function pointers, and block pointers to + // get down to the likely type of an expression when the entity is + // used. + do { + if (const ReferenceType *Ref = T->getAs<ReferenceType>()) { + T = Ref->getPointeeType(); + continue; + } + + if (const PointerType *Pointer = T->getAs<PointerType>()) { + if (Pointer->getPointeeType()->isFunctionType()) { + T = Pointer->getPointeeType(); + continue; + } + + break; + } + + if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) { + T = Block->getPointeeType(); + continue; + } + + if (const FunctionType *Function = T->getAs<FunctionType>()) { + T = Function->getResultType(); + continue; + } + + break; + } while (true); + + return T; +} + +void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { + // If this is an Objective-C method declaration whose selector matches our + // preferred selector, give it a priority boost. + if (!PreferredSelector.isNull()) + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) + if (PreferredSelector == Method->getSelector()) + R.Priority += CCD_SelectorMatch; + + // If we have a preferred type, adjust the priority for results with exactly- + // matching or nearly-matching types. + if (!PreferredType.isNull()) { + QualType T = getDeclUsageType(SemaRef.Context, R.Declaration); + if (!T.isNull()) { + CanQualType TC = SemaRef.Context.getCanonicalType(T); + // Check for exactly-matching types (modulo qualifiers). + if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) + R.Priority /= CCF_ExactTypeMatch; + // Check for nearly-matching types, based on classification of each. + else if ((getSimplifiedTypeClass(PreferredType) + == getSimplifiedTypeClass(TC)) && + !(PreferredType->isEnumeralType() && TC->isEnumeralType())) + R.Priority /= CCF_SimilarTypeMatch; + } + } +} + +void ResultBuilder::MaybeAddConstructorResults(Result R) { + if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration || + !CompletionContext.wantConstructorResults()) + return; + + ASTContext &Context = SemaRef.Context; + NamedDecl *D = R.Declaration; + CXXRecordDecl *Record = 0; + if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) + Record = ClassTemplate->getTemplatedDecl(); + else if ((Record = dyn_cast<CXXRecordDecl>(D))) { + // Skip specializations and partial specializations. + if (isa<ClassTemplateSpecializationDecl>(Record)) + return; + } else { + // There are no constructors here. + return; + } + + Record = Record->getDefinition(); + if (!Record) + return; + + + QualType RecordTy = Context.getTypeDeclType(Record); + DeclarationName ConstructorName + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(RecordTy)); + for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName); + Ctors.first != Ctors.second; ++Ctors.first) { + R.Declaration = *Ctors.first; + R.CursorKind = getCursorKindForDecl(R.Declaration); + Results.push_back(R); + } +} + +void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { + assert(!ShadowMaps.empty() && "Must enter into a results scope"); + + if (R.Kind != Result::RK_Declaration) { + // For non-declaration results, just add the result. + Results.push_back(R); + return; + } + + // Look through using declarations. + if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { + MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext); + return; + } + + Decl *CanonDecl = R.Declaration->getCanonicalDecl(); + unsigned IDNS = CanonDecl->getIdentifierNamespace(); + + bool AsNestedNameSpecifier = false; + if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) + return; + + // C++ constructors are never found by name lookup. + if (isa<CXXConstructorDecl>(R.Declaration)) + return; + + ShadowMap &SMap = ShadowMaps.back(); + ShadowMapEntry::iterator I, IEnd; + ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName()); + if (NamePos != SMap.end()) { + I = NamePos->second.begin(); + IEnd = NamePos->second.end(); + } + + for (; I != IEnd; ++I) { + NamedDecl *ND = I->first; + unsigned Index = I->second; + if (ND->getCanonicalDecl() == CanonDecl) { + // This is a redeclaration. Always pick the newer declaration. + Results[Index].Declaration = R.Declaration; + + // We're done. + return; + } + } + + // This is a new declaration in this scope. However, check whether this + // declaration name is hidden by a similarly-named declaration in an outer + // scope. + std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end(); + --SMEnd; + for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) { + ShadowMapEntry::iterator I, IEnd; + ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName()); + if (NamePos != SM->end()) { + I = NamePos->second.begin(); + IEnd = NamePos->second.end(); + } + for (; I != IEnd; ++I) { + // A tag declaration does not hide a non-tag declaration. + if (I->first->hasTagIdentifierNamespace() && + (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | + Decl::IDNS_ObjCProtocol))) + continue; + + // Protocols are in distinct namespaces from everything else. + if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) + || (IDNS & Decl::IDNS_ObjCProtocol)) && + I->first->getIdentifierNamespace() != IDNS) + continue; + + // The newly-added result is hidden by an entry in the shadow map. + if (CheckHiddenResult(R, CurContext, I->first)) + return; + + break; + } + } + + // Make sure that any given declaration only shows up in the result set once. + if (!AllDeclsFound.insert(CanonDecl)) + return; + + // If the filter is for nested-name-specifiers, then this result starts a + // nested-name-specifier. + if (AsNestedNameSpecifier) { + R.StartsNestedNameSpecifier = true; + R.Priority = CCP_NestedNameSpecifier; + } else + AdjustResultPriorityForDecl(R); + + // If this result is supposed to have an informative qualifier, add one. + if (R.QualifierIsInformative && !R.Qualifier && + !R.StartsNestedNameSpecifier) { + DeclContext *Ctx = R.Declaration->getDeclContext(); + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); + else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + else + R.QualifierIsInformative = false; + } + + // Insert this result into the set of results and into the current shadow + // map. + SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size()); + Results.push_back(R); + + if (!AsNestedNameSpecifier) + MaybeAddConstructorResults(R); +} + +void ResultBuilder::AddResult(Result R, DeclContext *CurContext, + NamedDecl *Hiding, bool InBaseClass = false) { + if (R.Kind != Result::RK_Declaration) { + // For non-declaration results, just add the result. + Results.push_back(R); + return; + } + + // Look through using declarations. + if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { + AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding); + return; + } + + bool AsNestedNameSpecifier = false; + if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) + return; + + // C++ constructors are never found by name lookup. + if (isa<CXXConstructorDecl>(R.Declaration)) + return; + + if (Hiding && CheckHiddenResult(R, CurContext, Hiding)) + return; + + // Make sure that any given declaration only shows up in the result set once. + if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl())) + return; + + // If the filter is for nested-name-specifiers, then this result starts a + // nested-name-specifier. + if (AsNestedNameSpecifier) { + R.StartsNestedNameSpecifier = true; + R.Priority = CCP_NestedNameSpecifier; + } + else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass && + isa<CXXRecordDecl>(R.Declaration->getDeclContext() + ->getRedeclContext())) + R.QualifierIsInformative = true; + + // If this result is supposed to have an informative qualifier, add one. + if (R.QualifierIsInformative && !R.Qualifier && + !R.StartsNestedNameSpecifier) { + DeclContext *Ctx = R.Declaration->getDeclContext(); + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); + else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) + R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); + else + R.QualifierIsInformative = false; + } + + // Adjust the priority if this result comes from a base class. + if (InBaseClass) + R.Priority += CCD_InBaseClass; + + AdjustResultPriorityForDecl(R); + + if (HasObjectTypeQualifiers) + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) + if (Method->isInstance()) { + Qualifiers MethodQuals + = Qualifiers::fromCVRMask(Method->getTypeQualifiers()); + if (ObjectTypeQualifiers == MethodQuals) + R.Priority += CCD_ObjectQualifierMatch; + else if (ObjectTypeQualifiers - MethodQuals) { + // The method cannot be invoked, because doing so would drop + // qualifiers. + return; + } + } + + // Insert this result into the set of results. + Results.push_back(R); + + if (!AsNestedNameSpecifier) + MaybeAddConstructorResults(R); +} + +void ResultBuilder::AddResult(Result R) { + assert(R.Kind != Result::RK_Declaration && + "Declaration results need more context"); + Results.push_back(R); +} + +/// \brief Enter into a new scope. +void ResultBuilder::EnterNewScope() { + ShadowMaps.push_back(ShadowMap()); +} + +/// \brief Exit from the current scope. +void ResultBuilder::ExitScope() { + for (ShadowMap::iterator E = ShadowMaps.back().begin(), + EEnd = ShadowMaps.back().end(); + E != EEnd; + ++E) + E->second.Destroy(); + + ShadowMaps.pop_back(); +} + +/// \brief Determines whether this given declaration will be found by +/// ordinary name lookup. +bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + + unsigned IDNS = Decl::IDNS_Ordinary; + if (SemaRef.getLangOptions().CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; + else if (SemaRef.getLangOptions().ObjC1) { + if (isa<ObjCIvarDecl>(ND)) + return true; + if (isa<ObjCPropertyDecl>(ND) && + SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND))) + return true; + } + + return ND->getIdentifierNamespace() & IDNS; +} + +/// \brief Determines whether this given declaration will be found by +/// ordinary name lookup but is not a type name. +bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) + return false; + + unsigned IDNS = Decl::IDNS_Ordinary; + if (SemaRef.getLangOptions().CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; + else if (SemaRef.getLangOptions().ObjC1) { + if (isa<ObjCIvarDecl>(ND)) + return true; + if (isa<ObjCPropertyDecl>(ND) && + SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND))) + return true; + } + + return ND->getIdentifierNamespace() & IDNS; +} + +bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const { + if (!IsOrdinaryNonTypeName(ND)) + return 0; + + if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) + if (VD->getType()->isIntegralOrEnumerationType()) + return true; + + return false; +} + +/// \brief Determines whether this given declaration will be found by +/// ordinary name lookup. +bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + + unsigned IDNS = Decl::IDNS_Ordinary; + if (SemaRef.getLangOptions().CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; + + return (ND->getIdentifierNamespace() & IDNS) && + !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) && + !isa<ObjCPropertyDecl>(ND); +} + +/// \brief Determines whether the given declaration is suitable as the +/// start of a C++ nested-name-specifier, e.g., a class or namespace. +bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const { + // Allow us to find class templates, too. + if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + ND = ClassTemplate->getTemplatedDecl(); + + return SemaRef.isAcceptableNestedNameSpecifier(ND); +} + +/// \brief Determines whether the given declaration is an enumeration. +bool ResultBuilder::IsEnum(NamedDecl *ND) const { + return isa<EnumDecl>(ND); +} + +/// \brief Determines whether the given declaration is a class or struct. +bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const { + // Allow us to find class templates, too. + if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + ND = ClassTemplate->getTemplatedDecl(); + + if (RecordDecl *RD = dyn_cast<RecordDecl>(ND)) + return RD->getTagKind() == TTK_Class || + RD->getTagKind() == TTK_Struct; + + return false; +} + +/// \brief Determines whether the given declaration is a union. +bool ResultBuilder::IsUnion(NamedDecl *ND) const { + // Allow us to find class templates, too. + if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + ND = ClassTemplate->getTemplatedDecl(); + + if (RecordDecl *RD = dyn_cast<RecordDecl>(ND)) + return RD->getTagKind() == TTK_Union; + + return false; +} + +/// \brief Determines whether the given declaration is a namespace. +bool ResultBuilder::IsNamespace(NamedDecl *ND) const { + return isa<NamespaceDecl>(ND); +} + +/// \brief Determines whether the given declaration is a namespace or +/// namespace alias. +bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const { + return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); +} + +/// \brief Determines whether the given declaration is a type. +bool ResultBuilder::IsType(NamedDecl *ND) const { + if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) + ND = Using->getTargetDecl(); + + return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); +} + +/// \brief Determines which members of a class should be visible via +/// "." or "->". Only value declarations, nested name specifiers, and +/// using declarations thereof should show up. +bool ResultBuilder::IsMember(NamedDecl *ND) const { + if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) + ND = Using->getTargetDecl(); + + return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) || + isa<ObjCPropertyDecl>(ND); +} + +static bool isObjCReceiverType(ASTContext &C, QualType T) { + T = C.getCanonicalType(T); + switch (T->getTypeClass()) { + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + return true; + + case Type::Builtin: + switch (cast<BuiltinType>(T)->getKind()) { + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return true; + + default: + break; + } + return false; + + default: + break; + } + + if (!C.getLangOptions().CPlusPlus) + return false; + + // FIXME: We could perform more analysis here to determine whether a + // particular class type has any conversions to Objective-C types. For now, + // just accept all class types. + return T->isDependentType() || T->isRecordType(); +} + +bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const { + QualType T = getDeclUsageType(SemaRef.Context, ND); + if (T.isNull()) + return false; + + T = SemaRef.Context.getBaseElementType(T); + return isObjCReceiverType(SemaRef.Context, T); +} + +bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const { + if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) || + (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND))) + return false; + + QualType T = getDeclUsageType(SemaRef.Context, ND); + if (T.isNull()) + return false; + + T = SemaRef.Context.getBaseElementType(T); + return T->isObjCObjectType() || T->isObjCObjectPointerType() || + T->isObjCIdType() || + (SemaRef.getLangOptions().CPlusPlus && T->isRecordType()); +} + +bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const { + return false; +} + +/// \rief Determines whether the given declaration is an Objective-C +/// instance variable. +bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const { + return isa<ObjCIvarDecl>(ND); +} + +namespace { + /// \brief Visible declaration consumer that adds a code-completion result + /// for each visible declaration. + class CodeCompletionDeclConsumer : public VisibleDeclConsumer { + ResultBuilder &Results; + DeclContext *CurContext; + + public: + CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext) + : Results(Results), CurContext(CurContext) { } + + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) { + Results.AddResult(ND, CurContext, Hiding, InBaseClass); + } + }; +} + +/// \brief Add type specifiers for the current language as keyword results. +static void AddTypeSpecifierResults(const LangOptions &LangOpts, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + Results.AddResult(Result("short", CCP_Type)); + Results.AddResult(Result("long", CCP_Type)); + Results.AddResult(Result("signed", CCP_Type)); + Results.AddResult(Result("unsigned", CCP_Type)); + Results.AddResult(Result("void", CCP_Type)); + Results.AddResult(Result("char", CCP_Type)); + Results.AddResult(Result("int", CCP_Type)); + Results.AddResult(Result("float", CCP_Type)); + Results.AddResult(Result("double", CCP_Type)); + Results.AddResult(Result("enum", CCP_Type)); + Results.AddResult(Result("struct", CCP_Type)); + Results.AddResult(Result("union", CCP_Type)); + Results.AddResult(Result("const", CCP_Type)); + Results.AddResult(Result("volatile", CCP_Type)); + + if (LangOpts.C99) { + // C99-specific + Results.AddResult(Result("_Complex", CCP_Type)); + Results.AddResult(Result("_Imaginary", CCP_Type)); + Results.AddResult(Result("_Bool", CCP_Type)); + Results.AddResult(Result("restrict", CCP_Type)); + } + + CodeCompletionBuilder Builder(Results.getAllocator()); + if (LangOpts.CPlusPlus) { + // C++-specific + Results.AddResult(Result("bool", CCP_Type + + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0))); + Results.AddResult(Result("class", CCP_Type)); + Results.AddResult(Result("wchar_t", CCP_Type)); + + // typename qualified-id + Builder.AddTypedTextChunk("typename"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("qualifier"); + Builder.AddTextChunk("::"); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + + if (LangOpts.CPlusPlus0x) { + Results.AddResult(Result("auto", CCP_Type)); + Results.AddResult(Result("char16_t", CCP_Type)); + Results.AddResult(Result("char32_t", CCP_Type)); + + Builder.AddTypedTextChunk("decltype"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + } + + // GNU extensions + if (LangOpts.GNUMode) { + // FIXME: Enable when we actually support decimal floating point. + // Results.AddResult(Result("_Decimal32")); + // Results.AddResult(Result("_Decimal64")); + // Results.AddResult(Result("_Decimal128")); + + Builder.AddTypedTextChunk("typeof"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + Builder.AddTypedTextChunk("typeof"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } +} + +static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, + const LangOptions &LangOpts, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + // Note: we don't suggest either "auto" or "register", because both + // are pointless as storage specifiers. Elsewhere, we suggest "auto" + // in C++0x as a type specifier. + Results.AddResult(Result("extern")); + Results.AddResult(Result("static")); +} + +static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, + const LangOptions &LangOpts, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + switch (CCC) { + case Sema::PCC_Class: + case Sema::PCC_MemberTemplate: + if (LangOpts.CPlusPlus) { + Results.AddResult(Result("explicit")); + Results.AddResult(Result("friend")); + Results.AddResult(Result("mutable")); + Results.AddResult(Result("virtual")); + } + // Fall through + + case Sema::PCC_ObjCInterface: + case Sema::PCC_ObjCImplementation: + case Sema::PCC_Namespace: + case Sema::PCC_Template: + if (LangOpts.CPlusPlus || LangOpts.C99) + Results.AddResult(Result("inline")); + break; + + case Sema::PCC_ObjCInstanceVariableList: + case Sema::PCC_Expression: + case Sema::PCC_Statement: + case Sema::PCC_ForInit: + case Sema::PCC_Condition: + case Sema::PCC_RecoveryInFunction: + case Sema::PCC_Type: + case Sema::PCC_ParenthesizedExpression: + case Sema::PCC_LocalDeclarationSpecifiers: + break; + } +} + +static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); +static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); +static void AddObjCVisibilityResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt); +static void AddObjCImplementationResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt); +static void AddObjCInterfaceResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt); +static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); + +static void AddTypedefResult(ResultBuilder &Results) { + CodeCompletionBuilder Builder(Results.getAllocator()); + Builder.AddTypedTextChunk("typedef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); +} + +static bool WantTypesInContext(Sema::ParserCompletionContext CCC, + const LangOptions &LangOpts) { + switch (CCC) { + case Sema::PCC_Namespace: + case Sema::PCC_Class: + case Sema::PCC_ObjCInstanceVariableList: + case Sema::PCC_Template: + case Sema::PCC_MemberTemplate: + case Sema::PCC_Statement: + case Sema::PCC_RecoveryInFunction: + case Sema::PCC_Type: + case Sema::PCC_ParenthesizedExpression: + case Sema::PCC_LocalDeclarationSpecifiers: + return true; + + case Sema::PCC_Expression: + case Sema::PCC_Condition: + return LangOpts.CPlusPlus; + + case Sema::PCC_ObjCInterface: + case Sema::PCC_ObjCImplementation: + return false; + + case Sema::PCC_ForInit: + return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99; + } + + return false; +} + +/// \brief Add language constructs that show up for "ordinary" names. +static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, + Scope *S, + Sema &SemaRef, + ResultBuilder &Results) { + CodeCompletionBuilder Builder(Results.getAllocator()); + + typedef CodeCompletionResult Result; + switch (CCC) { + case Sema::PCC_Namespace: + if (SemaRef.getLangOptions().CPlusPlus) { + if (Results.includeCodePatterns()) { + // namespace <identifier> { declarations } + Builder.AddTypedTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("identifier"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("declarations"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + // namespace identifier = identifier ; + Builder.AddTypedTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("name"); + Builder.AddChunk(CodeCompletionString::CK_Equal); + Builder.AddPlaceholderChunk("namespace"); + Results.AddResult(Result(Builder.TakeString())); + + // Using directives + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("identifier"); + Results.AddResult(Result(Builder.TakeString())); + + // asm(string-literal) + Builder.AddTypedTextChunk("asm"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("string-literal"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + if (Results.includeCodePatterns()) { + // Explicit template instantiation + Builder.AddTypedTextChunk("template"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("declaration"); + Results.AddResult(Result(Builder.TakeString())); + } + } + + if (SemaRef.getLangOptions().ObjC1) + AddObjCTopLevelResults(Results, true); + + AddTypedefResult(Results); + // Fall through + + case Sema::PCC_Class: + if (SemaRef.getLangOptions().CPlusPlus) { + // Using declaration + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("qualifier"); + Builder.AddTextChunk("::"); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + + // using typename qualifier::name (only in a dependent context) + if (SemaRef.CurContext->isDependentContext()) { + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("typename"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("qualifier"); + Builder.AddTextChunk("::"); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + } + + if (CCC == Sema::PCC_Class) { + AddTypedefResult(Results); + + // public: + Builder.AddTypedTextChunk("public"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + + // protected: + Builder.AddTypedTextChunk("protected"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + + // private: + Builder.AddTypedTextChunk("private"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + } + } + // Fall through + + case Sema::PCC_Template: + case Sema::PCC_MemberTemplate: + if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { + // template < parameters > + Builder.AddTypedTextChunk("template"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("parameters"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Results.AddResult(Result(Builder.TakeString())); + } + + AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); + break; + + case Sema::PCC_ObjCInterface: + AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true); + AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); + break; + + case Sema::PCC_ObjCImplementation: + AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true); + AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); + AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results); + break; + + case Sema::PCC_ObjCInstanceVariableList: + AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true); + break; + + case Sema::PCC_RecoveryInFunction: + case Sema::PCC_Statement: { + AddTypedefResult(Results); + + if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() && + SemaRef.getLangOptions().CXXExceptions) { + Builder.AddTypedTextChunk("try"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("catch"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("declaration"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + if (SemaRef.getLangOptions().ObjC1) + AddObjCStatementResults(Results, true); + + if (Results.includeCodePatterns()) { + // if (condition) { statements } + Builder.AddTypedTextChunk("if"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOptions().CPlusPlus) + Builder.AddPlaceholderChunk("condition"); + else + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + + // switch (condition) { } + Builder.AddTypedTextChunk("switch"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOptions().CPlusPlus) + Builder.AddPlaceholderChunk("condition"); + else + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + // Switch-specific statements. + if (!SemaRef.getCurFunction()->SwitchStack.empty()) { + // case expression: + Builder.AddTypedTextChunk("case"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + + // default: + Builder.AddTypedTextChunk("default"); + Builder.AddChunk(CodeCompletionString::CK_Colon); + Results.AddResult(Result(Builder.TakeString())); + } + + if (Results.includeCodePatterns()) { + /// while (condition) { statements } + Builder.AddTypedTextChunk("while"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOptions().CPlusPlus) + Builder.AddPlaceholderChunk("condition"); + else + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + + // do { statements } while ( expression ); + Builder.AddTypedTextChunk("do"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("while"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // for ( for-init-statement ; condition ; expression ) { statements } + Builder.AddTypedTextChunk("for"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99) + Builder.AddPlaceholderChunk("init-statement"); + else + Builder.AddPlaceholderChunk("init-expression"); + Builder.AddChunk(CodeCompletionString::CK_SemiColon); + Builder.AddPlaceholderChunk("condition"); + Builder.AddChunk(CodeCompletionString::CK_SemiColon); + Builder.AddPlaceholderChunk("inc-expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + if (S->getContinueParent()) { + // continue ; + Builder.AddTypedTextChunk("continue"); + Results.AddResult(Result(Builder.TakeString())); + } + + if (S->getBreakParent()) { + // break ; + Builder.AddTypedTextChunk("break"); + Results.AddResult(Result(Builder.TakeString())); + } + + // "return expression ;" or "return ;", depending on whether we + // know the function is void or not. + bool isVoid = false; + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) + isVoid = Function->getResultType()->isVoidType(); + else if (ObjCMethodDecl *Method + = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) + isVoid = Method->getResultType()->isVoidType(); + else if (SemaRef.getCurBlock() && + !SemaRef.getCurBlock()->ReturnType.isNull()) + isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType(); + Builder.AddTypedTextChunk("return"); + if (!isVoid) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + } + Results.AddResult(Result(Builder.TakeString())); + + // goto identifier ; + Builder.AddTypedTextChunk("goto"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("label"); + Results.AddResult(Result(Builder.TakeString())); + + // Using directives + Builder.AddTypedTextChunk("using"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("namespace"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("identifier"); + Results.AddResult(Result(Builder.TakeString())); + } + + // Fall through (for statement expressions). + case Sema::PCC_ForInit: + case Sema::PCC_Condition: + AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results); + // Fall through: conditions and statements can have expressions. + + case Sema::PCC_ParenthesizedExpression: + case Sema::PCC_Expression: { + if (SemaRef.getLangOptions().CPlusPlus) { + // 'this', if we're in a non-static member function. + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) + if (!Method->isStatic()) + Results.AddResult(Result("this")); + + // true, false + Results.AddResult(Result("true")); + Results.AddResult(Result("false")); + + if (SemaRef.getLangOptions().RTTI) { + // dynamic_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("dynamic_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + + // static_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("static_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // reinterpret_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("reinterpret_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // const_cast < type-id > ( expression ) + Builder.AddTypedTextChunk("const_cast"); + Builder.AddChunk(CodeCompletionString::CK_LeftAngle); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_RightAngle); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + if (SemaRef.getLangOptions().RTTI) { + // typeid ( expression-or-type ) + Builder.AddTypedTextChunk("typeid"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression-or-type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + } + + // new T ( ... ) + Builder.AddTypedTextChunk("new"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expressions"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // new T [ ] ( ... ) + Builder.AddTypedTextChunk("new"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("type"); + Builder.AddChunk(CodeCompletionString::CK_LeftBracket); + Builder.AddPlaceholderChunk("size"); + Builder.AddChunk(CodeCompletionString::CK_RightBracket); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expressions"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // delete expression + Builder.AddTypedTextChunk("delete"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + // delete [] expression + Builder.AddTypedTextChunk("delete"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBracket); + Builder.AddChunk(CodeCompletionString::CK_RightBracket); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + if (SemaRef.getLangOptions().CXXExceptions) { + // throw expression + Builder.AddTypedTextChunk("throw"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + } + + // FIXME: Rethrow? + } + + if (SemaRef.getLangOptions().ObjC1) { + // Add "super", if we're in an Objective-C class with a superclass. + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { + // The interface can be NULL. + if (ObjCInterfaceDecl *ID = Method->getClassInterface()) + if (ID->getSuperClass()) + Results.AddResult(Result("super")); + } + + AddObjCExpressionResults(Results, true); + } + + // sizeof expression + Builder.AddTypedTextChunk("sizeof"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression-or-type"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + break; + } + + case Sema::PCC_Type: + case Sema::PCC_LocalDeclarationSpecifiers: + break; + } + + if (WantTypesInContext(CCC, SemaRef.getLangOptions())) + AddTypeSpecifierResults(SemaRef.getLangOptions(), Results); + + if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type) + Results.AddResult(Result("operator")); +} + +/// \brief Retrieve the string representation of the given type as a string +/// that has the appropriate lifetime for code completion. +/// +/// This routine provides a fast path where we provide constant strings for +/// common type names. +static const char *GetCompletionTypeString(QualType T, + ASTContext &Context, + CodeCompletionAllocator &Allocator) { + PrintingPolicy Policy(Context.PrintingPolicy); + Policy.AnonymousTagLocations = false; + + if (!T.getLocalQualifiers()) { + // Built-in type names are constant strings. + if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) + return BT->getName(Context.getLangOptions()); + + // Anonymous tag types are constant strings. + if (const TagType *TagT = dyn_cast<TagType>(T)) + if (TagDecl *Tag = TagT->getDecl()) + if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { + switch (Tag->getTagKind()) { + case TTK_Struct: return "struct <anonymous>"; + case TTK_Class: return "class <anonymous>"; + case TTK_Union: return "union <anonymous>"; + case TTK_Enum: return "enum <anonymous>"; + } + } + } + + // Slow path: format the type as a string. + std::string Result; + T.getAsStringInternal(Result, Policy); + return Allocator.CopyString(Result); +} + +/// \brief If the given declaration has an associated type, add it as a result +/// type chunk. +static void AddResultTypeChunk(ASTContext &Context, + NamedDecl *ND, + CodeCompletionBuilder &Result) { + if (!ND) + return; + + // Skip constructors and conversion functions, which have their return types + // built into their names. + if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND)) + return; + + // Determine the type of the declaration (if it has a type). + QualType T; + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + T = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + T = Method->getResultType(); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) + T = FunTmpl->getTemplatedDecl()->getResultType(); + else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); + else if (isa<UnresolvedUsingValueDecl>(ND)) { + /* Do nothing: ignore unresolved using declarations*/ + } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) + T = Value->getType(); + else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + T = Property->getType(); + + if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) + return; + + Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, + Result.getAllocator())); +} + +static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod, + CodeCompletionBuilder &Result) { + if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) + if (Sentinel->getSentinel() == 0) { + if (Context.getLangOptions().ObjC1 && + Context.Idents.get("nil").hasMacroDefinition()) + Result.AddTextChunk(", nil"); + else if (Context.Idents.get("NULL").hasMacroDefinition()) + Result.AddTextChunk(", NULL"); + else + Result.AddTextChunk(", (void*)0"); + } +} + +static std::string FormatFunctionParameter(ASTContext &Context, + ParmVarDecl *Param, + bool SuppressName = false) { + bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); + if (Param->getType()->isDependentType() || + !Param->getType()->isBlockPointerType()) { + // The argument for a dependent or non-block parameter is a placeholder + // containing that parameter's type. + std::string Result; + + if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName) + Result = Param->getIdentifier()->getName(); + + Param->getType().getAsStringInternal(Result, + Context.PrintingPolicy); + + if (ObjCMethodParam) { + Result = "(" + Result; + Result += ")"; + if (Param->getIdentifier() && !SuppressName) + Result += Param->getIdentifier()->getName(); + } + return Result; + } + + // The argument for a block pointer parameter is a block literal with + // the appropriate type. + FunctionTypeLoc *Block = 0; + FunctionProtoTypeLoc *BlockProto = 0; + TypeLoc TL; + if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) { + TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); + while (true) { + // Look through typedefs. + if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) { + if (TypeSourceInfo *InnerTSInfo + = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) { + TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); + continue; + } + } + + // Look through qualified types + if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) { + TL = QualifiedTL->getUnqualifiedLoc(); + continue; + } + + // Try to get the function prototype behind the block pointer type, + // then we're done. + if (BlockPointerTypeLoc *BlockPtr + = dyn_cast<BlockPointerTypeLoc>(&TL)) { + TL = BlockPtr->getPointeeLoc().IgnoreParens(); + Block = dyn_cast<FunctionTypeLoc>(&TL); + BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL); + } + break; + } + } + + if (!Block) { + // We were unable to find a FunctionProtoTypeLoc with parameter names + // for the block; just use the parameter type as a placeholder. + std::string Result; + Param->getType().getUnqualifiedType(). + getAsStringInternal(Result, Context.PrintingPolicy); + + if (ObjCMethodParam) { + Result = "(" + Result; + Result += ")"; + if (Param->getIdentifier()) + Result += Param->getIdentifier()->getName(); + } + + return Result; + } + + // We have the function prototype behind the block pointer type, as it was + // written in the source. + std::string Result; + QualType ResultType = Block->getTypePtr()->getResultType(); + if (!ResultType->isVoidType()) + ResultType.getAsStringInternal(Result, Context.PrintingPolicy); + + Result = '^' + Result; + if (!BlockProto || Block->getNumArgs() == 0) { + if (BlockProto && BlockProto->getTypePtr()->isVariadic()) + Result += "(...)"; + else + Result += "(void)"; + } else { + Result += "("; + for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) { + if (I) + Result += ", "; + Result += FormatFunctionParameter(Context, Block->getArg(I)); + + if (I == N - 1 && BlockProto->getTypePtr()->isVariadic()) + Result += ", ..."; + } + Result += ")"; + } + + if (Param->getIdentifier()) + Result += Param->getIdentifier()->getName(); + + return Result; +} + +/// \brief Add function parameter chunks to the given code completion string. +static void AddFunctionParameterChunks(ASTContext &Context, + FunctionDecl *Function, + CodeCompletionBuilder &Result, + unsigned Start = 0, + bool InOptional = false) { + typedef CodeCompletionString::Chunk Chunk; + bool FirstParameter = true; + + for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { + ParmVarDecl *Param = Function->getParamDecl(P); + + if (Param->hasDefaultArg() && !InOptional) { + // When we see an optional default argument, put that argument and + // the remaining default arguments into a new, optional string. + CodeCompletionBuilder Opt(Result.getAllocator()); + if (!FirstParameter) + Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + AddFunctionParameterChunks(Context, Function, Opt, P, true); + Result.AddOptionalChunk(Opt.TakeString()); + break; + } + + if (FirstParameter) + FirstParameter = false; + else + Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + + InOptional = false; + + // Format the placeholder string. + std::string PlaceholderStr = FormatFunctionParameter(Context, Param); + + if (Function->isVariadic() && P == N - 1) + PlaceholderStr += ", ..."; + + // Add the placeholder string. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString(PlaceholderStr)); + } + + if (const FunctionProtoType *Proto + = Function->getType()->getAs<FunctionProtoType>()) + if (Proto->isVariadic()) { + if (Proto->getNumArgs() == 0) + Result.AddPlaceholderChunk("..."); + + MaybeAddSentinel(Context, Function, Result); + } +} + +/// \brief Add template parameter chunks to the given code completion string. +static void AddTemplateParameterChunks(ASTContext &Context, + TemplateDecl *Template, + CodeCompletionBuilder &Result, + unsigned MaxParameters = 0, + unsigned Start = 0, + bool InDefaultArg = false) { + typedef CodeCompletionString::Chunk Chunk; + bool FirstParameter = true; + + TemplateParameterList *Params = Template->getTemplateParameters(); + TemplateParameterList::iterator PEnd = Params->end(); + if (MaxParameters) + PEnd = Params->begin() + MaxParameters; + for (TemplateParameterList::iterator P = Params->begin() + Start; + P != PEnd; ++P) { + bool HasDefaultArg = false; + std::string PlaceholderStr; + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { + if (TTP->wasDeclaredWithTypename()) + PlaceholderStr = "typename"; + else + PlaceholderStr = "class"; + + if (TTP->getIdentifier()) { + PlaceholderStr += ' '; + PlaceholderStr += TTP->getIdentifier()->getName(); + } + + HasDefaultArg = TTP->hasDefaultArgument(); + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + if (NTTP->getIdentifier()) + PlaceholderStr = NTTP->getIdentifier()->getName(); + NTTP->getType().getAsStringInternal(PlaceholderStr, + Context.PrintingPolicy); + HasDefaultArg = NTTP->hasDefaultArgument(); + } else { + assert(isa<TemplateTemplateParmDecl>(*P)); + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); + + // Since putting the template argument list into the placeholder would + // be very, very long, we just use an abbreviation. + PlaceholderStr = "template<...> class"; + if (TTP->getIdentifier()) { + PlaceholderStr += ' '; + PlaceholderStr += TTP->getIdentifier()->getName(); + } + + HasDefaultArg = TTP->hasDefaultArgument(); + } + + if (HasDefaultArg && !InDefaultArg) { + // When we see an optional default argument, put that argument and + // the remaining default arguments into a new, optional string. + CodeCompletionBuilder Opt(Result.getAllocator()); + if (!FirstParameter) + Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + AddTemplateParameterChunks(Context, Template, Opt, MaxParameters, + P - Params->begin(), true); + Result.AddOptionalChunk(Opt.TakeString()); + break; + } + + InDefaultArg = false; + + if (FirstParameter) + FirstParameter = false; + else + Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + + // Add the placeholder string. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString(PlaceholderStr)); + } +} + +/// \brief Add a qualifier to the given code-completion string, if the +/// provided nested-name-specifier is non-NULL. +static void +AddQualifierToCompletionString(CodeCompletionBuilder &Result, + NestedNameSpecifier *Qualifier, + bool QualifierIsInformative, + ASTContext &Context) { + if (!Qualifier) + return; + + std::string PrintedNNS; + { + llvm::raw_string_ostream OS(PrintedNNS); + Qualifier->print(OS, Context.PrintingPolicy); + } + if (QualifierIsInformative) + Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS)); + else + Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS)); +} + +static void +AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, + FunctionDecl *Function) { + const FunctionProtoType *Proto + = Function->getType()->getAs<FunctionProtoType>(); + if (!Proto || !Proto->getTypeQuals()) + return; + + // FIXME: Add ref-qualifier! + + // Handle single qualifiers without copying + if (Proto->getTypeQuals() == Qualifiers::Const) { + Result.AddInformativeChunk(" const"); + return; + } + + if (Proto->getTypeQuals() == Qualifiers::Volatile) { + Result.AddInformativeChunk(" volatile"); + return; + } + + if (Proto->getTypeQuals() == Qualifiers::Restrict) { + Result.AddInformativeChunk(" restrict"); + return; + } + + // Handle multiple qualifiers. + std::string QualsStr; + if (Proto->getTypeQuals() & Qualifiers::Const) + QualsStr += " const"; + if (Proto->getTypeQuals() & Qualifiers::Volatile) + QualsStr += " volatile"; + if (Proto->getTypeQuals() & Qualifiers::Restrict) + QualsStr += " restrict"; + Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); +} + +/// \brief Add the name of the given declaration +static void AddTypedNameChunk(ASTContext &Context, NamedDecl *ND, + CodeCompletionBuilder &Result) { + typedef CodeCompletionString::Chunk Chunk; + + DeclarationName Name = ND->getDeclName(); + if (!Name) + return; + + switch (Name.getNameKind()) { + case DeclarationName::CXXOperatorName: { + const char *OperatorName = 0; + switch (Name.getCXXOverloadedOperator()) { + case OO_None: + case OO_Conditional: + case NUM_OVERLOADED_OPERATORS: + OperatorName = "operator"; + break; + +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + case OO_##Name: OperatorName = "operator" Spelling; break; +#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) +#include "clang/Basic/OperatorKinds.def" + + case OO_New: OperatorName = "operator new"; break; + case OO_Delete: OperatorName = "operator delete"; break; + case OO_Array_New: OperatorName = "operator new[]"; break; + case OO_Array_Delete: OperatorName = "operator delete[]"; break; + case OO_Call: OperatorName = "operator()"; break; + case OO_Subscript: OperatorName = "operator[]"; break; + } + Result.AddTypedTextChunk(OperatorName); + break; + } + + case DeclarationName::Identifier: + case DeclarationName::CXXConversionFunctionName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXLiteralOperatorName: + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + break; + + case DeclarationName::CXXUsingDirective: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + break; + + case DeclarationName::CXXConstructorName: { + CXXRecordDecl *Record = 0; + QualType Ty = Name.getCXXNameType(); + if (const RecordType *RecordTy = Ty->getAs<RecordType>()) + Record = cast<CXXRecordDecl>(RecordTy->getDecl()); + else if (const InjectedClassNameType *InjectedTy + = Ty->getAs<InjectedClassNameType>()) + Record = InjectedTy->getDecl(); + else { + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + break; + } + + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Record->getNameAsString())); + if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); + AddTemplateParameterChunks(Context, Template, Result); + Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); + } + break; + } + } +} + +/// \brief If possible, create a new code completion string for the given +/// result. +/// +/// \returns Either a new, heap-allocated code completion string describing +/// how to use this result, or NULL to indicate that the string or name of the +/// result is all that is needed. +CodeCompletionString * +CodeCompletionResult::CreateCodeCompletionString(Sema &S, + CodeCompletionAllocator &Allocator) { + typedef CodeCompletionString::Chunk Chunk; + CodeCompletionBuilder Result(Allocator, Priority, Availability); + + if (Kind == RK_Pattern) { + Pattern->Priority = Priority; + Pattern->Availability = Availability; + return Pattern; + } + + if (Kind == RK_Keyword) { + Result.AddTypedTextChunk(Keyword); + return Result.TakeString(); + } + + if (Kind == RK_Macro) { + MacroInfo *MI = S.PP.getMacroInfo(Macro); + assert(MI && "Not a macro?"); + + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Macro->getName())); + + if (!MI->isFunctionLike()) + return Result.TakeString(); + + // Format a function-like macro with placeholders for the arguments. + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end(); + A != AEnd; ++A) { + if (A != MI->arg_begin()) + Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + + if (!MI->isVariadic() || A != AEnd - 1) { + // Non-variadic argument. + Result.AddPlaceholderChunk( + Result.getAllocator().CopyString((*A)->getName())); + continue; + } + + // Variadic argument; cope with the different between GNU and C99 + // variadic macros, providing a single placeholder for the rest of the + // arguments. + if ((*A)->isStr("__VA_ARGS__")) + Result.AddPlaceholderChunk("..."); + else { + std::string Arg = (*A)->getName(); + Arg += "..."; + Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); + } + } + Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + return Result.TakeString(); + } + + assert(Kind == RK_Declaration && "Missed a result kind?"); + NamedDecl *ND = Declaration; + + if (StartsNestedNameSpecifier) { + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + Result.AddTextChunk("::"); + return Result.TakeString(); + } + + AddResultTypeChunk(S.Context, ND, Result); + + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); + AddTypedNameChunk(S.Context, ND, Result); + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + AddFunctionParameterChunks(S.Context, Function, Result); + Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + AddFunctionTypeQualsToCompletionString(Result, Function); + return Result.TakeString(); + } + + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); + FunctionDecl *Function = FunTmpl->getTemplatedDecl(); + AddTypedNameChunk(S.Context, Function, Result); + + // Figure out which template parameters are deduced (or have default + // arguments). + llvm::SmallVector<bool, 16> Deduced; + S.MarkDeducedTemplateParameters(FunTmpl, Deduced); + unsigned LastDeducibleArgument; + for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0; + --LastDeducibleArgument) { + if (!Deduced[LastDeducibleArgument - 1]) { + // C++0x: Figure out if the template argument has a default. If so, + // the user doesn't need to type this argument. + // FIXME: We need to abstract template parameters better! + bool HasDefaultArg = false; + NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( + LastDeducibleArgument - 1); + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) + HasDefaultArg = TTP->hasDefaultArgument(); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) + HasDefaultArg = NTTP->hasDefaultArgument(); + else { + assert(isa<TemplateTemplateParmDecl>(Param)); + HasDefaultArg + = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); + } + + if (!HasDefaultArg) + break; + } + } + + if (LastDeducibleArgument) { + // Some of the function template arguments cannot be deduced from a + // function call, so we introduce an explicit template argument list + // containing all of the arguments up to the first deducible argument. + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); + AddTemplateParameterChunks(S.Context, FunTmpl, Result, + LastDeducibleArgument); + Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); + } + + // Add the function parameters + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + AddFunctionParameterChunks(S.Context, Function, Result); + Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + AddFunctionTypeQualsToCompletionString(Result, Function); + return Result.TakeString(); + } + + if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(Template->getNameAsString())); + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle)); + AddTemplateParameterChunks(S.Context, Template, Result); + Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle)); + return Result.TakeString(); + } + + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { + Selector Sel = Method->getSelector(); + if (Sel.isUnarySelector()) { + Result.AddTypedTextChunk(Result.getAllocator().CopyString( + Sel.getNameForSlot(0))); + return Result.TakeString(); + } + + std::string SelName = Sel.getNameForSlot(0).str(); + SelName += ':'; + if (StartParameter == 0) + Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName)); + else { + Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName)); + + // If there is only one parameter, and we're past it, add an empty + // typed-text chunk since there is nothing to type. + if (Method->param_size() == 1) + Result.AddTypedTextChunk(""); + } + unsigned Idx = 0; + for (ObjCMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; (void)++P, ++Idx) { + if (Idx > 0) { + std::string Keyword; + if (Idx > StartParameter) + Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); + if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) + Keyword += II->getName().str(); + Keyword += ":"; + if (Idx < StartParameter || AllParametersAreInformative) + Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword)); + else + Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword)); + } + + // If we're before the starting parameter, skip the placeholder. + if (Idx < StartParameter) + continue; + + std::string Arg; + + if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity) + Arg = FormatFunctionParameter(S.Context, *P, true); + else { + (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy); + Arg = "(" + Arg + ")"; + if (IdentifierInfo *II = (*P)->getIdentifier()) + if (DeclaringEntity || AllParametersAreInformative) + Arg += II->getName().str(); + } + + if (Method->isVariadic() && (P + 1) == PEnd) + Arg += ", ..."; + + if (DeclaringEntity) + Result.AddTextChunk(Result.getAllocator().CopyString(Arg)); + else if (AllParametersAreInformative) + Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg)); + else + Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); + } + + if (Method->isVariadic()) { + if (Method->param_size() == 0) { + if (DeclaringEntity) + Result.AddTextChunk(", ..."); + else if (AllParametersAreInformative) + Result.AddInformativeChunk(", ..."); + else + Result.AddPlaceholderChunk(", ..."); + } + + MaybeAddSentinel(S.Context, Method, Result); + } + + return Result.TakeString(); + } + + if (Qualifier) + AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, + S.Context); + + Result.AddTypedTextChunk( + Result.getAllocator().CopyString(ND->getNameAsString())); + return Result.TakeString(); +} + +CodeCompletionString * +CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( + unsigned CurrentArg, + Sema &S, + CodeCompletionAllocator &Allocator) const { + typedef CodeCompletionString::Chunk Chunk; + + // FIXME: Set priority, availability appropriately. + CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available); + FunctionDecl *FDecl = getFunction(); + AddResultTypeChunk(S.Context, FDecl, Result); + const FunctionProtoType *Proto + = dyn_cast<FunctionProtoType>(getFunctionType()); + if (!FDecl && !Proto) { + // Function without a prototype. Just give the return type and a + // highlighted ellipsis. + const FunctionType *FT = getFunctionType(); + Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(), + S.Context, + Result.getAllocator())); + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "...")); + Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + return Result.TakeString(); + } + + if (FDecl) + Result.AddTextChunk( + Result.getAllocator().CopyString(FDecl->getNameAsString())); + else + Result.AddTextChunk( + Result.getAllocator().CopyString( + Proto->getResultType().getAsString(S.Context.PrintingPolicy))); + + Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs(); + for (unsigned I = 0; I != NumParams; ++I) { + if (I) + Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + + std::string ArgString; + QualType ArgType; + + if (FDecl) { + ArgString = FDecl->getParamDecl(I)->getNameAsString(); + ArgType = FDecl->getParamDecl(I)->getOriginalType(); + } else { + ArgType = Proto->getArgType(I); + } + + ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy); + + if (I == CurrentArg) + Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, + Result.getAllocator().CopyString(ArgString))); + else + Result.AddTextChunk(Result.getAllocator().CopyString(ArgString)); + } + + if (Proto && Proto->isVariadic()) { + Result.AddChunk(Chunk(CodeCompletionString::CK_Comma)); + if (CurrentArg < NumParams) + Result.AddTextChunk("..."); + else + Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "...")); + } + Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + + return Result.TakeString(); +} + +unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName, + const LangOptions &LangOpts, + bool PreferredTypeIsPointer) { + unsigned Priority = CCP_Macro; + + // Treat the "nil", "Nil" and "NULL" macros as null pointer constants. + if (MacroName.equals("nil") || MacroName.equals("NULL") || + MacroName.equals("Nil")) { + Priority = CCP_Constant; + if (PreferredTypeIsPointer) + Priority = Priority / CCF_SimilarTypeMatch; + } + // Treat "YES", "NO", "true", and "false" as constants. + else if (MacroName.equals("YES") || MacroName.equals("NO") || + MacroName.equals("true") || MacroName.equals("false")) + Priority = CCP_Constant; + // Treat "bool" as a type. + else if (MacroName.equals("bool")) + Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0); + + + return Priority; +} + +CXCursorKind clang::getCursorKindForDecl(Decl *D) { + if (!D) + return CXCursor_UnexposedDecl; + + switch (D->getKind()) { + case Decl::Enum: return CXCursor_EnumDecl; + case Decl::EnumConstant: return CXCursor_EnumConstantDecl; + case Decl::Field: return CXCursor_FieldDecl; + case Decl::Function: + return CXCursor_FunctionDecl; + case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; + case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; + case Decl::ObjCClass: + // FIXME + return CXCursor_UnexposedDecl; + case Decl::ObjCForwardProtocol: + // FIXME + return CXCursor_UnexposedDecl; + case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; + case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; + case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; + case Decl::ObjCMethod: + return cast<ObjCMethodDecl>(D)->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl; + case Decl::CXXMethod: return CXCursor_CXXMethod; + case Decl::CXXConstructor: return CXCursor_Constructor; + case Decl::CXXDestructor: return CXCursor_Destructor; + case Decl::CXXConversion: return CXCursor_ConversionFunction; + case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl; + case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; + case Decl::ParmVar: return CXCursor_ParmDecl; + case Decl::Typedef: return CXCursor_TypedefDecl; + case Decl::TypeAlias: return CXCursor_TypeAliasDecl; + case Decl::Var: return CXCursor_VarDecl; + case Decl::Namespace: return CXCursor_Namespace; + case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; + case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter; + case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter; + case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter; + case Decl::FunctionTemplate: return CXCursor_FunctionTemplate; + case Decl::ClassTemplate: return CXCursor_ClassTemplate; + case Decl::ClassTemplatePartialSpecialization: + return CXCursor_ClassTemplatePartialSpecialization; + case Decl::UsingDirective: return CXCursor_UsingDirective; + + case Decl::Using: + case Decl::UnresolvedUsingValue: + case Decl::UnresolvedUsingTypename: + return CXCursor_UsingDeclaration; + + case Decl::ObjCPropertyImpl: + switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { + case ObjCPropertyImplDecl::Dynamic: + return CXCursor_ObjCDynamicDecl; + + case ObjCPropertyImplDecl::Synthesize: + return CXCursor_ObjCSynthesizeDecl; + } + break; + + default: + if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + switch (TD->getTagKind()) { + case TTK_Struct: return CXCursor_StructDecl; + case TTK_Class: return CXCursor_ClassDecl; + case TTK_Union: return CXCursor_UnionDecl; + case TTK_Enum: return CXCursor_EnumDecl; + } + } + } + + return CXCursor_UnexposedDecl; +} + +static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, + bool TargetTypeIsPointer = false) { + typedef CodeCompletionResult Result; + + Results.EnterNewScope(); + + for (Preprocessor::macro_iterator M = PP.macro_begin(), + MEnd = PP.macro_end(); + M != MEnd; ++M) { + Results.AddResult(Result(M->first, + getMacroUsagePriority(M->first->getName(), + PP.getLangOptions(), + TargetTypeIsPointer))); + } + + Results.ExitScope(); + +} + +static void AddPrettyFunctionResults(const LangOptions &LangOpts, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + Results.EnterNewScope(); + + Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant)); + Results.AddResult(Result("__FUNCTION__", CCP_Constant)); + if (LangOpts.C99 || LangOpts.CPlusPlus0x) + Results.AddResult(Result("__func__", CCP_Constant)); + Results.ExitScope(); +} + +static void HandleCodeCompleteResults(Sema *S, + CodeCompleteConsumer *CodeCompleter, + CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) { + if (CodeCompleter) + CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); +} + +static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, + Sema::ParserCompletionContext PCC) { + switch (PCC) { + case Sema::PCC_Namespace: + return CodeCompletionContext::CCC_TopLevel; + + case Sema::PCC_Class: + return CodeCompletionContext::CCC_ClassStructUnion; + + case Sema::PCC_ObjCInterface: + return CodeCompletionContext::CCC_ObjCInterface; + + case Sema::PCC_ObjCImplementation: + return CodeCompletionContext::CCC_ObjCImplementation; + + case Sema::PCC_ObjCInstanceVariableList: + return CodeCompletionContext::CCC_ObjCIvarList; + + case Sema::PCC_Template: + case Sema::PCC_MemberTemplate: + if (S.CurContext->isFileContext()) + return CodeCompletionContext::CCC_TopLevel; + else if (S.CurContext->isRecord()) + return CodeCompletionContext::CCC_ClassStructUnion; + else + return CodeCompletionContext::CCC_Other; + + case Sema::PCC_RecoveryInFunction: + return CodeCompletionContext::CCC_Recovery; + + case Sema::PCC_ForInit: + if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 || + S.getLangOptions().ObjC1) + return CodeCompletionContext::CCC_ParenthesizedExpression; + else + return CodeCompletionContext::CCC_Expression; + + case Sema::PCC_Expression: + case Sema::PCC_Condition: + return CodeCompletionContext::CCC_Expression; + + case Sema::PCC_Statement: + return CodeCompletionContext::CCC_Statement; + + case Sema::PCC_Type: + return CodeCompletionContext::CCC_Type; + + case Sema::PCC_ParenthesizedExpression: + return CodeCompletionContext::CCC_ParenthesizedExpression; + + case Sema::PCC_LocalDeclarationSpecifiers: + return CodeCompletionContext::CCC_Type; + } + + return CodeCompletionContext::CCC_Other; +} + +/// \brief If we're in a C++ virtual member function, add completion results +/// that invoke the functions we override, since it's common to invoke the +/// overridden function as well as adding new functionality. +/// +/// \param S The semantic analysis object for which we are generating results. +/// +/// \param InContext This context in which the nested-name-specifier preceding +/// the code-completion point +static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, + ResultBuilder &Results) { + // Look through blocks. + DeclContext *CurContext = S.CurContext; + while (isa<BlockDecl>(CurContext)) + CurContext = CurContext->getParent(); + + + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext); + if (!Method || !Method->isVirtual()) + return; + + // We need to have names for all of the parameters, if we're going to + // generate a forwarding call. + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; + ++P) { + if (!(*P)->getDeclName()) + return; + } + + for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(), + MEnd = Method->end_overridden_methods(); + M != MEnd; ++M) { + CodeCompletionBuilder Builder(Results.getAllocator()); + CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M); + if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) + continue; + + // If we need a nested-name-specifier, add one now. + if (!InContext) { + NestedNameSpecifier *NNS + = getRequiredQualification(S.Context, CurContext, + Overridden->getDeclContext()); + if (NNS) { + std::string Str; + llvm::raw_string_ostream OS(Str); + NNS->print(OS, S.Context.PrintingPolicy); + Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str())); + } + } else if (!InContext->Equals(Overridden->getDeclContext())) + continue; + + Builder.AddTypedTextChunk(Results.getAllocator().CopyString( + Overridden->getNameAsString())); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + bool FirstParam = true; + for (CXXMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; ++P) { + if (FirstParam) + FirstParam = false; + else + Builder.AddChunk(CodeCompletionString::CK_Comma); + + Builder.AddPlaceholderChunk(Results.getAllocator().CopyString( + (*P)->getIdentifier()->getName())); + } + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + CCP_SuperCompletion, + CXCursor_CXXMethod)); + Results.Ignore(Overridden); + } +} + +void Sema::CodeCompleteOrdinaryName(Scope *S, + ParserCompletionContext CompletionContext) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + mapCodeCompletionContext(*this, CompletionContext)); + Results.EnterNewScope(); + + // Determine how to filter results, e.g., so that the names of + // values (functions, enumerators, function templates, etc.) are + // only allowed where we can have an expression. + switch (CompletionContext) { + case PCC_Namespace: + case PCC_Class: + case PCC_ObjCInterface: + case PCC_ObjCImplementation: + case PCC_ObjCInstanceVariableList: + case PCC_Template: + case PCC_MemberTemplate: + case PCC_Type: + case PCC_LocalDeclarationSpecifiers: + Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); + break; + + case PCC_Statement: + case PCC_ParenthesizedExpression: + case PCC_Expression: + case PCC_ForInit: + case PCC_Condition: + if (WantTypesInContext(CompletionContext, getLangOptions())) + Results.setFilter(&ResultBuilder::IsOrdinaryName); + else + Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); + + if (getLangOptions().CPlusPlus) + MaybeAddOverrideCalls(*this, /*InContext=*/0, Results); + break; + + case PCC_RecoveryInFunction: + // Unfiltered + break; + } + + // If we are in a C++ non-static member function, check the qualifiers on + // the member function to filter/prioritize the results list. + if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) + if (CurMethod->isInstance()) + Results.setObjectTypeQualifiers( + Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers())); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + AddOrdinaryNameResults(CompletionContext, S, *this, Results); + Results.ExitScope(); + + switch (CompletionContext) { + case PCC_ParenthesizedExpression: + case PCC_Expression: + case PCC_Statement: + case PCC_RecoveryInFunction: + if (S->getFnParent()) + AddPrettyFunctionResults(PP.getLangOptions(), Results); + break; + + case PCC_Namespace: + case PCC_Class: + case PCC_ObjCInterface: + case PCC_ObjCImplementation: + case PCC_ObjCInstanceVariableList: + case PCC_Template: + case PCC_MemberTemplate: + case PCC_ForInit: + case PCC_Condition: + case PCC_Type: + case PCC_LocalDeclarationSpecifiers: + break; + } + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(),Results.size()); +} + +static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, + ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + bool IsSuper, + ResultBuilder &Results); + +void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, + bool AllowNonIdentifiers, + bool AllowNestedNameSpecifiers) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + AllowNestedNameSpecifiers + ? CodeCompletionContext::CCC_PotentiallyQualifiedName + : CodeCompletionContext::CCC_Name); + Results.EnterNewScope(); + + // Type qualifiers can come after names. + Results.AddResult(Result("const")); + Results.AddResult(Result("volatile")); + if (getLangOptions().C99) + Results.AddResult(Result("restrict")); + + if (getLangOptions().CPlusPlus) { + if (AllowNonIdentifiers) { + Results.AddResult(Result("operator")); + } + + // Add nested-name-specifiers. + if (AllowNestedNameSpecifiers) { + Results.allowNestedNameSpecifiers(); + Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, + CodeCompleter->includeGlobals()); + Results.setFilter(0); + } + } + Results.ExitScope(); + + // If we're in a context where we might have an expression (rather than a + // declaration), and what we've seen so far is an Objective-C type that could + // be a receiver of a class message, this may be a class message send with + // the initial opening bracket '[' missing. Add appropriate completions. + if (AllowNonIdentifiers && !AllowNestedNameSpecifiers && + DS.getTypeSpecType() == DeclSpec::TST_typename && + DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified && + !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() && + DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && + DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && + DS.getTypeQualifiers() == 0 && + S && + (S->getFlags() & Scope::DeclScope) != 0 && + (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | + Scope::FunctionPrototypeScope | + Scope::AtCatchScope)) == 0) { + ParsedType T = DS.getRepAsType(); + if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) + AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results); + } + + // Note that we intentionally suppress macro results here, since we do not + // encourage using macros to produce the names of entities. + + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(), Results.size()); +} + +struct Sema::CodeCompleteExpressionData { + CodeCompleteExpressionData(QualType PreferredType = QualType()) + : PreferredType(PreferredType), IntegralConstantExpression(false), + ObjCCollection(false) { } + + QualType PreferredType; + bool IntegralConstantExpression; + bool ObjCCollection; + llvm::SmallVector<Decl *, 4> IgnoreDecls; +}; + +/// \brief Perform code-completion in an expression context when we know what +/// type we're looking for. +/// +/// \param IntegralConstantExpression Only permit integral constant +/// expressions. +void Sema::CodeCompleteExpression(Scope *S, + const CodeCompleteExpressionData &Data) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Expression); + if (Data.ObjCCollection) + Results.setFilter(&ResultBuilder::IsObjCCollection); + else if (Data.IntegralConstantExpression) + Results.setFilter(&ResultBuilder::IsIntegralConstantValue); + else if (WantTypesInContext(PCC_Expression, getLangOptions())) + Results.setFilter(&ResultBuilder::IsOrdinaryName); + else + Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); + + if (!Data.PreferredType.isNull()) + Results.setPreferredType(Data.PreferredType.getNonReferenceType()); + + // Ignore any declarations that we were told that we don't care about. + for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I) + Results.Ignore(Data.IgnoreDecls[I]); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + Results.EnterNewScope(); + AddOrdinaryNameResults(PCC_Expression, S, *this, Results); + Results.ExitScope(); + + bool PreferredTypeIsPointer = false; + if (!Data.PreferredType.isNull()) + PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() + || Data.PreferredType->isMemberPointerType() + || Data.PreferredType->isBlockPointerType(); + + if (S->getFnParent() && + !Data.ObjCCollection && + !Data.IntegralConstantExpression) + AddPrettyFunctionResults(PP.getLangOptions(), Results); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results, PreferredTypeIsPointer); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext(CodeCompletionContext::CCC_Expression, + Data.PreferredType), + Results.data(),Results.size()); +} + +void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { + if (E.isInvalid()) + CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); + else if (getLangOptions().ObjC1) + CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false); +} + +/// \brief The set of properties that have already been added, referenced by +/// property name. +typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet; + +static void AddObjCProperties(ObjCContainerDecl *Container, + bool AllowCategories, + bool AllowNullaryMethods, + DeclContext *CurContext, + AddedPropertiesSet &AddedProperties, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + // Add properties in this container. + for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(), + PEnd = Container->prop_end(); + P != PEnd; + ++P) { + if (AddedProperties.insert(P->getIdentifier())) + Results.MaybeAddResult(Result(*P, 0), CurContext); + } + + // Add nullary methods + if (AllowNullaryMethods) { + ASTContext &Context = Container->getASTContext(); + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if (M->getSelector().isUnarySelector()) + if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0)) + if (AddedProperties.insert(Name)) { + CodeCompletionBuilder Builder(Results.getAllocator()); + AddResultTypeChunk(Context, *M, Builder); + Builder.AddTypedTextChunk( + Results.getAllocator().CopyString(Name->getName())); + + CXAvailabilityKind Availability = CXAvailability_Available; + switch (M->getAvailability()) { + case AR_Available: + case AR_NotYetIntroduced: + Availability = CXAvailability_Available; + break; + + case AR_Deprecated: + Availability = CXAvailability_Deprecated; + break; + + case AR_Unavailable: + Availability = CXAvailability_NotAvailable; + break; + } + + Results.MaybeAddResult(Result(Builder.TakeString(), + CCP_MemberDeclaration + CCD_MethodAsProperty, + M->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl, + Availability), + CurContext); + } + } + } + + + // Add properties in referenced protocols. + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), + PEnd = Protocol->protocol_end(); + P != PEnd; ++P) + AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); + } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ + if (AllowCategories) { + // Look through categories. + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + AddObjCProperties(Category, AllowCategories, AllowNullaryMethods, + CurContext, AddedProperties, Results); + } + + // Look through protocols. + for (ObjCInterfaceDecl::all_protocol_iterator + I = IFace->all_referenced_protocol_begin(), + E = IFace->all_referenced_protocol_end(); I != E; ++I) + AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); + + // Look in the superclass. + if (IFace->getSuperClass()) + AddObjCProperties(IFace->getSuperClass(), AllowCategories, + AllowNullaryMethods, CurContext, + AddedProperties, Results); + } else if (const ObjCCategoryDecl *Category + = dyn_cast<ObjCCategoryDecl>(Container)) { + // Look through protocols. + for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), + PEnd = Category->protocol_end(); + P != PEnd; ++P) + AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, + AddedProperties, Results); + } +} + +void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, + SourceLocation OpLoc, + bool IsArrow) { + if (!BaseE || !CodeCompleter) + return; + + typedef CodeCompletionResult Result; + + Expr *Base = static_cast<Expr *>(BaseE); + QualType BaseType = Base->getType(); + + if (IsArrow) { + if (const PointerType *Ptr = BaseType->getAs<PointerType>()) + BaseType = Ptr->getPointeeType(); + else if (BaseType->isObjCObjectPointerType()) + /*Do nothing*/ ; + else + return; + } + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess, + BaseType), + &ResultBuilder::IsMember); + Results.EnterNewScope(); + if (const RecordType *Record = BaseType->getAs<RecordType>()) { + // Indicate that we are performing a member access, and the cv-qualifiers + // for the base object type. + Results.setObjectTypeQualifiers(BaseType.getQualifiers()); + + // Access to a C/C++ class, struct, or union. + Results.allowNestedNameSpecifiers(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, + CodeCompleter->includeGlobals()); + + if (getLangOptions().CPlusPlus) { + if (!Results.empty()) { + // The "template" keyword can follow "->" or "." in the grammar. + // However, we only want to suggest the template keyword if something + // is dependent. + bool IsDependent = BaseType->isDependentType(); + if (!IsDependent) { + for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) + if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) { + IsDependent = Ctx->isDependentContext(); + break; + } + } + + if (IsDependent) + Results.AddResult(Result("template")); + } + } + } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) { + // Objective-C property reference. + AddedPropertiesSet AddedProperties; + + // Add property results based on our interface. + const ObjCObjectPointerType *ObjCPtr + = BaseType->getAsObjCInterfacePointerType(); + assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); + AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, + /*AllowNullaryMethods=*/true, CurContext, + AddedProperties, Results); + + // Add properties from the protocols in a qualified interface. + for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(), + E = ObjCPtr->qual_end(); + I != E; ++I) + AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext, + AddedProperties, Results); + } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || + (!IsArrow && BaseType->isObjCObjectType())) { + // Objective-C instance variable access. + ObjCInterfaceDecl *Class = 0; + if (const ObjCObjectPointerType *ObjCPtr + = BaseType->getAs<ObjCObjectPointerType>()) + Class = ObjCPtr->getInterfaceDecl(); + else + Class = BaseType->getAs<ObjCObjectType>()->getInterface(); + + // Add all ivars from this class and its superclasses. + if (Class) { + CodeCompletionDeclConsumer Consumer(Results, CurContext); + Results.setFilter(&ResultBuilder::IsObjCIvar); + LookupVisibleDecls(Class, LookupMemberName, Consumer, + CodeCompleter->includeGlobals()); + } + } + + // FIXME: How do we cope with isa? + + Results.ExitScope(); + + // Hand off the results found for code completion. + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { + if (!CodeCompleter) + return; + + typedef CodeCompletionResult Result; + ResultBuilder::LookupFilter Filter = 0; + enum CodeCompletionContext::Kind ContextKind + = CodeCompletionContext::CCC_Other; + switch ((DeclSpec::TST)TagSpec) { + case DeclSpec::TST_enum: + Filter = &ResultBuilder::IsEnum; + ContextKind = CodeCompletionContext::CCC_EnumTag; + break; + + case DeclSpec::TST_union: + Filter = &ResultBuilder::IsUnion; + ContextKind = CodeCompletionContext::CCC_UnionTag; + break; + + case DeclSpec::TST_struct: + case DeclSpec::TST_class: + Filter = &ResultBuilder::IsClassOrStruct; + ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; + break; + + default: + assert(false && "Unknown type specifier kind in CodeCompleteTag"); + return; + } + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + + // First pass: look for tags. + Results.setFilter(Filter); + LookupVisibleDecls(S, LookupTagName, Consumer, + CodeCompleter->includeGlobals()); + + if (CodeCompleter->includeGlobals()) { + // Second pass: look for nested name specifiers. + Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); + LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); + } + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_TypeQualifiers); + Results.EnterNewScope(); + if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) + Results.AddResult("const"); + if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) + Results.AddResult("volatile"); + if (getLangOptions().C99 && + !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) + Results.AddResult("restrict"); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(), Results.size()); +} + +void Sema::CodeCompleteCase(Scope *S) { + if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) + return; + + SwitchStmt *Switch = getCurFunction()->SwitchStack.back(); + if (!Switch->getCond()->getType()->isEnumeralType()) { + CodeCompleteExpressionData Data(Switch->getCond()->getType()); + Data.IntegralConstantExpression = true; + CodeCompleteExpression(S, Data); + return; + } + + // Code-complete the cases of a switch statement over an enumeration type + // by providing the list of + EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl(); + + // Determine which enumerators we have already seen in the switch statement. + // FIXME: Ideally, we would also be able to look *past* the code-completion + // token, in case we are code-completing in the middle of the switch and not + // at the end. However, we aren't able to do so at the moment. + llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen; + NestedNameSpecifier *Qualifier = 0; + for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + CaseStmt *Case = dyn_cast<CaseStmt>(SC); + if (!Case) + continue; + + Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal)) + if (EnumConstantDecl *Enumerator + = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + // We look into the AST of the case statement to determine which + // enumerator was named. Alternatively, we could compute the value of + // the integral constant expression, then compare it against the + // values of each enumerator. However, value-based approach would not + // work as well with C++ templates where enumerators declared within a + // template are type- and value-dependent. + EnumeratorsSeen.insert(Enumerator); + + // If this is a qualified-id, keep track of the nested-name-specifier + // so that we can reproduce it as part of code completion, e.g., + // + // switch (TagD.getKind()) { + // case TagDecl::TK_enum: + // break; + // case XXX + // + // At the XXX, our completions are TagDecl::TK_union, + // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union, + // TK_struct, and TK_class. + Qualifier = DRE->getQualifier(); + } + } + + if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) { + // If there are no prior enumerators in C++, check whether we have to + // qualify the names of the enumerators that we suggest, because they + // may not be visible in this scope. + Qualifier = getRequiredQualification(Context, CurContext, + Enum->getDeclContext()); + + // FIXME: Scoped enums need to start with "EnumDecl" as the context! + } + + // Add any enumerators that have not yet been mentioned. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Expression); + Results.EnterNewScope(); + for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(), + EEnd = Enum->enumerator_end(); + E != EEnd; ++E) { + if (EnumeratorsSeen.count(*E)) + continue; + + CodeCompletionResult R(*E, Qualifier); + R.Priority = CCP_EnumInCase; + Results.AddResult(R, CurContext, 0, false); + } + Results.ExitScope(); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_OtherWithMacros, + Results.data(),Results.size()); +} + +namespace { + struct IsBetterOverloadCandidate { + Sema &S; + SourceLocation Loc; + + public: + explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc) + : S(S), Loc(Loc) { } + + bool + operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const { + return isBetterOverloadCandidate(S, X, Y, Loc); + } + }; +} + +static bool anyNullArguments(Expr **Args, unsigned NumArgs) { + if (NumArgs && !Args) + return true; + + for (unsigned I = 0; I != NumArgs; ++I) + if (!Args[I]) + return true; + + return false; +} + +void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, + ExprTy **ArgsIn, unsigned NumArgs) { + if (!CodeCompleter) + return; + + // When we're code-completing for a call, we fall back to ordinary + // name code-completion whenever we can't produce specific + // results. We may want to revisit this strategy in the future, + // e.g., by merging the two kinds of results. + + Expr *Fn = (Expr *)FnIn; + Expr **Args = (Expr **)ArgsIn; + + // Ignore type-dependent call expressions entirely. + if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) || + Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { + CodeCompleteOrdinaryName(S, PCC_Expression); + return; + } + + // Build an overload candidate set based on the functions we find. + SourceLocation Loc = Fn->getExprLoc(); + OverloadCandidateSet CandidateSet(Loc); + + // FIXME: What if we're calling something that isn't a function declaration? + // FIXME: What if we're calling a pseudo-destructor? + // FIXME: What if we're calling a member function? + + typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; + llvm::SmallVector<ResultCandidate, 8> Results; + + Expr *NakedFn = Fn->IgnoreParenCasts(); + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) + AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet, + /*PartialOverloading=*/ true); + else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { + FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); + if (FDecl) { + if (!getLangOptions().CPlusPlus || + !FDecl->getType()->getAs<FunctionProtoType>()) + Results.push_back(ResultCandidate(FDecl)); + else + // FIXME: access? + AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), + Args, NumArgs, CandidateSet, + false, /*PartialOverloading*/true); + } + } + + QualType ParamType; + + if (!CandidateSet.empty()) { + // Sort the overload candidate set by placing the best overloads first. + std::stable_sort(CandidateSet.begin(), CandidateSet.end(), + IsBetterOverloadCandidate(*this, Loc)); + + // Add the remaining viable overload candidates as code-completion reslults. + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), + CandEnd = CandidateSet.end(); + Cand != CandEnd; ++Cand) { + if (Cand->Viable) + Results.push_back(ResultCandidate(Cand->Function)); + } + + // From the viable candidates, try to determine the type of this parameter. + for (unsigned I = 0, N = Results.size(); I != N; ++I) { + if (const FunctionType *FType = Results[I].getFunctionType()) + if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType)) + if (NumArgs < Proto->getNumArgs()) { + if (ParamType.isNull()) + ParamType = Proto->getArgType(NumArgs); + else if (!Context.hasSameUnqualifiedType( + ParamType.getNonReferenceType(), + Proto->getArgType(NumArgs).getNonReferenceType())) { + ParamType = QualType(); + break; + } + } + } + } else { + // Try to determine the parameter type from the type of the expression + // being called. + QualType FunctionType = Fn->getType(); + if (const PointerType *Ptr = FunctionType->getAs<PointerType>()) + FunctionType = Ptr->getPointeeType(); + else if (const BlockPointerType *BlockPtr + = FunctionType->getAs<BlockPointerType>()) + FunctionType = BlockPtr->getPointeeType(); + else if (const MemberPointerType *MemPtr + = FunctionType->getAs<MemberPointerType>()) + FunctionType = MemPtr->getPointeeType(); + + if (const FunctionProtoType *Proto + = FunctionType->getAs<FunctionProtoType>()) { + if (NumArgs < Proto->getNumArgs()) + ParamType = Proto->getArgType(NumArgs); + } + } + + if (ParamType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, ParamType); + + if (!Results.empty()) + CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), + Results.size()); +} + +void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { + ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D); + if (!VD) { + CodeCompleteOrdinaryName(S, PCC_Expression); + return; + } + + CodeCompleteExpression(S, VD->getType()); +} + +void Sema::CodeCompleteReturn(Scope *S) { + QualType ResultType; + if (isa<BlockDecl>(CurContext)) { + if (BlockScopeInfo *BSI = getCurBlock()) + ResultType = BSI->ReturnType; + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext)) + ResultType = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext)) + ResultType = Method->getResultType(); + + if (ResultType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, ResultType); +} + +void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { + if (LHS) + CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType()); + else + CodeCompleteOrdinaryName(S, PCC_Expression); +} + +void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, + bool EnteringContext) { + if (!SS.getScopeRep() || !CodeCompleter) + return; + + DeclContext *Ctx = computeDeclContext(SS, EnteringContext); + if (!Ctx) + return; + + // Try to instantiate any non-dependent declaration contexts before + // we look in them. + if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx)) + return; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Name); + Results.EnterNewScope(); + + // The "template" keyword can follow "::" in the grammar, but only + // put it into the grammar if the nested-name-specifier is dependent. + NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); + if (!Results.empty() && NNS->isDependent()) + Results.AddResult("template"); + + // Add calls to overridden virtual functions, if there are any. + // + // FIXME: This isn't wonderful, because we don't know whether we're actually + // in a context that permits expressions. This is a general issue with + // qualified-id completions. + if (!EnteringContext) + MaybeAddOverrideCalls(*this, Ctx, Results); + Results.ExitScope(); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Name, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteUsing(Scope *S) { + if (!CodeCompleter) + return; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_PotentiallyQualifiedName, + &ResultBuilder::IsNestedNameSpecifier); + Results.EnterNewScope(); + + // If we aren't in class scope, we could see the "namespace" keyword. + if (!S->isClassScope()) + Results.AddResult(CodeCompletionResult("namespace")); + + // After "using", we can see anything that would start a + // nested-name-specifier. + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_PotentiallyQualifiedName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteUsingDirective(Scope *S) { + if (!CodeCompleter) + return; + + // After "using namespace", we expect to see a namespace name or namespace + // alias. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Namespace, + &ResultBuilder::IsNamespaceOrAlias); + Results.EnterNewScope(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Namespace, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteNamespaceDecl(Scope *S) { + if (!CodeCompleter) + return; + + DeclContext *Ctx = (DeclContext *)S->getEntity(); + if (!S->getParent()) + Ctx = Context.getTranslationUnitDecl(); + + bool SuppressedGlobalResults + = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + SuppressedGlobalResults + ? CodeCompletionContext::CCC_Namespace + : CodeCompletionContext::CCC_Other, + &ResultBuilder::IsNamespace); + + if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { + // We only want to see those namespaces that have already been defined + // within this scope, because its likely that the user is creating an + // extended namespace declaration. Keep track of the most recent + // definition of each namespace. + std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest; + for (DeclContext::specific_decl_iterator<NamespaceDecl> + NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end()); + NS != NSEnd; ++NS) + OrigToLatest[NS->getOriginalNamespace()] = *NS; + + // Add the most recent definition (or extended definition) of each + // namespace to the list of results. + Results.EnterNewScope(); + for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator + NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end(); + NS != NSEnd; ++NS) + Results.AddResult(CodeCompletionResult(NS->second, 0), + CurContext, 0, false); + Results.ExitScope(); + } + + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { + if (!CodeCompleter) + return; + + // After "namespace", we expect to see a namespace or alias. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Namespace, + &ResultBuilder::IsNamespaceOrAlias); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + HandleCodeCompleteResults(this, CodeCompleter, + Results.getCompletionContext(), + Results.data(),Results.size()); +} + +void Sema::CodeCompleteOperatorName(Scope *S) { + if (!CodeCompleter) + return; + + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Type, + &ResultBuilder::IsType); + Results.EnterNewScope(); + + // Add the names of overloadable operators. +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + if (std::strcmp(Spelling, "?")) \ + Results.AddResult(Result(Spelling)); +#include "clang/Basic/OperatorKinds.def" + + // Add any type names visible from the current scope + Results.allowNestedNameSpecifiers(); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + // Add any type specifiers + AddTypeSpecifierResults(getLangOptions(), Results); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Type, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, + CXXCtorInitializer** Initializers, + unsigned NumInitializers) { + CXXConstructorDecl *Constructor + = static_cast<CXXConstructorDecl *>(ConstructorD); + if (!Constructor) + return; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_PotentiallyQualifiedName); + Results.EnterNewScope(); + + // Fill in any already-initialized fields or base classes. + llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; + llvm::SmallPtrSet<CanQualType, 4> InitializedBases; + for (unsigned I = 0; I != NumInitializers; ++I) { + if (Initializers[I]->isBaseInitializer()) + InitializedBases.insert( + Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0))); + else + InitializedFields.insert(cast<FieldDecl>( + Initializers[I]->getAnyMember())); + } + + // Add completions for base classes. + CodeCompletionBuilder Builder(Results.getAllocator()); + bool SawLastInitializer = (NumInitializers == 0); + CXXRecordDecl *ClassDecl = Constructor->getParent(); + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isBaseInitializer() && + Context.hasSameUnqualifiedType(Base->getType(), + QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); + continue; + } + + Builder.AddTypedTextChunk( + Results.getAllocator().CopyString( + Base->getType().getAsString(Context.PrintingPolicy))); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; + } + + // Add completions for virtual base classes. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; ++Base) { + if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isBaseInitializer() && + Context.hasSameUnqualifiedType(Base->getType(), + QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); + continue; + } + + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString( + Base->getType().getAsString(Context.PrintingPolicy))); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; + } + + // Add completions for members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isAnyMemberInitializer() && + Initializers[NumInitializers - 1]->getAnyMember() == *Field; + continue; + } + + if (!Field->getDeclName()) + continue; + + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Field->getIdentifier()->getName())); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration, + CXCursor_MemberRef)); + SawLastInitializer = false; + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + +// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is +// true or false. +#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword +static void AddObjCImplementationResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt) { + typedef CodeCompletionResult Result; + // Since we have an implementation, we can end it. + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); + + CodeCompletionBuilder Builder(Results.getAllocator()); + if (LangOpts.ObjC2) { + // @dynamic + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("property"); + Results.AddResult(Result(Builder.TakeString())); + + // @synthesize + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("property"); + Results.AddResult(Result(Builder.TakeString())); + } +} + +static void AddObjCInterfaceResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt) { + typedef CodeCompletionResult Result; + + // Since we have an interface or protocol, we can end it. + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); + + if (LangOpts.ObjC2) { + // @property + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property))); + + // @required + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required))); + + // @optional + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional))); + } +} + +static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { + typedef CodeCompletionResult Result; + CodeCompletionBuilder Builder(Results.getAllocator()); + + // @class name ; + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("name"); + Results.AddResult(Result(Builder.TakeString())); + + if (Results.includeCodePatterns()) { + // @interface name + // FIXME: Could introduce the whole pattern, including superclasses and + // such. + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("class"); + Results.AddResult(Result(Builder.TakeString())); + + // @protocol name + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("protocol"); + Results.AddResult(Result(Builder.TakeString())); + + // @implementation name + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("class"); + Results.AddResult(Result(Builder.TakeString())); + } + + // @compatibility_alias name + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("alias"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("class"); + Results.AddResult(Result(Builder.TakeString())); +} + +void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl, + bool InInterface) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + if (ObjCImpDecl) + AddObjCImplementationResults(getLangOptions(), Results, false); + else if (InInterface) + AddObjCInterfaceResults(getLangOptions(), Results, false); + else + AddObjCTopLevelResults(Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { + typedef CodeCompletionResult Result; + CodeCompletionBuilder Builder(Results.getAllocator()); + + // @encode ( type-name ) + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode)); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("type-name"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // @protocol ( protocol-name ) + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol)); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("protocol-name"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); + + // @selector ( selector ) + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector)); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("selector"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Builder.TakeString())); +} + +static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { + typedef CodeCompletionResult Result; + CodeCompletionBuilder Builder(Results.getAllocator()); + + if (Results.includeCodePatterns()) { + // @try { statements } @catch ( declaration ) { statements } @finally + // { statements } + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try)); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("@catch"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("parameter"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Builder.AddTextChunk("@finally"); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } + + // @throw + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Results.AddResult(Result(Builder.TakeString())); + + if (Results.includeCodePatterns()) { + // @synchronized ( expression ) { statements } + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized)); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddPlaceholderChunk("statements"); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Builder.TakeString())); + } +} + +static void AddObjCVisibilityResults(const LangOptions &LangOpts, + ResultBuilder &Results, + bool NeedAt) { + typedef CodeCompletionResult Result; + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected))); + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public))); + if (LangOpts.ObjC2) + Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package))); +} + +void Sema::CodeCompleteObjCAtVisibility(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + AddObjCVisibilityResults(getLangOptions(), Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCAtStatement(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + AddObjCStatementResults(Results, false); + AddObjCExpressionResults(Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCAtExpression(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + AddObjCExpressionResults(Results, false); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +/// \brief Determine whether the addition of the given flag to an Objective-C +/// property's attributes will cause a conflict. +static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { + // Check if we've already added this flag. + if (Attributes & NewFlag) + return true; + + Attributes |= NewFlag; + + // Check for collisions with "readonly". + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | + ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain))) + return true; + + // Check for more than one of { assign, copy, retain }. + unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain); + if (AssignCopyRetMask && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain) + return true; + + return false; +} + +void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { + if (!CodeCompleter) + return; + + unsigned Attributes = ODS.getPropertyAttributes(); + + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) + Results.AddResult(CodeCompletionResult("readonly")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign)) + Results.AddResult(CodeCompletionResult("assign")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite)) + Results.AddResult(CodeCompletionResult("readwrite")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain)) + Results.AddResult(CodeCompletionResult("retain")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy)) + Results.AddResult(CodeCompletionResult("copy")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic)) + Results.AddResult(CodeCompletionResult("nonatomic")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) + Results.AddResult(CodeCompletionResult("atomic")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { + CodeCompletionBuilder Setter(Results.getAllocator()); + Setter.AddTypedTextChunk("setter"); + Setter.AddTextChunk(" = "); + Setter.AddPlaceholderChunk("method"); + Results.AddResult(CodeCompletionResult(Setter.TakeString())); + } + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) { + CodeCompletionBuilder Getter(Results.getAllocator()); + Getter.AddTypedTextChunk("getter"); + Getter.AddTextChunk(" = "); + Getter.AddPlaceholderChunk("method"); + Results.AddResult(CodeCompletionResult(Getter.TakeString())); + } + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +/// \brief Descripts the kind of Objective-C method that we want to find +/// via code completion. +enum ObjCMethodKind { + MK_Any, //< Any kind of method, provided it means other specified criteria. + MK_ZeroArgSelector, //< Zero-argument (unary) selector. + MK_OneArgSelector //< One-argument selector. +}; + +static bool isAcceptableObjCSelector(Selector Sel, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AllowSameLength = true) { + if (NumSelIdents > Sel.getNumArgs()) + return false; + + switch (WantKind) { + case MK_Any: break; + case MK_ZeroArgSelector: return Sel.isUnarySelector(); + case MK_OneArgSelector: return Sel.getNumArgs() == 1; + } + + if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs()) + return false; + + for (unsigned I = 0; I != NumSelIdents; ++I) + if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I)) + return false; + + return true; +} + +static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AllowSameLength = true) { + return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents, + NumSelIdents, AllowSameLength); +} + +namespace { + /// \brief A set of selectors, which is used to avoid introducing multiple + /// completions with the same selector into the result set. + typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet; +} + +/// \brief Add all of the Objective-C methods in the given Objective-C +/// container to the set of results. +/// +/// The container will be a class, protocol, category, or implementation of +/// any of the above. This mether will recurse to include methods from +/// the superclasses of classes along with their categories, protocols, and +/// implementations. +/// +/// \param Container the container in which we'll look to find methods. +/// +/// \param WantInstance whether to add instance methods (only); if false, this +/// routine will add factory methods (only). +/// +/// \param CurContext the context in which we're performing the lookup that +/// finds methods. +/// +/// \param AllowSameLength Whether we allow a method to be added to the list +/// when it has the same number of parameters as we have selector identifiers. +/// +/// \param Results the structure into which we'll add results. +static void AddObjCMethods(ObjCContainerDecl *Container, + bool WantInstanceMethods, + ObjCMethodKind WantKind, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + DeclContext *CurContext, + VisitedSelectorSet &Selectors, + bool AllowSameLength, + ResultBuilder &Results, + bool InOriginalClass = true) { + typedef CodeCompletionResult Result; + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if ((*M)->isInstanceMethod() == WantInstanceMethods) { + // Check whether the selector identifiers we've been given are a + // subset of the identifiers for this particular method. + if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents, + AllowSameLength)) + continue; + + if (!Selectors.insert((*M)->getSelector())) + continue; + + Result R = Result(*M, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = (WantKind != MK_Any); + if (!InOriginalClass) + R.Priority += CCD_InBaseClass; + Results.MaybeAddResult(R, CurContext); + } + } + + // Visit the protocols of protocols. + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + const ObjCList<ObjCProtocolDecl> &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, + CurContext, Selectors, AllowSameLength, Results, false); + } + + ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); + if (!IFace) + return; + + // Add methods in protocols. + const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, + CurContext, Selectors, AllowSameLength, Results, false); + + // Add methods in categories. + for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; + CatDecl = CatDecl->getNextClassCategory()) { + AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, InOriginalClass); + + // Add a categories protocol methods. + const ObjCList<ObjCProtocolDecl> &Protocols + = CatDecl->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, false); + + // Add methods in category implementations. + if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, InOriginalClass); + } + + // Add methods in superclass. + if (IFace->getSuperClass()) + AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, + SelIdents, NumSelIdents, CurContext, Selectors, + AllowSameLength, Results, false); + + // Add methods in our implementation, if any. + if (ObjCImplementationDecl *Impl = IFace->getImplementation()) + AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, + NumSelIdents, CurContext, Selectors, AllowSameLength, + Results, InOriginalClass); +} + + +void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) { + typedef CodeCompletionResult Result; + + // Try to find the interface where getters might live. + ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl); + if (!Class) { + if (ObjCCategoryDecl *Category + = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl)) + Class = Category->getClassInterface(); + + if (!Class) + return; + } + + // Find all of the potential getters. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + VisitedSelectorSet Selectors; + AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors, + /*AllowSameLength=*/true, Results); + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) { + typedef CodeCompletionResult Result; + + // Try to find the interface where setters might live. + ObjCInterfaceDecl *Class + = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl); + if (!Class) { + if (ObjCCategoryDecl *Category + = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl)) + Class = Category->getClassInterface(); + + if (!Class) + return; + } + + // Find all of the potential getters. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + VisitedSelectorSet Selectors; + AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, + Selectors, /*AllowSameLength=*/true, Results); + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, + bool IsParameter) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Type); + Results.EnterNewScope(); + + // Add context-sensitive, Objective-C parameter-passing keywords. + bool AddedInOut = false; + if ((DS.getObjCDeclQualifier() & + (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) { + Results.AddResult("in"); + Results.AddResult("inout"); + AddedInOut = true; + } + if ((DS.getObjCDeclQualifier() & + (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) { + Results.AddResult("out"); + if (!AddedInOut) + Results.AddResult("inout"); + } + if ((DS.getObjCDeclQualifier() & + (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref | + ObjCDeclSpec::DQ_Oneway)) == 0) { + Results.AddResult("bycopy"); + Results.AddResult("byref"); + Results.AddResult("oneway"); + } + + // If we're completing the return type of an Objective-C method and the + // identifier IBAction refers to a macro, provide a completion item for + // an action, e.g., + // IBAction)<#selector#>:(id)sender + if (DS.getObjCDeclQualifier() == 0 && !IsParameter && + Context.Idents.get("IBAction").hasMacroDefinition()) { + typedef CodeCompletionString::Chunk Chunk; + CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern, + CXAvailability_Available); + Builder.AddTypedTextChunk("IBAction"); + Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Builder.AddPlaceholderChunk("selector"); + Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon)); + Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen)); + Builder.AddTextChunk("id"); + Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen)); + Builder.AddTextChunk("sender"); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); + } + + // Add various builtin type names and specifiers. + AddOrdinaryNameResults(PCC_Type, S, *this, Results); + Results.ExitScope(); + + // Add the various type names + Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Type, + Results.data(), Results.size()); +} + +/// \brief When we have an expression with type "id", we may assume +/// that it has some more-specific class type based on knowledge of +/// common uses of Objective-C. This routine returns that class type, +/// or NULL if no better result could be determined. +static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { + ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E); + if (!Msg) + return 0; + + Selector Sel = Msg->getSelector(); + if (Sel.isNull()) + return 0; + + IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0); + if (!Id) + return 0; + + ObjCMethodDecl *Method = Msg->getMethodDecl(); + if (!Method) + return 0; + + // Determine the class that we're sending the message to. + ObjCInterfaceDecl *IFace = 0; + switch (Msg->getReceiverKind()) { + case ObjCMessageExpr::Class: + if (const ObjCObjectType *ObjType + = Msg->getClassReceiver()->getAs<ObjCObjectType>()) + IFace = ObjType->getInterface(); + break; + + case ObjCMessageExpr::Instance: { + QualType T = Msg->getInstanceReceiver()->getType(); + if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) + IFace = Ptr->getInterfaceDecl(); + break; + } + + case ObjCMessageExpr::SuperInstance: + case ObjCMessageExpr::SuperClass: + break; + } + + if (!IFace) + return 0; + + ObjCInterfaceDecl *Super = IFace->getSuperClass(); + if (Method->isInstanceMethod()) + return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) + .Case("retain", IFace) + .Case("autorelease", IFace) + .Case("copy", IFace) + .Case("copyWithZone", IFace) + .Case("mutableCopy", IFace) + .Case("mutableCopyWithZone", IFace) + .Case("awakeFromCoder", IFace) + .Case("replacementObjectFromCoder", IFace) + .Case("class", IFace) + .Case("classForCoder", IFace) + .Case("superclass", Super) + .Default(0); + + return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) + .Case("new", IFace) + .Case("alloc", IFace) + .Case("allocWithZone", IFace) + .Case("class", IFace) + .Case("superclass", Super) + .Default(0); +} + +// Add a special completion for a message send to "super", which fills in the +// most likely case of forwarding all of our arguments to the superclass +// function. +/// +/// \param S The semantic analysis object. +/// +/// \param S NeedSuperKeyword Whether we need to prefix this completion with +/// the "super" keyword. Otherwise, we just need to provide the arguments. +/// +/// \param SelIdents The identifiers in the selector that have already been +/// provided as arguments for a send to "super". +/// +/// \param NumSelIdents The number of identifiers in \p SelIdents. +/// +/// \param Results The set of results to augment. +/// +/// \returns the Objective-C method declaration that would be invoked by +/// this "super" completion. If NULL, no completion was added. +static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + ResultBuilder &Results) { + ObjCMethodDecl *CurMethod = S.getCurMethodDecl(); + if (!CurMethod) + return 0; + + ObjCInterfaceDecl *Class = CurMethod->getClassInterface(); + if (!Class) + return 0; + + // Try to find a superclass method with the same selector. + ObjCMethodDecl *SuperMethod = 0; + while ((Class = Class->getSuperClass()) && !SuperMethod) { + // Check in the class + SuperMethod = Class->getMethod(CurMethod->getSelector(), + CurMethod->isInstanceMethod()); + + // Check in categories or class extensions. + if (!SuperMethod) { + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + if ((SuperMethod = Category->getMethod(CurMethod->getSelector(), + CurMethod->isInstanceMethod()))) + break; + } + } + + if (!SuperMethod) + return 0; + + // Check whether the superclass method has the same signature. + if (CurMethod->param_size() != SuperMethod->param_size() || + CurMethod->isVariadic() != SuperMethod->isVariadic()) + return 0; + + for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(), + CurPEnd = CurMethod->param_end(), + SuperP = SuperMethod->param_begin(); + CurP != CurPEnd; ++CurP, ++SuperP) { + // Make sure the parameter types are compatible. + if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), + (*SuperP)->getType())) + return 0; + + // Make sure we have a parameter name to forward! + if (!(*CurP)->getIdentifier()) + return 0; + } + + // We have a superclass method. Now, form the send-to-super completion. + CodeCompletionBuilder Builder(Results.getAllocator()); + + // Give this completion a return type. + AddResultTypeChunk(S.Context, SuperMethod, Builder); + + // If we need the "super" keyword, add it (plus some spacing). + if (NeedSuperKeyword) { + Builder.AddTypedTextChunk("super"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + } + + Selector Sel = CurMethod->getSelector(); + if (Sel.isUnarySelector()) { + if (NeedSuperKeyword) + Builder.AddTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + else + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + } else { + ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); + for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { + if (I > NumSelIdents) + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + + if (I < NumSelIdents) + Builder.AddInformativeChunk( + Builder.getAllocator().CopyString( + Sel.getNameForSlot(I) + ":")); + else if (NeedSuperKeyword || I > NumSelIdents) { + Builder.AddTextChunk( + Builder.getAllocator().CopyString( + Sel.getNameForSlot(I) + ":")); + Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( + (*CurP)->getIdentifier()->getName())); + } else { + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString( + Sel.getNameForSlot(I) + ":")); + Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( + (*CurP)->getIdentifier()->getName())); + } + } + } + + Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion, + SuperMethod->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl)); + return SuperMethod; +} + +void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_ObjCMessageReceiver, + &ResultBuilder::IsObjCMessageReceiver); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + Results.EnterNewScope(); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer, + CodeCompleter->includeGlobals()); + + // If we are in an Objective-C method inside a class that has a superclass, + // add "super" as an option. + if (ObjCMethodDecl *Method = getCurMethodDecl()) + if (ObjCInterfaceDecl *Iface = Method->getClassInterface()) + if (Iface->getSuperClass()) { + Results.AddResult(Result("super")); + + AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results); + } + + Results.ExitScope(); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); + +} + +void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression) { + ObjCInterfaceDecl *CDecl = 0; + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + // Figure out which interface we're in. + CDecl = CurMethod->getClassInterface(); + if (!CDecl) + return; + + // Find the superclass of this class. + CDecl = CDecl->getSuperClass(); + if (!CDecl) + return; + + if (CurMethod->isInstanceMethod()) { + // We are inside an instance method, which means that the message + // send [super ...] is actually calling an instance method on the + // current object. + return CodeCompleteObjCInstanceMessage(S, 0, + SelIdents, NumSelIdents, + AtArgumentExpression, + CDecl); + } + + // Fall through to send to the superclass in CDecl. + } else { + // "super" may be the name of a type or variable. Figure out which + // it is. + IdentifierInfo *Super = &Context.Idents.get("super"); + NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, + LookupOrdinaryName); + if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) { + // "super" names an interface. Use it. + } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) { + if (const ObjCObjectType *Iface + = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>()) + CDecl = Iface->getInterface(); + } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) { + // "super" names an unresolved type; we can't be more specific. + } else { + // Assume that "super" names some kind of value and parse that way. + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(Super, SuperLoc); + ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false); + return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), + SelIdents, NumSelIdents, + AtArgumentExpression); + } + + // Fall through + } + + ParsedType Receiver; + if (CDecl) + Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); + return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, + NumSelIdents, AtArgumentExpression, + /*IsSuper=*/true); +} + +/// \brief Given a set of code-completion results for the argument of a message +/// send, determine the preferred type (if any) for that argument expression. +static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, + unsigned NumSelIdents) { + typedef CodeCompletionResult Result; + ASTContext &Context = Results.getSema().Context; + + QualType PreferredType; + unsigned BestPriority = CCP_Unlikely * 2; + Result *ResultsData = Results.data(); + for (unsigned I = 0, N = Results.size(); I != N; ++I) { + Result &R = ResultsData[I]; + if (R.Kind == Result::RK_Declaration && + isa<ObjCMethodDecl>(R.Declaration)) { + if (R.Priority <= BestPriority) { + ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration); + if (NumSelIdents <= Method->param_size()) { + QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1] + ->getType(); + if (R.Priority < BestPriority || PreferredType.isNull()) { + BestPriority = R.Priority; + PreferredType = MyPreferredType; + } else if (!Context.hasSameUnqualifiedType(PreferredType, + MyPreferredType)) { + PreferredType = QualType(); + } + } + } + } + } + + return PreferredType; +} + +static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, + ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + bool IsSuper, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + ObjCInterfaceDecl *CDecl = 0; + + // If the given name refers to an interface type, retrieve the + // corresponding declaration. + if (Receiver) { + QualType T = SemaRef.GetTypeFromParser(Receiver, 0); + if (!T.isNull()) + if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>()) + CDecl = Interface->getInterface(); + } + + // Add all of the factory methods in this Objective-C class, its protocols, + // superclasses, categories, implementation, etc. + Results.EnterNewScope(); + + // If this is a send-to-super, try to add the special "super" send + // completion. + if (IsSuper) { + if (ObjCMethodDecl *SuperMethod + = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents, + Results)) + Results.Ignore(SuperMethod); + } + + // If we're inside an Objective-C method definition, prefer its selector to + // others. + if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) + Results.setPreferredSelector(CurMethod->getSelector()); + + VisitedSelectorSet Selectors; + if (CDecl) + AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, + SemaRef.CurContext, Selectors, AtArgumentExpression, + Results); + else { + // We're messaging "id" as a type; provide all class/factory methods. + + // If we have an external source, load the entire class method + // pool from the AST file. + if (SemaRef.ExternalSource) { + for (uint32_t I = 0, + N = SemaRef.ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || SemaRef.MethodPool.count(Sel)) + continue; + + SemaRef.ReadMethodPool(Sel); + } + } + + for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), + MEnd = SemaRef.MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = &M->second.second; + MethList && MethList->Method; + MethList = MethList->Next) { + if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, + NumSelIdents)) + continue; + + Result R(MethList->Method, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = false; + Results.MaybeAddResult(R, SemaRef.CurContext); + } + } + } + + Results.ExitScope(); +} + +void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + bool IsSuper) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents, + AtArgumentExpression, IsSuper, Results); + + // If we're actually at the argument expression (rather than prior to the + // selector), we're actually performing code completion for an expression. + // Determine whether we have a single, best method. If so, we can + // code-complete the expression using the corresponding parameter type as + // our preferred type, improving completion results. + if (AtArgumentExpression) { + QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, + NumSelIdents); + if (PreferredType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, PreferredType); + return; + } + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(), Results.size()); +} + +void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, + IdentifierInfo **SelIdents, + unsigned NumSelIdents, + bool AtArgumentExpression, + ObjCInterfaceDecl *Super) { + typedef CodeCompletionResult Result; + + Expr *RecExpr = static_cast<Expr *>(Receiver); + + // If necessary, apply function/array conversion to the receiver. + // C99 6.7.5.3p[7,8]. + if (RecExpr) { + ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr); + if (Conv.isInvalid()) // conversion failed. bail. + return; + RecExpr = Conv.take(); + } + QualType ReceiverType = RecExpr? RecExpr->getType() + : Super? Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(Super)) + : Context.getObjCIdType(); + + // If we're messaging an expression with type "id" or "Class", check + // whether we know something special about the receiver that allows + // us to assume a more-specific receiver type. + if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) + if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) { + if (ReceiverType->isObjCClassType()) + return CodeCompleteObjCClassMessage(S, + ParsedType::make(Context.getObjCInterfaceType(IFace)), + SelIdents, NumSelIdents, + AtArgumentExpression, Super); + + ReceiverType = Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(IFace)); + } + + // Build the set of methods we can see. + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + // If this is a send-to-super, try to add the special "super" send + // completion. + if (Super) { + if (ObjCMethodDecl *SuperMethod + = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents, + Results)) + Results.Ignore(SuperMethod); + } + + // If we're inside an Objective-C method definition, prefer its selector to + // others. + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) + Results.setPreferredSelector(CurMethod->getSelector()); + + // Keep track of the selectors we've already added. + VisitedSelectorSet Selectors; + + // Handle messages to Class. This really isn't a message to an instance + // method, so we treat it the same way we would treat a message send to a + // class method. + if (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()) { + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { + if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) + AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents, + CurContext, Selectors, AtArgumentExpression, Results); + } + } + // Handle messages to a qualified ID ("id<foo>"). + else if (const ObjCObjectPointerType *QualID + = ReceiverType->getAsObjCQualifiedIdType()) { + // Search protocols for instance methods. + for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(), + E = QualID->qual_end(); + I != E; ++I) + AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + Selectors, AtArgumentExpression, Results); + } + // Handle messages to a pointer to interface type. + else if (const ObjCObjectPointerType *IFacePtr + = ReceiverType->getAsObjCInterfacePointerType()) { + // Search the class, its superclasses, etc., for instance methods. + AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, + NumSelIdents, CurContext, Selectors, AtArgumentExpression, + Results); + + // Search protocols for instance methods. + for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(), + E = IFacePtr->qual_end(); + I != E; ++I) + AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, + Selectors, AtArgumentExpression, Results); + } + // Handle messages to "id". + else if (ReceiverType->isObjCIdType()) { + // We're messaging "id", so provide all instance methods we know + // about as code-completion results. + + // If we have an external source, load the entire class method + // pool from the AST file. + if (ExternalSource) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || MethodPool.count(Sel)) + continue; + + ReadMethodPool(Sel); + } + } + + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = &M->second.first; + MethList && MethList->Method; + MethList = MethList->Next) { + if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, + NumSelIdents)) + continue; + + if (!Selectors.insert(MethList->Method->getSelector())) + continue; + + Result R(MethList->Method, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = false; + Results.MaybeAddResult(R, CurContext); + } + } + } + Results.ExitScope(); + + + // If we're actually at the argument expression (rather than prior to the + // selector), we're actually performing code completion for an expression. + // Determine whether we have a single, best method. If so, we can + // code-complete the expression using the corresponding parameter type as + // our preferred type, improving completion results. + if (AtArgumentExpression) { + QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, + NumSelIdents); + if (PreferredType.isNull()) + CodeCompleteOrdinaryName(S, PCC_Expression); + else + CodeCompleteExpression(S, PreferredType); + return; + } + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCForCollection(Scope *S, + DeclGroupPtrTy IterationVar) { + CodeCompleteExpressionData Data; + Data.ObjCCollection = true; + + if (IterationVar.getAsOpaquePtr()) { + DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>(); + for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) { + if (*I) + Data.IgnoreDecls.push_back(*I); + } + } + + CodeCompleteExpression(S, Data); +} + +void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, + unsigned NumSelIdents) { + // If we have an external source, load the entire class method + // pool from the AST file. + if (ExternalSource) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || MethodPool.count(Sel)) + continue; + + ReadMethodPool(Sel); + } + } + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_SelectorName); + Results.EnterNewScope(); + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + + Selector Sel = M->first; + if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents)) + continue; + + CodeCompletionBuilder Builder(Results.getAllocator()); + if (Sel.isUnarySelector()) { + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + Results.AddResult(Builder.TakeString()); + continue; + } + + std::string Accumulator; + for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { + if (I == NumSelIdents) { + if (!Accumulator.empty()) { + Builder.AddInformativeChunk(Builder.getAllocator().CopyString( + Accumulator)); + Accumulator.clear(); + } + } + + Accumulator += Sel.getNameForSlot(I).str(); + Accumulator += ':'; + } + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator)); + Results.AddResult(Builder.TakeString()); + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_SelectorName, + Results.data(), Results.size()); +} + +/// \brief Add all of the protocol declarations that we find in the given +/// (translation unit) context. +static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, + bool OnlyForwardDeclarations, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); + D != DEnd; ++D) { + // Record any protocols we find. + if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D)) + if (!OnlyForwardDeclarations || Proto->isForwardDecl()) + Results.AddResult(Result(Proto, 0), CurContext, 0, false); + + // Record any forward-declared protocols we find. + if (ObjCForwardProtocolDecl *Forward + = dyn_cast<ObjCForwardProtocolDecl>(*D)) { + for (ObjCForwardProtocolDecl::protocol_iterator + P = Forward->protocol_begin(), + PEnd = Forward->protocol_end(); + P != PEnd; ++P) + if (!OnlyForwardDeclarations || (*P)->isForwardDecl()) + Results.AddResult(Result(*P, 0), CurContext, 0, false); + } + } +} + +void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, + unsigned NumProtocols) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_ObjCProtocolName); + + if (CodeCompleter && CodeCompleter->includeGlobals()) { + Results.EnterNewScope(); + + // Tell the result set to ignore all of the protocols we have + // already seen. + // FIXME: This doesn't work when caching code-completion results. + for (unsigned I = 0; I != NumProtocols; ++I) + if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first, + Protocols[I].second)) + Results.Ignore(Protocol); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, + Results); + + Results.ExitScope(); + } + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCProtocolName, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCProtocolDecl(Scope *) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_ObjCProtocolName); + + if (CodeCompleter && CodeCompleter->includeGlobals()) { + Results.EnterNewScope(); + + // Add all protocols. + AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, + Results); + + Results.ExitScope(); + } + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_ObjCProtocolName, + Results.data(),Results.size()); +} + +/// \brief Add all of the Objective-C interface declarations that we find in +/// the given (translation unit) context. +static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, + bool OnlyForwardDeclarations, + bool OnlyUnimplemented, + ResultBuilder &Results) { + typedef CodeCompletionResult Result; + + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); + D != DEnd; ++D) { + // Record any interfaces we find. + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) + if ((!OnlyForwardDeclarations || Class->isForwardDecl()) && + (!OnlyUnimplemented || !Class->getImplementation())) + Results.AddResult(Result(Class, 0), CurContext, 0, false); + + // Record any forward-declared interfaces we find. + if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) { + for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end(); + C != CEnd; ++C) + if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) && + (!OnlyUnimplemented || !C->getInterface()->getImplementation())) + Results.AddResult(Result(C->getInterface(), 0), CurContext, + 0, false); + } + } +} + +void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + // Add all classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true, + false, Results); + + Results.ExitScope(); + // FIXME: Add a special context for this, use cached global completion + // results. + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + // Make sure that we ignore the class we're currently defining. + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + if (CurClass && isa<ObjCInterfaceDecl>(CurClass)) + Results.Ignore(CurClass); + + // Add all classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, + false, Results); + + Results.ExitScope(); + // FIXME: Add a special context for this, use cached global completion + // results. + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + + // Add all unimplemented classes. + AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, + true, Results); + + Results.ExitScope(); + // FIXME: Add a special context for this, use cached global completion + // results. + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + typedef CodeCompletionResult Result; + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + + // Ignore any categories we find that have already been implemented by this + // interface. + llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + CategoryNames.insert(Category->getIdentifier()); + + // Add all of the categories we know about. + Results.EnterNewScope(); + TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + for (DeclContext::decl_iterator D = TU->decls_begin(), + DEnd = TU->decls_end(); + D != DEnd; ++D) + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D)) + if (CategoryNames.insert(Category->getIdentifier())) + Results.AddResult(Result(Category, 0), CurContext, 0, false); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCImplementationCategory(Scope *S, + IdentifierInfo *ClassName, + SourceLocation ClassNameLoc) { + typedef CodeCompletionResult Result; + + // Find the corresponding interface. If we couldn't find the interface, the + // program itself is ill-formed. However, we'll try to be helpful still by + // providing the list of all of the categories we know about. + NamedDecl *CurClass + = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); + ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass); + if (!Class) + return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); + + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + + // Add all of the categories that have have corresponding interface + // declarations in this class and any of its superclasses, except for + // already-implemented categories in the class itself. + llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; + Results.EnterNewScope(); + bool IgnoreImplemented = true; + while (Class) { + for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + if ((!IgnoreImplemented || !Category->getImplementation()) && + CategoryNames.insert(Category->getIdentifier())) + Results.AddResult(Result(Category, 0), CurContext, 0, false); + + Class = Class->getSuperClass(); + IgnoreImplemented = false; + } + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + + // Figure out where this @synthesize lives. + ObjCContainerDecl *Container + = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl); + if (!Container || + (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) + return; + + // Ignore any properties that have already been implemented. + for (DeclContext::decl_iterator D = Container->decls_begin(), + DEnd = Container->decls_end(); + D != DEnd; ++D) + if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D)) + Results.Ignore(PropertyImpl->getPropertyDecl()); + + // Add any properties that we find. + AddedPropertiesSet AddedProperties; + Results.EnterNewScope(); + if (ObjCImplementationDecl *ClassImpl + = dyn_cast<ObjCImplementationDecl>(Container)) + AddObjCProperties(ClassImpl->getClassInterface(), false, + /*AllowNullaryMethods=*/false, CurContext, + AddedProperties, Results); + else + AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(), + false, /*AllowNullaryMethods=*/false, CurContext, + AddedProperties, Results); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, + IdentifierInfo *PropertyName, + Decl *ObjCImpDecl) { + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + + // Figure out where this @synthesize lives. + ObjCContainerDecl *Container + = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl); + if (!Container || + (!isa<ObjCImplementationDecl>(Container) && + !isa<ObjCCategoryImplDecl>(Container))) + return; + + // Figure out which interface we're looking into. + ObjCInterfaceDecl *Class = 0; + if (ObjCImplementationDecl *ClassImpl + = dyn_cast<ObjCImplementationDecl>(Container)) + Class = ClassImpl->getClassInterface(); + else + Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl() + ->getClassInterface(); + + // Determine the type of the property we're synthesizing. + QualType PropertyType = Context.getObjCIdType(); + if (Class) { + if (ObjCPropertyDecl *Property + = Class->FindPropertyDeclaration(PropertyName)) { + PropertyType + = Property->getType().getNonReferenceType().getUnqualifiedType(); + + // Give preference to ivars + Results.setPreferredType(PropertyType); + } + } + + // Add all of the instance variables in this class and its superclasses. + Results.EnterNewScope(); + bool SawSimilarlyNamedIvar = false; + std::string NameWithPrefix; + NameWithPrefix += '_'; + NameWithPrefix += PropertyName->getName().str(); + std::string NameWithSuffix = PropertyName->getName().str(); + NameWithSuffix += '_'; + for(; Class; Class = Class->getSuperClass()) { + for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; + Ivar = Ivar->getNextIvar()) { + Results.AddResult(Result(Ivar, 0), CurContext, 0, false); + + // Determine whether we've seen an ivar with a name similar to the + // property. + if ((PropertyName == Ivar->getIdentifier() || + NameWithPrefix == Ivar->getName() || + NameWithSuffix == Ivar->getName())) { + SawSimilarlyNamedIvar = true; + + // Reduce the priority of this result by one, to give it a slight + // advantage over other results whose names don't match so closely. + if (Results.size() && + Results.data()[Results.size() - 1].Kind + == CodeCompletionResult::RK_Declaration && + Results.data()[Results.size() - 1].Declaration == Ivar) + Results.data()[Results.size() - 1].Priority--; + } + } + } + + if (!SawSimilarlyNamedIvar) { + // Create ivar result _propName, that the user can use to synthesize + // an ivar of the appropriate type. + unsigned Priority = CCP_MemberDeclaration + 1; + typedef CodeCompletionResult Result; + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available); + + Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, + Allocator)); + Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); + Results.AddResult(Result(Builder.TakeString(), Priority, + CXCursor_ObjCIvarDecl)); + } + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +// Mapping from selectors to the methods that implement that selector, along +// with the "in original class" flag. +typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> > + KnownMethodsMap; + +/// \brief Find all of the methods that reside in the given container +/// (and its superclasses, protocols, etc.) that meet the given +/// criteria. Insert those methods into the map of known methods, +/// indexed by selector so they can be easily found. +static void FindImplementableMethods(ASTContext &Context, + ObjCContainerDecl *Container, + bool WantInstanceMethods, + QualType ReturnType, + KnownMethodsMap &KnownMethods, + bool InOriginalClass = true) { + if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) { + // Recurse into protocols. + const ObjCList<ObjCProtocolDecl> &Protocols + = IFace->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, InOriginalClass); + + // Add methods from any class extensions and categories. + for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat; + Cat = Cat->getNextClassCategory()) + FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat), + WantInstanceMethods, ReturnType, + KnownMethods, false); + + // Visit the superclass. + if (IFace->getSuperClass()) + FindImplementableMethods(Context, IFace->getSuperClass(), + WantInstanceMethods, ReturnType, + KnownMethods, false); + } + + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { + // Recurse into protocols. + const ObjCList<ObjCProtocolDecl> &Protocols + = Category->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, InOriginalClass); + + // If this category is the original class, jump to the interface. + if (InOriginalClass && Category->getClassInterface()) + FindImplementableMethods(Context, Category->getClassInterface(), + WantInstanceMethods, ReturnType, KnownMethods, + false); + } + + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + // Recurse into protocols. + const ObjCList<ObjCProtocolDecl> &Protocols + = Protocol->getReferencedProtocols(); + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), + E = Protocols.end(); + I != E; ++I) + FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, + KnownMethods, false); + } + + // Add methods in this container. This operation occurs last because + // we want the methods from this container to override any methods + // we've previously seen with the same selector. + for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), + MEnd = Container->meth_end(); + M != MEnd; ++M) { + if ((*M)->isInstanceMethod() == WantInstanceMethods) { + if (!ReturnType.isNull() && + !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType())) + continue; + + KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass); + } + } +} + +/// \brief Add the parenthesized return or parameter type chunk to a code +/// completion string. +static void AddObjCPassingTypeChunk(QualType Type, + ASTContext &Context, + CodeCompletionBuilder &Builder) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk(GetCompletionTypeString(Type, Context, + Builder.getAllocator())); + Builder.AddChunk(CodeCompletionString::CK_RightParen); +} + +/// \brief Determine whether the given class is or inherits from a class by +/// the given name. +static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, + llvm::StringRef Name) { + if (!Class) + return false; + + if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name) + return true; + + return InheritsFromClassNamed(Class->getSuperClass(), Name); +} + +/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and +/// Key-Value Observing (KVO). +static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, + bool IsInstanceMethod, + QualType ReturnType, + ASTContext &Context, + VisitedSelectorSet &KnownSelectors, + ResultBuilder &Results) { + IdentifierInfo *PropName = Property->getIdentifier(); + if (!PropName || PropName->getLength() == 0) + return; + + + // Builder that will create each code completion. + typedef CodeCompletionResult Result; + CodeCompletionAllocator &Allocator = Results.getAllocator(); + CodeCompletionBuilder Builder(Allocator); + + // The selector table. + SelectorTable &Selectors = Context.Selectors; + + // The property name, copied into the code completion allocation region + // on demand. + struct KeyHolder { + CodeCompletionAllocator &Allocator; + llvm::StringRef Key; + const char *CopiedKey; + + KeyHolder(CodeCompletionAllocator &Allocator, llvm::StringRef Key) + : Allocator(Allocator), Key(Key), CopiedKey(0) { } + + operator const char *() { + if (CopiedKey) + return CopiedKey; + + return CopiedKey = Allocator.CopyString(Key); + } + } Key(Allocator, PropName->getName()); + + // The uppercased name of the property name. + std::string UpperKey = PropName->getName(); + if (!UpperKey.empty()) + UpperKey[0] = toupper(UpperKey[0]); + + bool ReturnTypeMatchesProperty = ReturnType.isNull() || + Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), + Property->getType()); + bool ReturnTypeMatchesVoid + = ReturnType.isNull() || ReturnType->isVoidType(); + + // Add the normal accessor -(type)key. + if (IsInstanceMethod && + KnownSelectors.insert(Selectors.getNullarySelector(PropName)) && + ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) { + if (ReturnType.isNull()) + AddObjCPassingTypeChunk(Property->getType(), Context, Builder); + + Builder.AddTypedTextChunk(Key); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCInstanceMethodDecl)); + } + + // If we have an integral or boolean property (or the user has provided + // an integral or boolean return type), add the accessor -(type)isKey. + if (IsInstanceMethod && + ((!ReturnType.isNull() && + (ReturnType->isIntegerType() || ReturnType->isBooleanType())) || + (ReturnType.isNull() && + (Property->getType()->isIntegerType() || + Property->getType()->isBooleanType())))) { + std::string SelectorName = (llvm::Twine("is") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("BOOL"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk( + Allocator.CopyString(SelectorId->getName())); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Add the normal mutator. + if (IsInstanceMethod && ReturnTypeMatchesVoid && + !Property->getSetterMethodDecl()) { + std::string SelectorName = (llvm::Twine("set") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk( + Allocator.CopyString(SelectorId->getName())); + Builder.AddTypedTextChunk(":"); + AddObjCPassingTypeChunk(Property->getType(), Context, Builder); + Builder.AddTextChunk(Key); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Indexed and unordered accessors + unsigned IndexedGetterPriority = CCP_CodePattern; + unsigned IndexedSetterPriority = CCP_CodePattern; + unsigned UnorderedGetterPriority = CCP_CodePattern; + unsigned UnorderedSetterPriority = CCP_CodePattern; + if (const ObjCObjectPointerType *ObjCPointer + = Property->getType()->getAs<ObjCObjectPointerType>()) { + if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) { + // If this interface type is not provably derived from a known + // collection, penalize the corresponding completions. + if (!InheritsFromClassNamed(IFace, "NSMutableArray")) { + IndexedSetterPriority += CCD_ProbablyNotObjCCollection; + if (!InheritsFromClassNamed(IFace, "NSArray")) + IndexedGetterPriority += CCD_ProbablyNotObjCCollection; + } + + if (!InheritsFromClassNamed(IFace, "NSMutableSet")) { + UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; + if (!InheritsFromClassNamed(IFace, "NSSet")) + UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; + } + } + } else { + IndexedGetterPriority += CCD_ProbablyNotObjCCollection; + IndexedSetterPriority += CCD_ProbablyNotObjCCollection; + UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; + UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; + } + + // Add -(NSUInteger)countOf<key> + if (IsInstanceMethod && + (ReturnType.isNull() || ReturnType->isIntegerType())) { + std::string SelectorName = (llvm::Twine("countOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk( + Allocator.CopyString(SelectorId->getName())); + Results.AddResult(Result(Builder.TakeString(), + std::min(IndexedGetterPriority, + UnorderedGetterPriority), + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Indexed getters + // Add -(id)objectInKeyAtIndex:(NSUInteger)index + if (IsInstanceMethod && + (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { + std::string SelectorName + = (llvm::Twine("objectIn") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("id"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes + if (IsInstanceMethod && + (ReturnType.isNull() || + (ReturnType->isObjCObjectPointerType() && + ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && + ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() + ->getName() == "NSArray"))) { + std::string SelectorName + = (llvm::Twine(Property->getName()) + "AtIndexes").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSArray *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Add -(void)getKey:(type **)buffer range:(NSRange)inRange + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (llvm::Twine("get") + UpperKey).str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName), + &Context.Idents.get("range") + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" **"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("buffer"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk("range:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSRange"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("inRange"); + Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Mutable indexed accessors + + // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (llvm::Twine("in") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get("insertObject"), + &Context.Idents.get(SelectorName) + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk("insertObject:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (llvm::Twine("insert") + UpperKey).str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName), + &Context.Idents.get("atIndexes") + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSArray *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("array"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk("atIndexes:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (llvm::Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (llvm::Twine("remove") + UpperKey + "AtIndexes").str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (llvm::Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName), + &Context.Idents.get("withObject") + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSUInteger"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("index"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk("withObject:"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("id"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName1 + = (llvm::Twine("replace") + UpperKey + "AtIndexes").str(); + std::string SelectorName2 = (llvm::Twine("with") + UpperKey).str(); + IdentifierInfo *SelectorIds[2] = { + &Context.Idents.get(SelectorName1), + &Context.Idents.get(SelectorName2) + }; + + if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("NSIndexSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("indexes"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSArray *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("array"); + Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Unordered getters + // - (NSEnumerator *)enumeratorOfKey + if (IsInstanceMethod && + (ReturnType.isNull() || + (ReturnType->isObjCObjectPointerType() && + ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && + ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() + ->getName() == "NSEnumerator"))) { + std::string SelectorName = (llvm::Twine("enumeratorOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSEnumerator *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); + Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (type *)memberOfKey:(type *)object + if (IsInstanceMethod && + (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { + std::string SelectorName = (llvm::Twine("memberOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + if (ReturnType.isNull()) { + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + } else { + Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, + Builder.getAllocator())); + } + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Mutable unordered accessors + // - (void)addKeyObject:(type *)object + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (llvm::Twine("add") + UpperKey + llvm::Twine("Object")).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)addKey:(NSSet *)objects + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (llvm::Twine("add") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("objects"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)removeKeyObject:(type *)object + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName + = (llvm::Twine("remove") + UpperKey + llvm::Twine("Object")).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("object-type"); + Builder.AddTextChunk(" *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("object"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)removeKey:(NSSet *)objects + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (llvm::Twine("remove") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("objects"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // - (void)intersectKey:(NSSet *)objects + if (IsInstanceMethod && ReturnTypeMatchesVoid) { + std::string SelectorName = (llvm::Twine("intersect") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("void"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Builder.AddTextChunk("objects"); + Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, + CXCursor_ObjCInstanceMethodDecl)); + } + } + + // Key-Value Observing + // + (NSSet *)keyPathsForValuesAffectingKey + if (!IsInstanceMethod && + (ReturnType.isNull() || + (ReturnType->isObjCObjectPointerType() && + ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && + ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() + ->getName() == "NSSet"))) { + std::string SelectorName + = (llvm::Twine("keyPathsForValuesAffecting") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("NSSet *"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCClassMethodDecl)); + } + } + + // + (BOOL)automaticallyNotifiesObserversForKey + if (!IsInstanceMethod && + (ReturnType.isNull() || + ReturnType->isIntegerType() || + ReturnType->isBooleanType())) { + std::string SelectorName + = (llvm::Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); + IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); + if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { + if (ReturnType.isNull()) { + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddTextChunk("BOOL"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + } + + Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); + Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, + CXCursor_ObjCClassMethodDecl)); + } + } +} + +void Sema::CodeCompleteObjCMethodDecl(Scope *S, + bool IsInstanceMethod, + ParsedType ReturnTy, + Decl *IDecl) { + // Determine the return type of the method we're declaring, if + // provided. + QualType ReturnType = GetTypeFromParser(ReturnTy); + + // Determine where we should start searching for methods. + ObjCContainerDecl *SearchDecl = 0; + bool IsInImplementation = false; + if (Decl *D = IDecl) { + if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) { + SearchDecl = Impl->getClassInterface(); + IsInImplementation = true; + } else if (ObjCCategoryImplDecl *CatImpl + = dyn_cast<ObjCCategoryImplDecl>(D)) { + SearchDecl = CatImpl->getCategoryDecl(); + IsInImplementation = true; + } else + SearchDecl = dyn_cast<ObjCContainerDecl>(D); + } + + if (!SearchDecl && S) { + if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity())) + SearchDecl = dyn_cast<ObjCContainerDecl>(DC); + } + + if (!SearchDecl) { + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + 0, 0); + return; + } + + // Find all of the methods that we could declare/implement here. + KnownMethodsMap KnownMethods; + FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, + ReturnType, KnownMethods); + + // Add declarations or definitions for each of the known methods. + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + Results.EnterNewScope(); + PrintingPolicy Policy(Context.PrintingPolicy); + Policy.AnonymousTagLocations = false; + for (KnownMethodsMap::iterator M = KnownMethods.begin(), + MEnd = KnownMethods.end(); + M != MEnd; ++M) { + ObjCMethodDecl *Method = M->second.first; + CodeCompletionBuilder Builder(Results.getAllocator()); + + // If the result type was not already provided, add it to the + // pattern as (type). + if (ReturnType.isNull()) + AddObjCPassingTypeChunk(Method->getResultType(), Context, Builder); + + Selector Sel = Method->getSelector(); + + // Add the first part of the selector to the pattern. + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Sel.getNameForSlot(0))); + + // Add parameters to the pattern. + unsigned I = 0; + for (ObjCMethodDecl::param_iterator P = Method->param_begin(), + PEnd = Method->param_end(); + P != PEnd; (void)++P, ++I) { + // Add the part of the selector name. + if (I == 0) + Builder.AddTypedTextChunk(":"); + else if (I < Sel.getNumArgs()) { + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTypedTextChunk( + Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); + } else + break; + + // Add the parameter type. + AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Builder); + + if (IdentifierInfo *Id = (*P)->getIdentifier()) + Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); + } + + if (Method->isVariadic()) { + if (Method->param_size() > 0) + Builder.AddChunk(CodeCompletionString::CK_Comma); + Builder.AddTextChunk("..."); + } + + if (IsInImplementation && Results.includeCodePatterns()) { + // We will be defining the method here, so add a compound statement. + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftBrace); + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + if (!Method->getResultType()->isVoidType()) { + // If the result type is not void, add a return clause. + Builder.AddTextChunk("return"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("expression"); + Builder.AddChunk(CodeCompletionString::CK_SemiColon); + } else + Builder.AddPlaceholderChunk("statements"); + + Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); + Builder.AddChunk(CodeCompletionString::CK_RightBrace); + } + + unsigned Priority = CCP_CodePattern; + if (!M->second.second) + Priority += CCD_InBaseClass; + + Results.AddResult(Result(Builder.TakeString(), Priority, + Method->isInstanceMethod() + ? CXCursor_ObjCInstanceMethodDecl + : CXCursor_ObjCClassMethodDecl)); + } + + // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of + // the properties in this class and its categories. + if (Context.getLangOptions().ObjC2) { + llvm::SmallVector<ObjCContainerDecl *, 4> Containers; + Containers.push_back(SearchDecl); + + VisitedSelectorSet KnownSelectors; + for (KnownMethodsMap::iterator M = KnownMethods.begin(), + MEnd = KnownMethods.end(); + M != MEnd; ++M) + KnownSelectors.insert(M->first); + + + ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl); + if (!IFace) + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl)) + IFace = Category->getClassInterface(); + + if (IFace) { + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category; + Category = Category->getNextClassCategory()) + Containers.push_back(Category); + } + + for (unsigned I = 0, N = Containers.size(); I != N; ++I) { + for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(), + PEnd = Containers[I]->prop_end(); + P != PEnd; ++P) { + AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context, + KnownSelectors, Results); + } + } + } + + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, + bool IsInstanceMethod, + bool AtParameterName, + ParsedType ReturnTy, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { + // If we have an external source, load the entire class method + // pool from the AST file. + if (ExternalSource) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || MethodPool.count(Sel)) + continue; + + ReadMethodPool(Sel); + } + } + + // Build the set of methods we can see. + typedef CodeCompletionResult Result; + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_Other); + + if (ReturnTy) + Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); + + Results.EnterNewScope(); + for (GlobalMethodPool::iterator M = MethodPool.begin(), + MEnd = MethodPool.end(); + M != MEnd; ++M) { + for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : + &M->second.second; + MethList && MethList->Method; + MethList = MethList->Next) { + if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, + NumSelIdents)) + continue; + + if (AtParameterName) { + // Suggest parameter names we've seen before. + if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) { + ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1]; + if (Param->getIdentifier()) { + CodeCompletionBuilder Builder(Results.getAllocator()); + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + Param->getIdentifier()->getName())); + Results.AddResult(Builder.TakeString()); + } + } + + continue; + } + + Result R(MethList->Method, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = false; + R.DeclaringEntity = true; + Results.MaybeAddResult(R, CurContext); + } + } + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_Other, + Results.data(),Results.size()); +} + +void Sema::CodeCompletePreprocessorDirective(bool InConditional) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_PreprocessorDirective); + Results.EnterNewScope(); + + // #if <condition> + CodeCompletionBuilder Builder(Results.getAllocator()); + Builder.AddTypedTextChunk("if"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("condition"); + Results.AddResult(Builder.TakeString()); + + // #ifdef <macro> + Builder.AddTypedTextChunk("ifdef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + // #ifndef <macro> + Builder.AddTypedTextChunk("ifndef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + if (InConditional) { + // #elif <condition> + Builder.AddTypedTextChunk("elif"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("condition"); + Results.AddResult(Builder.TakeString()); + + // #else + Builder.AddTypedTextChunk("else"); + Results.AddResult(Builder.TakeString()); + + // #endif + Builder.AddTypedTextChunk("endif"); + Results.AddResult(Builder.TakeString()); + } + + // #include "header" + Builder.AddTypedTextChunk("include"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #include <header> + Builder.AddTypedTextChunk("include"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("<"); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk(">"); + Results.AddResult(Builder.TakeString()); + + // #define <macro> + Builder.AddTypedTextChunk("define"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + // #define <macro>(<args>) + Builder.AddTypedTextChunk("define"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("args"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Builder.TakeString()); + + // #undef <macro> + Builder.AddTypedTextChunk("undef"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("macro"); + Results.AddResult(Builder.TakeString()); + + // #line <number> + Builder.AddTypedTextChunk("line"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("number"); + Results.AddResult(Builder.TakeString()); + + // #line <number> "filename" + Builder.AddTypedTextChunk("line"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("number"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("filename"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #error <message> + Builder.AddTypedTextChunk("error"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("message"); + Results.AddResult(Builder.TakeString()); + + // #pragma <arguments> + Builder.AddTypedTextChunk("pragma"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("arguments"); + Results.AddResult(Builder.TakeString()); + + if (getLangOptions().ObjC1) { + // #import "header" + Builder.AddTypedTextChunk("import"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #import <header> + Builder.AddTypedTextChunk("import"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("<"); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk(">"); + Results.AddResult(Builder.TakeString()); + } + + // #include_next "header" + Builder.AddTypedTextChunk("include_next"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("\""); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk("\""); + Results.AddResult(Builder.TakeString()); + + // #include_next <header> + Builder.AddTypedTextChunk("include_next"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddTextChunk("<"); + Builder.AddPlaceholderChunk("header"); + Builder.AddTextChunk(">"); + Results.AddResult(Builder.TakeString()); + + // #warning <message> + Builder.AddTypedTextChunk("warning"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("message"); + Results.AddResult(Builder.TakeString()); + + // Note: #ident and #sccs are such crazy anachronisms that we don't provide + // completions for them. And __include_macros is a Clang-internal extension + // that we don't want to encourage anyone to use. + + // FIXME: we don't support #assert or #unassert, so don't suggest them. + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_PreprocessorDirective, + Results.data(), Results.size()); +} + +void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { + CodeCompleteOrdinaryName(S, + S->getFnParent()? Sema::PCC_RecoveryInFunction + : Sema::PCC_Namespace); +} + +void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + IsDefinition? CodeCompletionContext::CCC_MacroName + : CodeCompletionContext::CCC_MacroNameUse); + if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { + // Add just the names of macros, not their arguments. + CodeCompletionBuilder Builder(Results.getAllocator()); + Results.EnterNewScope(); + for (Preprocessor::macro_iterator M = PP.macro_begin(), + MEnd = PP.macro_end(); + M != MEnd; ++M) { + Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( + M->first->getName())); + Results.AddResult(Builder.TakeString()); + } + Results.ExitScope(); + } else if (IsDefinition) { + // FIXME: Can we detect when the user just wrote an include guard above? + } + + HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), + Results.data(), Results.size()); +} + +void Sema::CodeCompletePreprocessorExpression() { + ResultBuilder Results(*this, CodeCompleter->getAllocator(), + CodeCompletionContext::CCC_PreprocessorExpression); + + if (!CodeCompleter || CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + + // defined (<macro>) + Results.EnterNewScope(); + CodeCompletionBuilder Builder(Results.getAllocator()); + Builder.AddTypedTextChunk("defined"); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddChunk(CodeCompletionString::CK_LeftParen); + Builder.AddPlaceholderChunk("macro"); + Builder.AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Builder.TakeString()); + Results.ExitScope(); + + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_PreprocessorExpression, + Results.data(), Results.size()); +} + +void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, + IdentifierInfo *Macro, + MacroInfo *MacroInfo, + unsigned Argument) { + // FIXME: In the future, we could provide "overload" results, much like we + // do for function calls. + + CodeCompleteOrdinaryName(S, + S->getFnParent()? Sema::PCC_RecoveryInFunction + : Sema::PCC_Namespace); +} + +void Sema::CodeCompleteNaturalLanguage() { + HandleCodeCompleteResults(this, CodeCompleter, + CodeCompletionContext::CCC_NaturalLanguage, + 0, 0); +} + +void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, + llvm::SmallVectorImpl<CodeCompletionResult> &Results) { + ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery); + if (!CodeCompleter || CodeCompleter->includeGlobals()) { + CodeCompletionDeclConsumer Consumer(Builder, + Context.getTranslationUnitDecl()); + LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, + Consumer); + } + + if (!CodeCompleter || CodeCompleter->includeMacros()) + AddMacroResults(PP, Builder); + + Results.clear(); + Results.insert(Results.end(), + Builder.data(), Builder.data() + Builder.size()); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp new file mode 100644 index 0000000..9446c0e --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -0,0 +1,8872 @@ +//===--- SemaDecl.cpp - Semantic Analysis for Declarations ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for declarations. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "TypeLocBuilder.h" +#include "clang/AST/APValue.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/CharUnits.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +// FIXME: layering (ideally, Sema shouldn't be dependent on Lex API's) +#include "clang/Lex/Preprocessor.h" +#include "clang/Lex/HeaderSearch.h" +#include "llvm/ADT/Triple.h" +#include <algorithm> +#include <cstring> +#include <functional> +using namespace clang; +using namespace sema; + +Sema::DeclGroupPtrTy Sema::ConvertDeclToDeclGroup(Decl *Ptr) { + return DeclGroupPtrTy::make(DeclGroupRef(Ptr)); +} + +/// \brief If the identifier refers to a type name within this scope, +/// return the declaration of that type. +/// +/// This routine performs ordinary name lookup of the identifier II +/// within the given scope, with optional C++ scope specifier SS, to +/// determine whether the name refers to a type. If so, returns an +/// opaque pointer (actually a QualType) corresponding to that +/// type. Otherwise, returns NULL. +/// +/// If name lookup results in an ambiguity, this routine will complain +/// and then return NULL. +ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec *SS, + bool isClassName, bool HasTrailingDot, + ParsedType ObjectTypePtr, + bool WantNontrivialTypeSourceInfo) { + // Determine where we will perform name lookup. + DeclContext *LookupCtx = 0; + if (ObjectTypePtr) { + QualType ObjectType = ObjectTypePtr.get(); + if (ObjectType->isRecordType()) + LookupCtx = computeDeclContext(ObjectType); + } else if (SS && SS->isNotEmpty()) { + LookupCtx = computeDeclContext(*SS, false); + + if (!LookupCtx) { + if (isDependentScopeSpecifier(*SS)) { + // C++ [temp.res]p3: + // A qualified-id that refers to a type and in which the + // nested-name-specifier depends on a template-parameter (14.6.2) + // shall be prefixed by the keyword typename to indicate that the + // qualified-id denotes a type, forming an + // elaborated-type-specifier (7.1.5.3). + // + // We therefore do not perform any name lookup if the result would + // refer to a member of an unknown specialization. + if (!isClassName) + return ParsedType(); + + // We know from the grammar that this name refers to a type, + // so build a dependent node to describe the type. + if (WantNontrivialTypeSourceInfo) + return ActOnTypenameType(S, SourceLocation(), *SS, II, NameLoc).get(); + + NestedNameSpecifierLoc QualifierLoc = SS->getWithLocInContext(Context); + QualType T = + CheckTypenameType(ETK_None, SourceLocation(), QualifierLoc, + II, NameLoc); + + return ParsedType::make(T); + } + + return ParsedType(); + } + + if (!LookupCtx->isDependentContext() && + RequireCompleteDeclContext(*SS, LookupCtx)) + return ParsedType(); + } + + // FIXME: LookupNestedNameSpecifierName isn't the right kind of + // lookup for class-names. + LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName : + LookupOrdinaryName; + LookupResult Result(*this, &II, NameLoc, Kind); + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + LookupQualifiedName(Result, LookupCtx); + + if (ObjectTypePtr && Result.empty()) { + // C++ [basic.lookup.classref]p3: + // If the unqualified-id is ~type-name, the type-name is looked up + // in the context of the entire postfix-expression. If the type T of + // the object expression is of a class type C, the type-name is also + // looked up in the scope of class C. At least one of the lookups shall + // find a name that refers to (possibly cv-qualified) T. + LookupName(Result, S); + } + } else { + // Perform unqualified name lookup. + LookupName(Result, S); + } + + NamedDecl *IIDecl = 0; + switch (Result.getResultKind()) { + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + Result.suppressDiagnostics(); + return ParsedType(); + + case LookupResult::Ambiguous: + // Recover from type-hiding ambiguities by hiding the type. We'll + // do the lookup again when looking for an object, and we can + // diagnose the error then. If we don't do this, then the error + // about hiding the type will be immediately followed by an error + // that only makes sense if the identifier was treated like a type. + if (Result.getAmbiguityKind() == LookupResult::AmbiguousTagHiding) { + Result.suppressDiagnostics(); + return ParsedType(); + } + + // Look to see if we have a type anywhere in the list of results. + for (LookupResult::iterator Res = Result.begin(), ResEnd = Result.end(); + Res != ResEnd; ++Res) { + if (isa<TypeDecl>(*Res) || isa<ObjCInterfaceDecl>(*Res)) { + if (!IIDecl || + (*Res)->getLocation().getRawEncoding() < + IIDecl->getLocation().getRawEncoding()) + IIDecl = *Res; + } + } + + if (!IIDecl) { + // None of the entities we found is a type, so there is no way + // to even assume that the result is a type. In this case, don't + // complain about the ambiguity. The parser will either try to + // perform this lookup again (e.g., as an object name), which + // will produce the ambiguity, or will complain that it expected + // a type name. + Result.suppressDiagnostics(); + return ParsedType(); + } + + // We found a type within the ambiguous lookup; diagnose the + // ambiguity and then return that type. This might be the right + // answer, or it might not be, but it suppresses any attempt to + // perform the name lookup again. + break; + + case LookupResult::Found: + IIDecl = Result.getFoundDecl(); + break; + } + + assert(IIDecl && "Didn't find decl"); + + QualType T; + if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { + DiagnoseUseOfDecl(IIDecl, NameLoc); + + if (T.isNull()) + T = Context.getTypeDeclType(TD); + + if (SS && SS->isNotEmpty()) { + if (WantNontrivialTypeSourceInfo) { + // Construct a type with type-source information. + TypeLocBuilder Builder; + Builder.pushTypeSpec(T).setNameLoc(NameLoc); + + T = getElaboratedType(ETK_None, *SS, T); + ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); + ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS->getWithLocInContext(Context)); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); + } else { + T = getElaboratedType(ETK_None, *SS, T); + } + } + } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { + (void)DiagnoseUseOfDecl(IDecl, NameLoc); + if (!HasTrailingDot) + T = Context.getObjCInterfaceType(IDecl); + } + + if (T.isNull()) { + // If it's not plausibly a type, suppress diagnostics. + Result.suppressDiagnostics(); + return ParsedType(); + } + return ParsedType::make(T); +} + +/// isTagName() - This method is called *for error recovery purposes only* +/// to determine if the specified name is a valid tag name ("struct foo"). If +/// so, this returns the TST for the tag corresponding to it (TST_enum, +/// TST_union, TST_struct, TST_class). This is used to diagnose cases in C +/// where the user forgot to specify the tag. +DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { + // Do a tag name lookup in this scope. + LookupResult R(*this, &II, SourceLocation(), LookupTagName); + LookupName(R, S, false); + R.suppressDiagnostics(); + if (R.getResultKind() == LookupResult::Found) + if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { + switch (TD->getTagKind()) { + default: return DeclSpec::TST_unspecified; + case TTK_Struct: return DeclSpec::TST_struct; + case TTK_Union: return DeclSpec::TST_union; + case TTK_Class: return DeclSpec::TST_class; + case TTK_Enum: return DeclSpec::TST_enum; + } + } + + return DeclSpec::TST_unspecified; +} + +/// isMicrosoftMissingTypename - In Microsoft mode, within class scope, +/// if a CXXScopeSpec's type is equal to the type of one of the base classes +/// then downgrade the missing typename error to a warning. +/// This is needed for MSVC compatibility; Example: +/// @code +/// template<class T> class A { +/// public: +/// typedef int TYPE; +/// }; +/// template<class T> class B : public A<T> { +/// public: +/// A<T>::TYPE a; // no typename required because A<T> is a base class. +/// }; +/// @endcode +bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) { + if (CurContext->isRecord()) { + const Type *Ty = SS->getScopeRep()->getAsType(); + + CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext); + for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), + BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) + if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType())) + return true; + } + return false; +} + +bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + CXXScopeSpec *SS, + ParsedType &SuggestedType) { + // We don't have anything to suggest (yet). + SuggestedType = ParsedType(); + + // There may have been a typo in the name of the type. Look up typo + // results, in case we have something that we can suggest. + LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName, + NotForRedeclaration); + + if (DeclarationName Corrected = CorrectTypo(Lookup, S, SS, 0, 0, CTC_Type)) { + if (NamedDecl *Result = Lookup.getAsSingle<NamedDecl>()) { + if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) && + !Result->isInvalidDecl()) { + // We found a similarly-named type or interface; suggest that. + if (!SS || !SS->isSet()) + Diag(IILoc, diag::err_unknown_typename_suggest) + << &II << Lookup.getLookupName() + << FixItHint::CreateReplacement(SourceRange(IILoc), + Result->getNameAsString()); + else if (DeclContext *DC = computeDeclContext(*SS, false)) + Diag(IILoc, diag::err_unknown_nested_typename_suggest) + << &II << DC << Lookup.getLookupName() << SS->getRange() + << FixItHint::CreateReplacement(SourceRange(IILoc), + Result->getNameAsString()); + else + llvm_unreachable("could not have corrected a typo here"); + + Diag(Result->getLocation(), diag::note_previous_decl) + << Result->getDeclName(); + + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, + false, false, ParsedType(), + /*NonTrivialTypeSourceInfo=*/true); + return true; + } + } else if (Lookup.empty()) { + // We corrected to a keyword. + // FIXME: Actually recover with the keyword we suggest, and emit a fix-it. + Diag(IILoc, diag::err_unknown_typename_suggest) + << &II << Corrected; + return true; + } + } + + if (getLangOptions().CPlusPlus) { + // See if II is a class template that the user forgot to pass arguments to. + UnqualifiedId Name; + Name.setIdentifier(&II, IILoc); + CXXScopeSpec EmptySS; + TemplateTy TemplateResult; + bool MemberOfUnknownSpecialization; + if (isTemplateName(S, SS ? *SS : EmptySS, /*hasTemplateKeyword=*/false, + Name, ParsedType(), true, TemplateResult, + MemberOfUnknownSpecialization) == TNK_Type_template) { + TemplateName TplName = TemplateResult.getAsVal<TemplateName>(); + Diag(IILoc, diag::err_template_missing_args) << TplName; + if (TemplateDecl *TplDecl = TplName.getAsTemplateDecl()) { + Diag(TplDecl->getLocation(), diag::note_template_decl_here) + << TplDecl->getTemplateParameters()->getSourceRange(); + } + return true; + } + } + + // FIXME: Should we move the logic that tries to recover from a missing tag + // (struct, union, enum) from Parser::ParseImplicitInt here, instead? + + if (!SS || (!SS->isSet() && !SS->isInvalid())) + Diag(IILoc, diag::err_unknown_typename) << &II; + else if (DeclContext *DC = computeDeclContext(*SS, false)) + Diag(IILoc, diag::err_typename_nested_not_found) + << &II << DC << SS->getRange(); + else if (isDependentScopeSpecifier(*SS)) { + unsigned DiagID = diag::err_typename_missing; + if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS)) + DiagID = diag::warn_typename_missing; + + Diag(SS->getRange().getBegin(), DiagID) + << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() + << SourceRange(SS->getRange().getBegin(), IILoc) + << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); + SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc).get(); + } else { + assert(SS && SS->isInvalid() && + "Invalid scope specifier has already been diagnosed"); + } + + return true; +} + +/// \brief Determine whether the given result set contains either a type name +/// or +static bool isResultTypeOrTemplate(LookupResult &R, const Token &NextToken) { + bool CheckTemplate = R.getSema().getLangOptions().CPlusPlus && + NextToken.is(tok::less); + + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) { + if (isa<TypeDecl>(*I) || isa<ObjCInterfaceDecl>(*I)) + return true; + + if (CheckTemplate && isa<TemplateDecl>(*I)) + return true; + } + + return false; +} + +Sema::NameClassification Sema::ClassifyName(Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *&Name, + SourceLocation NameLoc, + const Token &NextToken) { + DeclarationNameInfo NameInfo(Name, NameLoc); + ObjCMethodDecl *CurMethod = getCurMethodDecl(); + + if (NextToken.is(tok::coloncolon)) { + BuildCXXNestedNameSpecifier(S, *Name, NameLoc, NextToken.getLocation(), + QualType(), false, SS, 0, false); + + } + + LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); + LookupParsedName(Result, S, &SS, !CurMethod); + + // Perform lookup for Objective-C instance variables (including automatically + // synthesized instance variables), if we're in an Objective-C method. + // FIXME: This lookup really, really needs to be folded in to the normal + // unqualified lookup mechanism. + if (!SS.isSet() && CurMethod && !isResultTypeOrTemplate(Result, NextToken)) { + ExprResult E = LookupInObjCMethod(Result, S, Name, true); + if (E.get() || E.isInvalid()) + return E; + + // Synthesize ivars lazily. + if (getLangOptions().ObjCDefaultSynthProperties && + getLangOptions().ObjCNonFragileABI2) { + if (SynthesizeProvisionalIvar(Result, Name, NameLoc)) { + if (const ObjCPropertyDecl *Property = + canSynthesizeProvisionalIvar(Name)) { + Diag(NameLoc, diag::warn_synthesized_ivar_access) << Name; + Diag(Property->getLocation(), diag::note_property_declare); + } + + // FIXME: This is strange. Shouldn't we just take the ivar returned + // from SynthesizeProvisionalIvar and continue with that? + E = LookupInObjCMethod(Result, S, Name, true); + if (E.get() || E.isInvalid()) + return E; + } + } + } + + bool SecondTry = false; + bool IsFilteredTemplateName = false; + +Corrected: + switch (Result.getResultKind()) { + case LookupResult::NotFound: + // If an unqualified-id is followed by a '(', then we have a function + // call. + if (!SS.isSet() && NextToken.is(tok::l_paren)) { + // In C++, this is an ADL-only call. + // FIXME: Reference? + if (getLangOptions().CPlusPlus) + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/true); + + // C90 6.3.2.2: + // If the expression that precedes the parenthesized argument list in a + // function call consists solely of an identifier, and if no + // declaration is visible for this identifier, the identifier is + // implicitly declared exactly as if, in the innermost block containing + // the function call, the declaration + // + // extern int identifier (); + // + // appeared. + // + // We also allow this in C99 as an extension. + if (NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *Name, S)) { + Result.addDecl(D); + Result.resolveKind(); + return BuildDeclarationNameExpr(SS, Result, /*ADL=*/false); + } + } + + // In C, we first see whether there is a tag type by the same name, in + // which case it's likely that the user just forget to write "enum", + // "struct", or "union". + if (!getLangOptions().CPlusPlus && !SecondTry) { + Result.clear(LookupTagName); + LookupParsedName(Result, S, &SS); + if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) { + const char *TagName = 0; + const char *FixItTagName = 0; + switch (Tag->getTagKind()) { + case TTK_Class: + TagName = "class"; + FixItTagName = "class "; + break; + + case TTK_Enum: + TagName = "enum"; + FixItTagName = "enum "; + break; + + case TTK_Struct: + TagName = "struct"; + FixItTagName = "struct "; + break; + + case TTK_Union: + TagName = "union"; + FixItTagName = "union "; + break; + } + + Diag(NameLoc, diag::err_use_of_tag_name_without_tag) + << Name << TagName << getLangOptions().CPlusPlus + << FixItHint::CreateInsertion(NameLoc, FixItTagName); + break; + } + + Result.clear(LookupOrdinaryName); + } + + // Perform typo correction to determine if there is another name that is + // close to this name. + if (!SecondTry) { + if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) { + unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; + unsigned QualifiedDiag = diag::err_no_member_suggest; + + NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin(); + NamedDecl *UnderlyingFirstDecl + = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { + UnqualifiedDiag = diag::err_no_template_suggest; + QualifiedDiag = diag::err_no_member_template_suggest; + } else if (UnderlyingFirstDecl && + (isa<TypeDecl>(UnderlyingFirstDecl) || + isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) || + isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) { + UnqualifiedDiag = diag::err_unknown_typename_suggest; + QualifiedDiag = diag::err_unknown_nested_typename_suggest; + } + + if (SS.isEmpty()) + Diag(NameLoc, UnqualifiedDiag) + << Name << Corrected + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + else + Diag(NameLoc, QualifiedDiag) + << Name << computeDeclContext(SS, false) << Corrected + << SS.getRange() + << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + + // Update the name, so that the caller has the new name. + Name = Corrected.getAsIdentifierInfo(); + + // Typo correction corrected to a keyword. + if (Result.empty()) + return Corrected.getAsIdentifierInfo(); + + Diag(FirstDecl->getLocation(), diag::note_previous_decl) + << FirstDecl->getDeclName(); + + // If we found an Objective-C instance variable, let + // LookupInObjCMethod build the appropriate expression to + // reference the ivar. + // FIXME: This is a gross hack. + if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) { + Result.clear(); + ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); + return move(E); + } + + goto Corrected; + } + } + + // We failed to correct; just fall through and let the parser deal with it. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + + case LookupResult::NotFoundInCurrentInstantiation: + // We performed name lookup into the current instantiation, and there were + // dependent bases, so we treat this result the same way as any other + // dependent nested-name-specifier. + + // C++ [temp.res]p2: + // A name used in a template declaration or definition and that is + // dependent on a template-parameter is assumed not to name a type + // unless the applicable name lookup finds a type name or the name is + // qualified by the keyword typename. + // + // FIXME: If the next token is '<', we might want to ask the parser to + // perform some heroics to see if we actually have a + // template-argument-list, which would indicate a missing 'template' + // keyword here. + return BuildDependentDeclRefExpr(SS, NameInfo, /*TemplateArgs=*/0); + + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + break; + + case LookupResult::Ambiguous: + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + hasAnyAcceptableTemplateNames(Result)) { + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is followed by a template-argument-list, the reference refers to the + // class template itself and not a specialization thereof, and is not + // ambiguous. + // + // This filtering can make an ambiguous result into an unambiguous one, + // so try again after filtering out template names. + FilterAcceptableTemplateNames(Result); + if (!Result.isAmbiguous()) { + IsFilteredTemplateName = true; + break; + } + } + + // Diagnose the ambiguity and return an error. + return NameClassification::Error(); + } + + if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && + (IsFilteredTemplateName || hasAnyAcceptableTemplateNames(Result))) { + // C++ [temp.names]p3: + // After name lookup (3.4) finds that a name is a template-name or that + // an operator-function-id or a literal- operator-id refers to a set of + // overloaded functions any member of which is a function template if + // this is followed by a <, the < is always taken as the delimiter of a + // template-argument-list and never as the less-than operator. + if (!IsFilteredTemplateName) + FilterAcceptableTemplateNames(Result); + + if (!Result.empty()) { + bool IsFunctionTemplate; + TemplateName Template; + if (Result.end() - Result.begin() > 1) { + IsFunctionTemplate = true; + Template = Context.getOverloadedTemplateName(Result.begin(), + Result.end()); + } else { + TemplateDecl *TD + = cast<TemplateDecl>((*Result.begin())->getUnderlyingDecl()); + IsFunctionTemplate = isa<FunctionTemplateDecl>(TD); + + if (SS.isSet() && !SS.isInvalid()) + Template = Context.getQualifiedTemplateName(SS.getScopeRep(), + /*TemplateKeyword=*/false, + TD); + else + Template = TemplateName(TD); + } + + if (IsFunctionTemplate) { + // Function templates always go through overload resolution, at which + // point we'll perform the various checks (e.g., accessibility) we need + // to based on which function we selected. + Result.suppressDiagnostics(); + + return NameClassification::FunctionTemplate(Template); + } + + return NameClassification::TypeTemplate(Template); + } + } + + NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); + if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) { + DiagnoseUseOfDecl(Type, NameLoc); + QualType T = Context.getTypeDeclType(Type); + return ParsedType::make(T); + } + + ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl); + if (!Class) { + // FIXME: It's unfortunate that we don't have a Type node for handling this. + if (ObjCCompatibleAliasDecl *Alias + = dyn_cast<ObjCCompatibleAliasDecl>(FirstDecl)) + Class = Alias->getClassInterface(); + } + + if (Class) { + DiagnoseUseOfDecl(Class, NameLoc); + + if (NextToken.is(tok::period)) { + // Interface. <something> is parsed as a property reference expression. + // Just return "unknown" as a fall-through for now. + Result.suppressDiagnostics(); + return NameClassification::Unknown(); + } + + QualType T = Context.getObjCInterfaceType(Class); + return ParsedType::make(T); + } + + if (!Result.empty() && (*Result.begin())->isCXXClassMember()) + return BuildPossibleImplicitMemberExpr(SS, Result, 0); + + bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); + return BuildDeclarationNameExpr(SS, Result, ADL); +} + +// Determines the context to return to after temporarily entering a +// context. This depends in an unnecessarily complicated way on the +// exact ordering of callbacks from the parser. +DeclContext *Sema::getContainingDC(DeclContext *DC) { + + // Functions defined inline within classes aren't parsed until we've + // finished parsing the top-level class, so the top-level class is + // the context we'll need to return to. + if (isa<FunctionDecl>(DC)) { + DC = DC->getLexicalParent(); + + // A function not defined within a class will always return to its + // lexical context. + if (!isa<CXXRecordDecl>(DC)) + return DC; + + // A C++ inline method/friend is parsed *after* the topmost class + // it was declared in is fully parsed ("complete"); the topmost + // class is the context we need to return to. + while (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC->getLexicalParent())) + DC = RD; + + // Return the declaration context of the topmost class the inline method is + // declared in. + return DC; + } + + // ObjCMethodDecls are parsed (for some reason) outside the context + // of the class. + if (isa<ObjCMethodDecl>(DC)) + return DC->getLexicalParent()->getLexicalParent(); + + return DC->getLexicalParent(); +} + +void Sema::PushDeclContext(Scope *S, DeclContext *DC) { + assert(getContainingDC(DC) == CurContext && + "The next DeclContext should be lexically contained in the current one."); + CurContext = DC; + S->setEntity(DC); +} + +void Sema::PopDeclContext() { + assert(CurContext && "DeclContext imbalance!"); + + CurContext = getContainingDC(CurContext); + assert(CurContext && "Popped translation unit!"); +} + +/// EnterDeclaratorContext - Used when we must lookup names in the context +/// of a declarator's nested name specifier. +/// +void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { + // C++0x [basic.lookup.unqual]p13: + // A name used in the definition of a static data member of class + // X (after the qualified-id of the static member) is looked up as + // if the name was used in a member function of X. + // C++0x [basic.lookup.unqual]p14: + // If a variable member of a namespace is defined outside of the + // scope of its namespace then any name used in the definition of + // the variable member (after the declarator-id) is looked up as + // if the definition of the variable member occurred in its + // namespace. + // Both of these imply that we should push a scope whose context + // is the semantic context of the declaration. We can't use + // PushDeclContext here because that context is not necessarily + // lexically contained in the current context. Fortunately, + // the containing scope should have the appropriate information. + + assert(!S->getEntity() && "scope already has entity"); + +#ifndef NDEBUG + Scope *Ancestor = S->getParent(); + while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); + assert(Ancestor->getEntity() == CurContext && "ancestor context mismatch"); +#endif + + CurContext = DC; + S->setEntity(DC); +} + +void Sema::ExitDeclaratorContext(Scope *S) { + assert(S->getEntity() == CurContext && "Context imbalance!"); + + // Switch back to the lexical context. The safety of this is + // enforced by an assert in EnterDeclaratorContext. + Scope *Ancestor = S->getParent(); + while (!Ancestor->getEntity()) Ancestor = Ancestor->getParent(); + CurContext = (DeclContext*) Ancestor->getEntity(); + + // We don't need to do anything with the scope, which is going to + // disappear. +} + +/// \brief Determine whether we allow overloading of the function +/// PrevDecl with another declaration. +/// +/// This routine determines whether overloading is possible, not +/// whether some new function is actually an overload. It will return +/// true in C++ (where we can always provide overloads) or, as an +/// extension, in C when the previous function is already an +/// overloaded function declaration or has the "overloadable" +/// attribute. +static bool AllowOverloadingOfFunction(LookupResult &Previous, + ASTContext &Context) { + if (Context.getLangOptions().CPlusPlus) + return true; + + if (Previous.getResultKind() == LookupResult::FoundOverloaded) + return true; + + return (Previous.getResultKind() == LookupResult::Found + && Previous.getFoundDecl()->hasAttr<OverloadableAttr>()); +} + +/// Add this decl to the scope shadowed decl chains. +void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { + // Move up the scope chain until we find the nearest enclosing + // non-transparent context. The declaration will be introduced into this + // scope. + while (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) + S = S->getParent(); + + // Add scoped declarations into their context, so that they can be + // found later. Declarations without a context won't be inserted + // into any context. + if (AddToContext) + CurContext->addDecl(D); + + // Out-of-line definitions shouldn't be pushed into scope in C++. + // Out-of-line variable and function definitions shouldn't even in C. + if ((getLangOptions().CPlusPlus || isa<VarDecl>(D) || isa<FunctionDecl>(D)) && + D->isOutOfLine()) + return; + + // Template instantiations should also not be pushed into scope. + if (isa<FunctionDecl>(D) && + cast<FunctionDecl>(D)->isFunctionTemplateSpecialization()) + return; + + // If this replaces anything in the current scope, + IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()), + IEnd = IdResolver.end(); + for (; I != IEnd; ++I) { + if (S->isDeclScope(*I) && D->declarationReplaces(*I)) { + S->RemoveDecl(*I); + IdResolver.RemoveDecl(*I); + + // Should only need to replace one decl. + break; + } + } + + S->AddDecl(D); + + if (isa<LabelDecl>(D) && !cast<LabelDecl>(D)->isGnuLocal()) { + // Implicitly-generated labels may end up getting generated in an order that + // isn't strictly lexical, which breaks name lookup. Be careful to insert + // the label at the appropriate place in the identifier chain. + for (I = IdResolver.begin(D->getDeclName()); I != IEnd; ++I) { + DeclContext *IDC = (*I)->getLexicalDeclContext()->getRedeclContext(); + if (IDC == CurContext) { + if (!S->isDeclScope(*I)) + continue; + } else if (IDC->Encloses(CurContext)) + break; + } + + IdResolver.InsertDeclAfter(I, D); + } else { + IdResolver.AddDecl(D); + } +} + +bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, + bool ExplicitInstantiationOrSpecialization) { + return IdResolver.isDeclInScope(D, Ctx, Context, S, + ExplicitInstantiationOrSpecialization); +} + +Scope *Sema::getScopeForDeclContext(Scope *S, DeclContext *DC) { + DeclContext *TargetDC = DC->getPrimaryContext(); + do { + if (DeclContext *ScopeDC = (DeclContext*) S->getEntity()) + if (ScopeDC->getPrimaryContext() == TargetDC) + return S; + } while ((S = S->getParent())); + + return 0; +} + +static bool isOutOfScopePreviousDeclaration(NamedDecl *, + DeclContext*, + ASTContext&); + +/// Filters out lookup results that don't fall within the given scope +/// as determined by isDeclInScope. +void Sema::FilterLookupForScope(LookupResult &R, + DeclContext *Ctx, Scope *S, + bool ConsiderLinkage, + bool ExplicitInstantiationOrSpecialization) { + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + + if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization)) + continue; + + if (ConsiderLinkage && + isOutOfScopePreviousDeclaration(D, Ctx, Context)) + continue; + + F.erase(); + } + + F.done(); +} + +static bool isUsingDecl(NamedDecl *D) { + return isa<UsingShadowDecl>(D) || + isa<UnresolvedUsingTypenameDecl>(D) || + isa<UnresolvedUsingValueDecl>(D); +} + +/// Removes using shadow declarations from the lookup results. +static void RemoveUsingDecls(LookupResult &R) { + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) + if (isUsingDecl(F.next())) + F.erase(); + + F.done(); +} + +/// \brief Check for this common pattern: +/// @code +/// class S { +/// S(const S&); // DO NOT IMPLEMENT +/// void operator=(const S&); // DO NOT IMPLEMENT +/// }; +/// @endcode +static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { + // FIXME: Should check for private access too but access is set after we get + // the decl here. + if (D->doesThisDeclarationHaveABody()) + return false; + + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(D)) + return CD->isCopyConstructor(); + if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + return Method->isCopyAssignmentOperator(); + return false; +} + +bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { + assert(D); + + if (D->isInvalidDecl() || D->isUsed() || D->hasAttr<UnusedAttr>()) + return false; + + // Ignore class templates. + if (D->getDeclContext()->isDependentContext() || + D->getLexicalDeclContext()->isDependentContext()) + return false; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; + + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { + if (MD->isVirtual() || IsDisallowedCopyOrAssign(MD)) + return false; + } else { + // 'static inline' functions are used in headers; don't warn. + if (FD->getStorageClass() == SC_Static && + FD->isInlineSpecified()) + return false; + } + + if (FD->doesThisDeclarationHaveABody() && + Context.DeclMustBeEmitted(FD)) + return false; + } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (!VD->isFileVarDecl() || + VD->getType().isConstant(Context) || + Context.DeclMustBeEmitted(VD)) + return false; + + if (VD->isStaticDataMember() && + VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) + return false; + + } else { + return false; + } + + // Only warn for unused decls internal to the translation unit. + if (D->getLinkage() == ExternalLinkage) + return false; + + return true; +} + +void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) { + if (!D) + return; + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + const FunctionDecl *First = FD->getFirstDeclaration(); + if (FD != First && ShouldWarnIfUnusedFileScopedDecl(First)) + return; // First should already be in the vector. + } + + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + const VarDecl *First = VD->getFirstDeclaration(); + if (VD != First && ShouldWarnIfUnusedFileScopedDecl(First)) + return; // First should already be in the vector. + } + + if (ShouldWarnIfUnusedFileScopedDecl(D)) + UnusedFileScopedDecls.push_back(D); + } + +static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { + if (D->isInvalidDecl()) + return false; + + if (D->isUsed() || D->hasAttr<UnusedAttr>()) + return false; + + if (isa<LabelDecl>(D)) + return true; + + // White-list anything that isn't a local variable. + if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) || + !D->getDeclContext()->isFunctionOrMethod()) + return false; + + // Types of valid local variables should be complete, so this should succeed. + if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { + + // White-list anything with an __attribute__((unused)) type. + QualType Ty = VD->getType(); + + // Only look at the outermost level of typedef. + if (const TypedefType *TT = dyn_cast<TypedefType>(Ty)) { + if (TT->getDecl()->hasAttr<UnusedAttr>()) + return false; + } + + // If we failed to complete the type for some reason, or if the type is + // dependent, don't diagnose the variable. + if (Ty->isIncompleteType() || Ty->isDependentType()) + return false; + + if (const TagType *TT = Ty->getAs<TagType>()) { + const TagDecl *Tag = TT->getDecl(); + if (Tag->hasAttr<UnusedAttr>()) + return false; + + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Tag)) { + // FIXME: Checking for the presence of a user-declared constructor + // isn't completely accurate; we'd prefer to check that the initializer + // has no side effects. + if (RD->hasUserDeclaredConstructor() || !RD->hasTrivialDestructor()) + return false; + } + } + + // TODO: __attribute__((unused)) templates? + } + + return true; +} + +/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used +/// unless they are marked attr(unused). +void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { + if (!ShouldDiagnoseUnusedDecl(D)) + return; + + unsigned DiagID; + if (isa<VarDecl>(D) && cast<VarDecl>(D)->isExceptionVariable()) + DiagID = diag::warn_unused_exception_param; + else if (isa<LabelDecl>(D)) + DiagID = diag::warn_unused_label; + else + DiagID = diag::warn_unused_variable; + + Diag(D->getLocation(), DiagID) << D->getDeclName(); +} + +static void CheckPoppedLabel(LabelDecl *L, Sema &S) { + // Verify that we have no forward references left. If so, there was a goto + // or address of a label taken, but no definition of it. Label fwd + // definitions are indicated with a null substmt. + if (L->getStmt() == 0) + S.Diag(L->getLocation(), diag::err_undeclared_label_use) <<L->getDeclName(); +} + +void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { + if (S->decl_empty()) return; + assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && + "Scope shouldn't contain decls!"); + + for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end(); + I != E; ++I) { + Decl *TmpD = (*I); + assert(TmpD && "This decl didn't get pushed??"); + + assert(isa<NamedDecl>(TmpD) && "Decl isn't NamedDecl?"); + NamedDecl *D = cast<NamedDecl>(TmpD); + + if (!D->getDeclName()) continue; + + // Diagnose unused variables in this scope. + if (!S->hasErrorOccurred()) + DiagnoseUnusedDecl(D); + + // If this was a forward reference to a label, verify it was defined. + if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) + CheckPoppedLabel(LD, *this); + + // Remove this name from our lexical scope. + IdResolver.RemoveDecl(D); + } +} + +/// \brief Look for an Objective-C class in the translation unit. +/// +/// \param Id The name of the Objective-C class we're looking for. If +/// typo-correction fixes this name, the Id will be updated +/// to the fixed name. +/// +/// \param IdLoc The location of the name in the translation unit. +/// +/// \param TypoCorrection If true, this routine will attempt typo correction +/// if there is no class with the given name. +/// +/// \returns The declaration of the named Objective-C class, or NULL if the +/// class could not be found. +ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, + SourceLocation IdLoc, + bool TypoCorrection) { + // The third "scope" argument is 0 since we aren't enabling lazy built-in + // creation from this context. + NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); + + if (!IDecl && TypoCorrection) { + // Perform typo correction at the given location, but only if we + // find an Objective-C class name. + LookupResult R(*this, Id, IdLoc, LookupOrdinaryName); + if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && + (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { + Diag(IdLoc, diag::err_undef_interface_suggest) + << Id << IDecl->getDeclName() + << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); + Diag(IDecl->getLocation(), diag::note_previous_decl) + << IDecl->getDeclName(); + + Id = IDecl->getIdentifier(); + } + } + + return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); +} + +/// getNonFieldDeclScope - Retrieves the innermost scope, starting +/// from S, where a non-field would be declared. This routine copes +/// with the difference between C and C++ scoping rules in structs and +/// unions. For example, the following code is well-formed in C but +/// ill-formed in C++: +/// @code +/// struct S6 { +/// enum { BAR } e; +/// }; +/// +/// void test_S6() { +/// struct S6 a; +/// a.e = BAR; +/// } +/// @endcode +/// For the declaration of BAR, this routine will return a different +/// scope. The scope S will be the scope of the unnamed enumeration +/// within S6. In C++, this routine will return the scope associated +/// with S6, because the enumeration's scope is a transparent +/// context but structures can contain non-field names. In C, this +/// routine will return the translation unit scope, since the +/// enumeration's scope is a transparent context and structures cannot +/// contain non-field names. +Scope *Sema::getNonFieldDeclScope(Scope *S) { + while (((S->getFlags() & Scope::DeclScope) == 0) || + (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) || + (S->isClassScope() && !getLangOptions().CPlusPlus)) + S = S->getParent(); + return S; +} + +/// LazilyCreateBuiltin - The specified Builtin-ID was first used at +/// file scope. lazily create a decl for it. ForRedeclaration is true +/// if we're creating this built-in in anticipation of redeclaring the +/// built-in. +NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, + Scope *S, bool ForRedeclaration, + SourceLocation Loc) { + Builtin::ID BID = (Builtin::ID)bid; + + ASTContext::GetBuiltinTypeError Error; + QualType R = Context.GetBuiltinType(BID, Error); + switch (Error) { + case ASTContext::GE_None: + // Okay + break; + + case ASTContext::GE_Missing_stdio: + if (ForRedeclaration) + Diag(Loc, diag::warn_implicit_decl_requires_stdio) + << Context.BuiltinInfo.GetName(BID); + return 0; + + case ASTContext::GE_Missing_setjmp: + if (ForRedeclaration) + Diag(Loc, diag::warn_implicit_decl_requires_setjmp) + << Context.BuiltinInfo.GetName(BID); + return 0; + } + + if (!ForRedeclaration && Context.BuiltinInfo.isPredefinedLibFunction(BID)) { + Diag(Loc, diag::ext_implicit_lib_function_decl) + << Context.BuiltinInfo.GetName(BID) + << R; + if (Context.BuiltinInfo.getHeaderName(BID) && + Diags.getDiagnosticLevel(diag::ext_implicit_lib_function_decl, Loc) + != Diagnostic::Ignored) + Diag(Loc, diag::note_please_include_header) + << Context.BuiltinInfo.getHeaderName(BID) + << Context.BuiltinInfo.GetName(BID); + } + + FunctionDecl *New = FunctionDecl::Create(Context, + Context.getTranslationUnitDecl(), + Loc, Loc, II, R, /*TInfo=*/0, + SC_Extern, + SC_None, false, + /*hasPrototype=*/true); + New->setImplicit(); + + // Create Decl objects for each parameter, adding them to the + // FunctionDecl. + if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(R)) { + llvm::SmallVector<ParmVarDecl*, 16> Params; + for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { + ParmVarDecl *parm = + ParmVarDecl::Create(Context, New, SourceLocation(), + SourceLocation(), 0, + FT->getArgType(i), /*TInfo=*/0, + SC_None, SC_None, 0); + parm->setScopeInfo(0, i); + Params.push_back(parm); + } + New->setParams(Params.data(), Params.size()); + } + + AddKnownFunctionAttributes(New); + + // TUScope is the translation-unit scope to insert this function into. + // FIXME: This is hideous. We need to teach PushOnScopeChains to + // relate Scopes to DeclContexts, and probably eliminate CurContext + // entirely, but we're not there yet. + DeclContext *SavedContext = CurContext; + CurContext = Context.getTranslationUnitDecl(); + PushOnScopeChains(New, TUScope); + CurContext = SavedContext; + return New; +} + +/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the +/// same name and scope as a previous declaration 'Old'. Figure out +/// how to resolve this situation, merging decls or emitting +/// diagnostics as appropriate. If there was an error, set New to be invalid. +/// +void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { + // If the new decl is known invalid already, don't bother doing any + // merging checks. + if (New->isInvalidDecl()) return; + + // Allow multiple definitions for ObjC built-in typedefs. + // FIXME: Verify the underlying types are equivalent! + if (getLangOptions().ObjC1) { + const IdentifierInfo *TypeID = New->getIdentifier(); + switch (TypeID->getLength()) { + default: break; + case 2: + if (!TypeID->isStr("id")) + break; + Context.ObjCIdRedefinitionType = New->getUnderlyingType(); + // Install the built-in type for 'id', ignoring the current definition. + New->setTypeForDecl(Context.getObjCIdType().getTypePtr()); + return; + case 5: + if (!TypeID->isStr("Class")) + break; + Context.ObjCClassRedefinitionType = New->getUnderlyingType(); + // Install the built-in type for 'Class', ignoring the current definition. + New->setTypeForDecl(Context.getObjCClassType().getTypePtr()); + return; + case 3: + if (!TypeID->isStr("SEL")) + break; + Context.ObjCSelRedefinitionType = New->getUnderlyingType(); + // Install the built-in type for 'SEL', ignoring the current definition. + New->setTypeForDecl(Context.getObjCSelType().getTypePtr()); + return; + case 8: + if (!TypeID->isStr("Protocol")) + break; + Context.setObjCProtoType(New->getUnderlyingType()); + return; + } + // Fall through - the typedef name was not a builtin type. + } + + // Verify the old decl was also a type. + TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>(); + if (!Old) { + Diag(New->getLocation(), diag::err_redefinition_different_kind) + << New->getDeclName(); + + NamedDecl *OldD = OldDecls.getRepresentativeDecl(); + if (OldD->getLocation().isValid()) + Diag(OldD->getLocation(), diag::note_previous_definition); + + return New->setInvalidDecl(); + } + + // If the old declaration is invalid, just give up here. + if (Old->isInvalidDecl()) + return New->setInvalidDecl(); + + // Determine the "old" type we'll use for checking and diagnostics. + QualType OldType; + if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) + OldType = OldTypedef->getUnderlyingType(); + else + OldType = Context.getTypeDeclType(Old); + + // If the typedef types are not identical, reject them in all languages and + // with any extensions enabled. + + if (OldType != New->getUnderlyingType() && + Context.getCanonicalType(OldType) != + Context.getCanonicalType(New->getUnderlyingType())) { + int Kind = 0; + if (isa<TypeAliasDecl>(Old)) + Kind = 1; + Diag(New->getLocation(), diag::err_redefinition_different_typedef) + << Kind << New->getUnderlyingType() << OldType; + if (Old->getLocation().isValid()) + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // The types match. Link up the redeclaration chain if the old + // declaration was a typedef. + // FIXME: this is a potential source of wierdness if the type + // spellings don't match exactly. + if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Old)) + New->setPreviousDeclaration(Typedef); + + if (getLangOptions().Microsoft) + return; + + if (getLangOptions().CPlusPlus) { + // C++ [dcl.typedef]p2: + // In a given non-class scope, a typedef specifier can be used to + // redefine the name of any type declared in that scope to refer + // to the type to which it already refers. + if (!isa<CXXRecordDecl>(CurContext)) + return; + + // C++0x [dcl.typedef]p4: + // In a given class scope, a typedef specifier can be used to redefine + // any class-name declared in that scope that is not also a typedef-name + // to refer to the type to which it already refers. + // + // This wording came in via DR424, which was a correction to the + // wording in DR56, which accidentally banned code like: + // + // struct S { + // typedef struct A { } A; + // }; + // + // in the C++03 standard. We implement the C++0x semantics, which + // allow the above but disallow + // + // struct S { + // typedef int I; + // typedef int I; + // }; + // + // since that was the intent of DR56. + if (!isa<TypedefNameDecl>(Old)) + return; + + Diag(New->getLocation(), diag::err_redefinition) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // If we have a redefinition of a typedef in C, emit a warning. This warning + // is normally mapped to an error, but can be controlled with + // -Wtypedef-redefinition. If either the original or the redefinition is + // in a system header, don't emit this for compatibility with GCC. + if (getDiagnostics().getSuppressSystemWarnings() && + (Context.getSourceManager().isInSystemHeader(Old->getLocation()) || + Context.getSourceManager().isInSystemHeader(New->getLocation()))) + return; + + Diag(New->getLocation(), diag::warn_redefinition_of_typedef) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return; +} + +/// DeclhasAttr - returns true if decl Declaration already has the target +/// attribute. +static bool +DeclHasAttr(const Decl *D, const Attr *A) { + const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A); + for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i) + if ((*i)->getKind() == A->getKind()) { + // FIXME: Don't hardcode this check + if (OA && isa<OwnershipAttr>(*i)) + return OA->getOwnKind() == cast<OwnershipAttr>(*i)->getOwnKind(); + return true; + } + + return false; +} + +/// mergeDeclAttributes - Copy attributes from the Old decl to the New one. +static void mergeDeclAttributes(Decl *newDecl, const Decl *oldDecl, + ASTContext &C) { + if (!oldDecl->hasAttrs()) + return; + + bool foundAny = newDecl->hasAttrs(); + + // Ensure that any moving of objects within the allocated map is done before + // we process them. + if (!foundAny) newDecl->setAttrs(AttrVec()); + + for (specific_attr_iterator<InheritableAttr> + i = oldDecl->specific_attr_begin<InheritableAttr>(), + e = oldDecl->specific_attr_end<InheritableAttr>(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast<InheritableAttr>((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; + } + } + + if (!foundAny) newDecl->dropAttrs(); +} + +/// mergeParamDeclAttributes - Copy attributes from the old parameter +/// to the new one. +static void mergeParamDeclAttributes(ParmVarDecl *newDecl, + const ParmVarDecl *oldDecl, + ASTContext &C) { + if (!oldDecl->hasAttrs()) + return; + + bool foundAny = newDecl->hasAttrs(); + + // Ensure that any moving of objects within the allocated map is + // done before we process them. + if (!foundAny) newDecl->setAttrs(AttrVec()); + + for (specific_attr_iterator<InheritableParamAttr> + i = oldDecl->specific_attr_begin<InheritableParamAttr>(), + e = oldDecl->specific_attr_end<InheritableParamAttr>(); i != e; ++i) { + if (!DeclHasAttr(newDecl, *i)) { + InheritableAttr *newAttr = cast<InheritableParamAttr>((*i)->clone(C)); + newAttr->setInherited(true); + newDecl->addAttr(newAttr); + foundAny = true; + } + } + + if (!foundAny) newDecl->dropAttrs(); +} + +namespace { + +/// Used in MergeFunctionDecl to keep track of function parameters in +/// C. +struct GNUCompatibleParamWarning { + ParmVarDecl *OldParm; + ParmVarDecl *NewParm; + QualType PromotedType; +}; + +} + +/// getSpecialMember - get the special member enum for a method. +Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { + if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { + if (Ctor->isDefaultConstructor()) + return Sema::CXXDefaultConstructor; + + if (Ctor->isCopyConstructor()) + return Sema::CXXCopyConstructor; + + if (Ctor->isMoveConstructor()) + return Sema::CXXMoveConstructor; + } else if (isa<CXXDestructorDecl>(MD)) { + return Sema::CXXDestructor; + } else if (MD->isCopyAssignmentOperator()) { + return Sema::CXXCopyAssignment; + } + + return Sema::CXXInvalid; +} + +/// canRedefineFunction - checks if a function can be redefined. Currently, +/// only extern inline functions can be redefined, and even then only in +/// GNU89 mode. +static bool canRedefineFunction(const FunctionDecl *FD, + const LangOptions& LangOpts) { + return (LangOpts.GNUInline && !LangOpts.CPlusPlus && + FD->isInlineSpecified() && + FD->getStorageClass() == SC_Extern); +} + +/// MergeFunctionDecl - We just parsed a function 'New' from +/// declarator D which has the same name and scope as a previous +/// declaration 'Old'. Figure out how to resolve this situation, +/// merging decls or emitting diagnostics as appropriate. +/// +/// In C++, New and Old must be declarations that are not +/// overloaded. Use IsOverload to determine whether New and Old are +/// overloaded, and to select the Old declaration that New should be +/// merged with. +/// +/// Returns true if there was an error, false otherwise. +bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { + // Verify the old decl was also a function. + FunctionDecl *Old = 0; + if (FunctionTemplateDecl *OldFunctionTemplate + = dyn_cast<FunctionTemplateDecl>(OldD)) + Old = OldFunctionTemplate->getTemplatedDecl(); + else + Old = dyn_cast<FunctionDecl>(OldD); + if (!Old) { + if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) { + Diag(New->getLocation(), diag::err_using_decl_conflict_reverse); + Diag(Shadow->getTargetDecl()->getLocation(), + diag::note_using_decl_target); + Diag(Shadow->getUsingDecl()->getLocation(), + diag::note_using_decl) << 0; + return true; + } + + Diag(New->getLocation(), diag::err_redefinition_different_kind) + << New->getDeclName(); + Diag(OldD->getLocation(), diag::note_previous_definition); + return true; + } + + // Determine whether the previous declaration was a definition, + // implicit declaration, or a declaration. + diag::kind PrevDiag; + if (Old->isThisDeclarationADefinition()) + PrevDiag = diag::note_previous_definition; + else if (Old->isImplicit()) + PrevDiag = diag::note_previous_implicit_declaration; + else + PrevDiag = diag::note_previous_declaration; + + QualType OldQType = Context.getCanonicalType(Old->getType()); + QualType NewQType = Context.getCanonicalType(New->getType()); + + // Don't complain about this if we're in GNU89 mode and the old function + // is an extern inline function. + if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) && + New->getStorageClass() == SC_Static && + Old->getStorageClass() != SC_Static && + !canRedefineFunction(Old, getLangOptions())) { + if (getLangOptions().Microsoft) { + Diag(New->getLocation(), diag::warn_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + } else { + Diag(New->getLocation(), diag::err_static_non_static) << New; + Diag(Old->getLocation(), PrevDiag); + return true; + } + } + + // If a function is first declared with a calling convention, but is + // later declared or defined without one, the second decl assumes the + // calling convention of the first. + // + // For the new decl, we have to look at the NON-canonical type to tell the + // difference between a function that really doesn't have a calling + // convention and one that is declared cdecl. That's because in + // canonicalization (see ASTContext.cpp), cdecl is canonicalized away + // because it is the default calling convention. + // + // Note also that we DO NOT return at this point, because we still have + // other tests to run. + const FunctionType *OldType = cast<FunctionType>(OldQType); + const FunctionType *NewType = New->getType()->getAs<FunctionType>(); + FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo(); + FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo(); + bool RequiresAdjustment = false; + if (OldTypeInfo.getCC() != CC_Default && + NewTypeInfo.getCC() == CC_Default) { + NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); + RequiresAdjustment = true; + } else if (!Context.isSameCallConv(OldTypeInfo.getCC(), + NewTypeInfo.getCC())) { + // Calling conventions really aren't compatible, so complain. + Diag(New->getLocation(), diag::err_cconv_change) + << FunctionType::getNameForCallConv(NewTypeInfo.getCC()) + << (OldTypeInfo.getCC() == CC_Default) + << (OldTypeInfo.getCC() == CC_Default ? "" : + FunctionType::getNameForCallConv(OldTypeInfo.getCC())); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + // FIXME: diagnose the other way around? + if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) { + NewTypeInfo = NewTypeInfo.withNoReturn(true); + RequiresAdjustment = true; + } + + // Merge regparm attribute. + if (OldTypeInfo.getHasRegParm() != NewTypeInfo.getHasRegParm() || + OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) { + if (NewTypeInfo.getHasRegParm()) { + Diag(New->getLocation(), diag::err_regparm_mismatch) + << NewType->getRegParmType() + << OldType->getRegParmType(); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm()); + RequiresAdjustment = true; + } + + if (RequiresAdjustment) { + NewType = Context.adjustFunctionType(NewType, NewTypeInfo); + New->setType(QualType(NewType, 0)); + NewQType = Context.getCanonicalType(New->getType()); + } + + if (getLangOptions().CPlusPlus) { + // (C++98 13.1p2): + // Certain function declarations cannot be overloaded: + // -- Function declarations that differ only in the return type + // cannot be overloaded. + QualType OldReturnType = OldType->getResultType(); + QualType NewReturnType = cast<FunctionType>(NewQType)->getResultType(); + QualType ResQT; + if (OldReturnType != NewReturnType) { + if (NewReturnType->isObjCObjectPointerType() + && OldReturnType->isObjCObjectPointerType()) + ResQT = Context.mergeObjCGCQualifiers(NewQType, OldQType); + if (ResQT.isNull()) { + if (New->isCXXClassMember() && New->isOutOfLine()) + Diag(New->getLocation(), + diag::err_member_def_does_not_match_ret_type) << New; + else + Diag(New->getLocation(), diag::err_ovl_diff_return_type); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; + } + else + NewQType = ResQT; + } + + const CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); + CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); + if (OldMethod && NewMethod) { + // Preserve triviality. + NewMethod->setTrivial(OldMethod->isTrivial()); + + bool isFriend = NewMethod->getFriendObjectKind(); + + if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord()) { + // -- Member function declarations with the same name and the + // same parameter types cannot be overloaded if any of them + // is a static member function declaration. + if (OldMethod->isStatic() || NewMethod->isStatic()) { + Diag(New->getLocation(), diag::err_ovl_static_nonstatic_member); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; + } + + // C++ [class.mem]p1: + // [...] A member shall not be declared twice in the + // member-specification, except that a nested class or member + // class template can be declared and then later defined. + unsigned NewDiag; + if (isa<CXXConstructorDecl>(OldMethod)) + NewDiag = diag::err_constructor_redeclared; + else if (isa<CXXDestructorDecl>(NewMethod)) + NewDiag = diag::err_destructor_redeclared; + else if (isa<CXXConversionDecl>(NewMethod)) + NewDiag = diag::err_conv_function_redeclared; + else + NewDiag = diag::err_member_redeclared; + + Diag(New->getLocation(), NewDiag); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + + // Complain if this is an explicit declaration of a special + // member that was initially declared implicitly. + // + // As an exception, it's okay to befriend such methods in order + // to permit the implicit constructor/destructor/operator calls. + } else if (OldMethod->isImplicit()) { + if (isFriend) { + NewMethod->setImplicit(); + } else { + Diag(NewMethod->getLocation(), + diag::err_definition_of_implicitly_declared_member) + << New << getSpecialMember(OldMethod); + return true; + } + } else if (OldMethod->isExplicitlyDefaulted()) { + Diag(NewMethod->getLocation(), + diag::err_definition_of_explicitly_defaulted_member) + << getSpecialMember(OldMethod); + return true; + } + } + + // (C++98 8.3.5p3): + // All declarations for a function shall agree exactly in both the + // return type and the parameter-type-list. + // We also want to respect all the extended bits except noreturn. + + // noreturn should now match unless the old type info didn't have it. + QualType OldQTypeForComparison = OldQType; + if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) { + assert(OldQType == QualType(OldType, 0)); + const FunctionType *OldTypeForComparison + = Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true)); + OldQTypeForComparison = QualType(OldTypeForComparison, 0); + assert(OldQTypeForComparison.isCanonical()); + } + + if (OldQTypeForComparison == NewQType) + return MergeCompatibleFunctionDecls(New, Old); + + // Fall through for conflicting redeclarations and redefinitions. + } + + // C: Function types need to be compatible, not identical. This handles + // duplicate function decls like "void f(int); void f(enum X);" properly. + if (!getLangOptions().CPlusPlus && + Context.typesAreCompatible(OldQType, NewQType)) { + const FunctionType *OldFuncType = OldQType->getAs<FunctionType>(); + const FunctionType *NewFuncType = NewQType->getAs<FunctionType>(); + const FunctionProtoType *OldProto = 0; + if (isa<FunctionNoProtoType>(NewFuncType) && + (OldProto = dyn_cast<FunctionProtoType>(OldFuncType))) { + // The old declaration provided a function prototype, but the + // new declaration does not. Merge in the prototype. + assert(!OldProto->hasExceptionSpec() && "Exception spec in C"); + llvm::SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(), + OldProto->arg_type_end()); + NewQType = Context.getFunctionType(NewFuncType->getResultType(), + ParamTypes.data(), ParamTypes.size(), + OldProto->getExtProtoInfo()); + New->setType(NewQType); + New->setHasInheritedPrototype(); + + // Synthesize a parameter for each argument type. + llvm::SmallVector<ParmVarDecl*, 16> Params; + for (FunctionProtoType::arg_type_iterator + ParamType = OldProto->arg_type_begin(), + ParamEnd = OldProto->arg_type_end(); + ParamType != ParamEnd; ++ParamType) { + ParmVarDecl *Param = ParmVarDecl::Create(Context, New, + SourceLocation(), + SourceLocation(), 0, + *ParamType, /*TInfo=*/0, + SC_None, SC_None, + 0); + Param->setScopeInfo(0, Params.size()); + Param->setImplicit(); + Params.push_back(Param); + } + + New->setParams(Params.data(), Params.size()); + } + + return MergeCompatibleFunctionDecls(New, Old); + } + + // GNU C permits a K&R definition to follow a prototype declaration + // if the declared types of the parameters in the K&R definition + // match the types in the prototype declaration, even when the + // promoted types of the parameters from the K&R definition differ + // from the types in the prototype. GCC then keeps the types from + // the prototype. + // + // If a variadic prototype is followed by a non-variadic K&R definition, + // the K&R definition becomes variadic. This is sort of an edge case, but + // it's legal per the standard depending on how you read C99 6.7.5.3p15 and + // C99 6.9.1p8. + if (!getLangOptions().CPlusPlus && + Old->hasPrototype() && !New->hasPrototype() && + New->getType()->getAs<FunctionProtoType>() && + Old->getNumParams() == New->getNumParams()) { + llvm::SmallVector<QualType, 16> ArgTypes; + llvm::SmallVector<GNUCompatibleParamWarning, 16> Warnings; + const FunctionProtoType *OldProto + = Old->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *NewProto + = New->getType()->getAs<FunctionProtoType>(); + + // Determine whether this is the GNU C extension. + QualType MergedReturn = Context.mergeTypes(OldProto->getResultType(), + NewProto->getResultType()); + bool LooseCompatible = !MergedReturn.isNull(); + for (unsigned Idx = 0, End = Old->getNumParams(); + LooseCompatible && Idx != End; ++Idx) { + ParmVarDecl *OldParm = Old->getParamDecl(Idx); + ParmVarDecl *NewParm = New->getParamDecl(Idx); + if (Context.typesAreCompatible(OldParm->getType(), + NewProto->getArgType(Idx))) { + ArgTypes.push_back(NewParm->getType()); + } else if (Context.typesAreCompatible(OldParm->getType(), + NewParm->getType(), + /*CompareUnqualified=*/true)) { + GNUCompatibleParamWarning Warn + = { OldParm, NewParm, NewProto->getArgType(Idx) }; + Warnings.push_back(Warn); + ArgTypes.push_back(NewParm->getType()); + } else + LooseCompatible = false; + } + + if (LooseCompatible) { + for (unsigned Warn = 0; Warn < Warnings.size(); ++Warn) { + Diag(Warnings[Warn].NewParm->getLocation(), + diag::ext_param_promoted_not_compatible_with_prototype) + << Warnings[Warn].PromotedType + << Warnings[Warn].OldParm->getType(); + if (Warnings[Warn].OldParm->getLocation().isValid()) + Diag(Warnings[Warn].OldParm->getLocation(), + diag::note_previous_declaration); + } + + New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0], + ArgTypes.size(), + OldProto->getExtProtoInfo())); + return MergeCompatibleFunctionDecls(New, Old); + } + + // Fall through to diagnose conflicting types. + } + + // A function that has already been declared has been redeclared or defined + // with a different type- show appropriate diagnostic + if (unsigned BuiltinID = Old->getBuiltinID()) { + // The user has declared a builtin function with an incompatible + // signature. + if (Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { + // The function the user is redeclaring is a library-defined + // function like 'malloc' or 'printf'. Warn about the + // redeclaration, then pretend that we don't know about this + // library built-in. + Diag(New->getLocation(), diag::warn_redecl_library_builtin) << New; + Diag(Old->getLocation(), diag::note_previous_builtin_declaration) + << Old << Old->getType(); + New->getIdentifier()->setBuiltinID(Builtin::NotBuiltin); + Old->setInvalidDecl(); + return false; + } + + PrevDiag = diag::note_previous_builtin_declaration; + } + + Diag(New->getLocation(), diag::err_conflicting_types) << New->getDeclName(); + Diag(Old->getLocation(), PrevDiag) << Old << Old->getType(); + return true; +} + +/// \brief Completes the merge of two function declarations that are +/// known to be compatible. +/// +/// This routine handles the merging of attributes and other +/// properties of function declarations form the old declaration to +/// the new declaration, once we know that New is in fact a +/// redeclaration of Old. +/// +/// \returns false +bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old) { + // Merge the attributes + mergeDeclAttributes(New, Old, Context); + + // Merge the storage class. + if (Old->getStorageClass() != SC_Extern && + Old->getStorageClass() != SC_None) + New->setStorageClass(Old->getStorageClass()); + + // Merge "pure" flag. + if (Old->isPure()) + New->setPure(); + + // Merge attributes from the parameters. These can mismatch with K&R + // declarations. + if (New->getNumParams() == Old->getNumParams()) + for (unsigned i = 0, e = New->getNumParams(); i != e; ++i) + mergeParamDeclAttributes(New->getParamDecl(i), Old->getParamDecl(i), + Context); + + if (getLangOptions().CPlusPlus) + return MergeCXXFunctionDecl(New, Old); + + return false; +} + +void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, + const ObjCMethodDecl *oldMethod) { + // Merge the attributes. + mergeDeclAttributes(newMethod, oldMethod, Context); + + // Merge attributes from the parameters. + for (ObjCMethodDecl::param_iterator oi = oldMethod->param_begin(), + ni = newMethod->param_begin(), ne = newMethod->param_end(); + ni != ne; ++ni, ++oi) + mergeParamDeclAttributes(*ni, *oi, Context); + + CheckObjCMethodOverride(newMethod, oldMethod, true); +} + +/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and +/// scope as a previous declaration 'Old'. Figure out how to merge their types, +/// emitting diagnostics as appropriate. +/// +/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back +/// to here in AddInitializerToDecl and AddCXXDirectInitializerToDecl. We can't +/// check them before the initializer is attached. +/// +void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { + if (New->isInvalidDecl() || Old->isInvalidDecl()) + return; + + QualType MergedT; + if (getLangOptions().CPlusPlus) { + AutoType *AT = New->getType()->getContainedAutoType(); + if (AT && !AT->isDeduced()) { + // We don't know what the new type is until the initializer is attached. + return; + } else if (Context.hasSameType(New->getType(), Old->getType())) { + // These could still be something that needs exception specs checked. + return MergeVarDeclExceptionSpecs(New, Old); + } + // C++ [basic.link]p10: + // [...] the types specified by all declarations referring to a given + // object or function shall be identical, except that declarations for an + // array object can specify array types that differ by the presence or + // absence of a major array bound (8.3.4). + else if (Old->getType()->isIncompleteArrayType() && + New->getType()->isArrayType()) { + CanQual<ArrayType> OldArray + = Context.getCanonicalType(Old->getType())->getAs<ArrayType>(); + CanQual<ArrayType> NewArray + = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); + if (OldArray->getElementType() == NewArray->getElementType()) + MergedT = New->getType(); + } else if (Old->getType()->isArrayType() && + New->getType()->isIncompleteArrayType()) { + CanQual<ArrayType> OldArray + = Context.getCanonicalType(Old->getType())->getAs<ArrayType>(); + CanQual<ArrayType> NewArray + = Context.getCanonicalType(New->getType())->getAs<ArrayType>(); + if (OldArray->getElementType() == NewArray->getElementType()) + MergedT = Old->getType(); + } else if (New->getType()->isObjCObjectPointerType() + && Old->getType()->isObjCObjectPointerType()) { + MergedT = Context.mergeObjCGCQualifiers(New->getType(), + Old->getType()); + } + } else { + MergedT = Context.mergeTypes(New->getType(), Old->getType()); + } + if (MergedT.isNull()) { + Diag(New->getLocation(), diag::err_redefinition_different_type) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + New->setType(MergedT); +} + +/// MergeVarDecl - We just parsed a variable 'New' which has the same name +/// and scope as a previous declaration 'Old'. Figure out how to resolve this +/// situation, merging decls or emitting diagnostics as appropriate. +/// +/// Tentative definition rules (C99 6.9.2p2) are checked by +/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative +/// definitions here, since the initializer hasn't been attached. +/// +void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { + // If the new decl is already invalid, don't do any other checking. + if (New->isInvalidDecl()) + return; + + // Verify the old decl was also a variable. + VarDecl *Old = 0; + if (!Previous.isSingleResult() || + !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) { + Diag(New->getLocation(), diag::err_redefinition_different_kind) + << New->getDeclName(); + Diag(Previous.getRepresentativeDecl()->getLocation(), + diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // C++ [class.mem]p1: + // A member shall not be declared twice in the member-specification [...] + // + // Here, we need only consider static data members. + if (Old->isStaticDataMember() && !New->isOutOfLine()) { + Diag(New->getLocation(), diag::err_duplicate_member) + << New->getIdentifier(); + Diag(Old->getLocation(), diag::note_previous_declaration); + New->setInvalidDecl(); + } + + mergeDeclAttributes(New, Old, Context); + + // Merge the types. + MergeVarDeclTypes(New, Old); + if (New->isInvalidDecl()) + return; + + // C99 6.2.2p4: Check if we have a static decl followed by a non-static. + if (New->getStorageClass() == SC_Static && + (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) { + Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + // C99 6.2.2p4: + // For an identifier declared with the storage-class specifier + // extern in a scope in which a prior declaration of that + // identifier is visible,23) if the prior declaration specifies + // internal or external linkage, the linkage of the identifier at + // the later declaration is the same as the linkage specified at + // the prior declaration. If no prior declaration is visible, or + // if the prior declaration specifies no linkage, then the + // identifier has external linkage. + if (New->hasExternalStorage() && Old->hasLinkage()) + /* Okay */; + else if (New->getStorageClass() != SC_Static && + Old->getStorageClass() == SC_Static) { + Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // Check if extern is followed by non-extern and vice-versa. + if (New->hasExternalStorage() && + !Old->hasLinkage() && Old->isLocalVarDecl()) { + Diag(New->getLocation(), diag::err_extern_non_extern) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + if (Old->hasExternalStorage() && + !New->hasLinkage() && New->isLocalVarDecl()) { + Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + // Variables with external linkage are analyzed in FinalizeDeclaratorGroup. + + // FIXME: The test for external storage here seems wrong? We still + // need to check for mismatches. + if (!New->hasExternalStorage() && !New->isFileVarDecl() && + // Don't complain about out-of-line definitions of static members. + !(Old->getLexicalDeclContext()->isRecord() && + !New->getLexicalDeclContext()->isRecord())) { + Diag(New->getLocation(), diag::err_redefinition) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + return New->setInvalidDecl(); + } + + if (New->isThreadSpecified() && !Old->isThreadSpecified()) { + Diag(New->getLocation(), diag::err_thread_non_thread) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + } else if (!New->isThreadSpecified() && Old->isThreadSpecified()) { + Diag(New->getLocation(), diag::err_non_thread_thread) << New->getDeclName(); + Diag(Old->getLocation(), diag::note_previous_definition); + } + + // C++ doesn't have tentative definitions, so go right ahead and check here. + const VarDecl *Def; + if (getLangOptions().CPlusPlus && + New->isThisDeclarationADefinition() == VarDecl::Definition && + (Def = Old->getDefinition())) { + Diag(New->getLocation(), diag::err_redefinition) + << New->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return; + } + // c99 6.2.2 P4. + // For an identifier declared with the storage-class specifier extern in a + // scope in which a prior declaration of that identifier is visible, if + // the prior declaration specifies internal or external linkage, the linkage + // of the identifier at the later declaration is the same as the linkage + // specified at the prior declaration. + // FIXME. revisit this code. + if (New->hasExternalStorage() && + Old->getLinkage() == InternalLinkage && + New->getDeclContext() == Old->getDeclContext()) + New->setStorageClass(Old->getStorageClass()); + + // Keep a chain of previous declarations. + New->setPreviousDeclaration(Old); + + // Inherit access appropriately. + New->setAccess(Old->getAccess()); +} + +/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with +/// no declarator (e.g. "struct foo;") is parsed. +Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS) { + return ParsedFreeStandingDeclSpec(S, AS, DS, + MultiTemplateParamsArg(*this, 0, 0)); +} + +/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with +/// no declarator (e.g. "struct foo;") is parsed. It also accopts template +/// parameters to cope with template friend declarations. +Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, + DeclSpec &DS, + MultiTemplateParamsArg TemplateParams) { + Decl *TagD = 0; + TagDecl *Tag = 0; + if (DS.getTypeSpecType() == DeclSpec::TST_class || + DS.getTypeSpecType() == DeclSpec::TST_struct || + DS.getTypeSpecType() == DeclSpec::TST_union || + DS.getTypeSpecType() == DeclSpec::TST_enum) { + TagD = DS.getRepAsDecl(); + + if (!TagD) // We probably had an error + return 0; + + // Note that the above type specs guarantee that the + // type rep is a Decl, whereas in many of the others + // it's a Type. + Tag = dyn_cast<TagDecl>(TagD); + } + + if (unsigned TypeQuals = DS.getTypeQualifiers()) { + // Enforce C99 6.7.3p2: "Types other than pointer types derived from object + // or incomplete types shall not be restrict-qualified." + if (TypeQuals & DeclSpec::TQ_restrict) + Diag(DS.getRestrictSpecLoc(), + diag::err_typecheck_invalid_restrict_not_pointer_noarg) + << DS.getSourceRange(); + } + + if (DS.isFriendSpecified()) { + // If we're dealing with a decl but not a TagDecl, assume that + // whatever routines created it handled the friendship aspect. + if (TagD && !Tag) + return 0; + return ActOnFriendTypeDecl(S, DS, TemplateParams); + } + + // Track whether we warned about the fact that there aren't any + // declarators. + bool emittedWarning = false; + + if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { + ProcessDeclAttributeList(S, Record, DS.getAttributes().getList()); + + if (!Record->getDeclName() && Record->isDefinition() && + DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { + if (getLangOptions().CPlusPlus || + Record->getDeclContext()->isRecord()) + return BuildAnonymousStructOrUnion(S, DS, AS, Record); + + Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) + << DS.getSourceRange(); + emittedWarning = true; + } + } + + // Check for Microsoft C extension: anonymous struct. + if (getLangOptions().Microsoft && !getLangOptions().CPlusPlus && + CurContext->isRecord() && + DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { + // Handle 2 kinds of anonymous struct: + // struct STRUCT; + // and + // STRUCT_TYPE; <- where STRUCT_TYPE is a typedef struct. + RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag); + if ((Record && Record->getDeclName() && !Record->isDefinition()) || + (DS.getTypeSpecType() == DeclSpec::TST_typename && + DS.getRepAsType().get()->isStructureType())) { + Diag(DS.getSourceRange().getBegin(), diag::ext_ms_anonymous_struct) + << DS.getSourceRange(); + return BuildMicrosoftCAnonymousStruct(S, DS, Record); + } + } + + if (getLangOptions().CPlusPlus && + DS.getStorageClassSpec() != DeclSpec::SCS_typedef) + if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag)) + if (Enum->enumerator_begin() == Enum->enumerator_end() && + !Enum->getIdentifier() && !Enum->isInvalidDecl()) { + Diag(Enum->getLocation(), diag::ext_no_declarators) + << DS.getSourceRange(); + emittedWarning = true; + } + + // Skip all the checks below if we have a type error. + if (DS.getTypeSpecType() == DeclSpec::TST_error) return TagD; + + if (!DS.isMissingDeclaratorOk()) { + // Warn about typedefs of enums without names, since this is an + // extension in both Microsoft and GNU. + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef && + Tag && isa<EnumDecl>(Tag)) { + Diag(DS.getSourceRange().getBegin(), diag::ext_typedef_without_a_name) + << DS.getSourceRange(); + return Tag; + } + + Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators) + << DS.getSourceRange(); + emittedWarning = true; + } + + // We're going to complain about a bunch of spurious specifiers; + // only do this if we're declaring a tag, because otherwise we + // should be getting diag::ext_no_declarators. + if (emittedWarning || (TagD && TagD->isInvalidDecl())) + return TagD; + + // Note that a linkage-specification sets a storage class, but + // 'extern "C" struct foo;' is actually valid and not theoretically + // useless. + if (DeclSpec::SCS scs = DS.getStorageClassSpec()) + if (!DS.isExternInLinkageSpec()) + Diag(DS.getStorageClassSpecLoc(), diag::warn_standalone_specifier) + << DeclSpec::getSpecifierName(scs); + + if (DS.isThreadSpecified()) + Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread"; + if (DS.getTypeQualifiers()) { + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const"; + if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) + Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile"; + // Restrict is covered above. + } + if (DS.isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::warn_standalone_specifier) << "inline"; + if (DS.isVirtualSpecified()) + Diag(DS.getVirtualSpecLoc(), diag::warn_standalone_specifier) << "virtual"; + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), diag::warn_standalone_specifier) <<"explicit"; + + // FIXME: Warn on useless attributes + + return TagD; +} + +/// ActOnVlaStmt - This rouine if finds a vla expression in a decl spec. +/// builds a statement for it and returns it so it is evaluated. +StmtResult Sema::ActOnVlaStmt(const DeclSpec &DS) { + StmtResult R; + if (DS.getTypeSpecType() == DeclSpec::TST_typeofExpr) { + Expr *Exp = DS.getRepAsExpr(); + QualType Ty = Exp->getType(); + if (Ty->isPointerType()) { + do + Ty = Ty->getAs<PointerType>()->getPointeeType(); + while (Ty->isPointerType()); + } + if (Ty->isVariableArrayType()) { + R = ActOnExprStmt(MakeFullExpr(Exp)); + } + } + return R; +} + +/// We are trying to inject an anonymous member into the given scope; +/// check if there's an existing declaration that can't be overloaded. +/// +/// \return true if this is a forbidden redeclaration +static bool CheckAnonMemberRedeclaration(Sema &SemaRef, + Scope *S, + DeclContext *Owner, + DeclarationName Name, + SourceLocation NameLoc, + unsigned diagnostic) { + LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName, + Sema::ForRedeclaration); + if (!SemaRef.LookupName(R, S)) return false; + + if (R.getAsSingle<TagDecl>()) + return false; + + // Pick a representative declaration. + NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); + assert(PrevDecl && "Expected a non-null Decl"); + + if (!SemaRef.isDeclInScope(PrevDecl, Owner, S)) + return false; + + SemaRef.Diag(NameLoc, diagnostic) << Name; + SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + + return true; +} + +/// InjectAnonymousStructOrUnionMembers - Inject the members of the +/// anonymous struct or union AnonRecord into the owning context Owner +/// and scope S. This routine will be invoked just after we realize +/// that an unnamed union or struct is actually an anonymous union or +/// struct, e.g., +/// +/// @code +/// union { +/// int i; +/// float f; +/// }; // InjectAnonymousStructOrUnionMembers called here to inject i and +/// // f into the surrounding scope.x +/// @endcode +/// +/// This routine is recursive, injecting the names of nested anonymous +/// structs/unions into the owning context and scope as well. +static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S, + DeclContext *Owner, + RecordDecl *AnonRecord, + AccessSpecifier AS, + llvm::SmallVector<NamedDecl*, 2> &Chaining, + bool MSAnonStruct) { + unsigned diagKind + = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl + : diag::err_anonymous_struct_member_redecl; + + bool Invalid = false; + + // Look every FieldDecl and IndirectFieldDecl with a name. + for (RecordDecl::decl_iterator D = AnonRecord->decls_begin(), + DEnd = AnonRecord->decls_end(); + D != DEnd; ++D) { + if ((isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) && + cast<NamedDecl>(*D)->getDeclName()) { + ValueDecl *VD = cast<ValueDecl>(*D); + if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, VD->getDeclName(), + VD->getLocation(), diagKind)) { + // C++ [class.union]p2: + // The names of the members of an anonymous union shall be + // distinct from the names of any other entity in the + // scope in which the anonymous union is declared. + Invalid = true; + } else { + // C++ [class.union]p2: + // For the purpose of name lookup, after the anonymous union + // definition, the members of the anonymous union are + // considered to have been defined in the scope in which the + // anonymous union is declared. + unsigned OldChainingSize = Chaining.size(); + if (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(VD)) + for (IndirectFieldDecl::chain_iterator PI = IF->chain_begin(), + PE = IF->chain_end(); PI != PE; ++PI) + Chaining.push_back(*PI); + else + Chaining.push_back(VD); + + assert(Chaining.size() >= 2); + NamedDecl **NamedChain = + new (SemaRef.Context)NamedDecl*[Chaining.size()]; + for (unsigned i = 0; i < Chaining.size(); i++) + NamedChain[i] = Chaining[i]; + + IndirectFieldDecl* IndirectField = + IndirectFieldDecl::Create(SemaRef.Context, Owner, VD->getLocation(), + VD->getIdentifier(), VD->getType(), + NamedChain, Chaining.size()); + + IndirectField->setAccess(AS); + IndirectField->setImplicit(); + SemaRef.PushOnScopeChains(IndirectField, S); + + // That includes picking up the appropriate access specifier. + if (AS != AS_none) IndirectField->setAccess(AS); + + Chaining.resize(OldChainingSize); + } + } + } + + return Invalid; +} + +/// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to +/// a VarDecl::StorageClass. Any error reporting is up to the caller: +/// illegal input values are mapped to SC_None. +static StorageClass +StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) { + switch (StorageClassSpec) { + case DeclSpec::SCS_unspecified: return SC_None; + case DeclSpec::SCS_extern: return SC_Extern; + case DeclSpec::SCS_static: return SC_Static; + case DeclSpec::SCS_auto: return SC_Auto; + case DeclSpec::SCS_register: return SC_Register; + case DeclSpec::SCS_private_extern: return SC_PrivateExtern; + // Illegal SCSs map to None: error reporting is up to the caller. + case DeclSpec::SCS_mutable: // Fall through. + case DeclSpec::SCS_typedef: return SC_None; + } + llvm_unreachable("unknown storage class specifier"); +} + +/// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to +/// a StorageClass. Any error reporting is up to the caller: +/// illegal input values are mapped to SC_None. +static StorageClass +StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) { + switch (StorageClassSpec) { + case DeclSpec::SCS_unspecified: return SC_None; + case DeclSpec::SCS_extern: return SC_Extern; + case DeclSpec::SCS_static: return SC_Static; + case DeclSpec::SCS_private_extern: return SC_PrivateExtern; + // Illegal SCSs map to None: error reporting is up to the caller. + case DeclSpec::SCS_auto: // Fall through. + case DeclSpec::SCS_mutable: // Fall through. + case DeclSpec::SCS_register: // Fall through. + case DeclSpec::SCS_typedef: return SC_None; + } + llvm_unreachable("unknown storage class specifier"); +} + +/// BuildAnonymousStructOrUnion - Handle the declaration of an +/// anonymous structure or union. Anonymous unions are a C++ feature +/// (C++ [class.union]) and a GNU C extension; anonymous structures +/// are a GNU C and GNU C++ extension. +Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, + AccessSpecifier AS, + RecordDecl *Record) { + DeclContext *Owner = Record->getDeclContext(); + + // Diagnose whether this anonymous struct/union is an extension. + if (Record->isUnion() && !getLangOptions().CPlusPlus) + Diag(Record->getLocation(), diag::ext_anonymous_union); + else if (!Record->isUnion()) + Diag(Record->getLocation(), diag::ext_anonymous_struct); + + // C and C++ require different kinds of checks for anonymous + // structs/unions. + bool Invalid = false; + if (getLangOptions().CPlusPlus) { + const char* PrevSpec = 0; + unsigned DiagID; + // C++ [class.union]p3: + // Anonymous unions declared in a named namespace or in the + // global namespace shall be declared static. + if (DS.getStorageClassSpec() != DeclSpec::SCS_static && + (isa<TranslationUnitDecl>(Owner) || + (isa<NamespaceDecl>(Owner) && + cast<NamespaceDecl>(Owner)->getDeclName()))) { + Diag(Record->getLocation(), diag::err_anonymous_union_not_static); + Invalid = true; + + // Recover by adding 'static'. + DS.SetStorageClassSpec(DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID, getLangOptions()); + } + // C++ [class.union]p3: + // A storage class is not allowed in a declaration of an + // anonymous union in a class scope. + else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && + isa<RecordDecl>(Owner)) { + Diag(DS.getStorageClassSpecLoc(), + diag::err_anonymous_union_with_storage_spec); + Invalid = true; + + // Recover by removing the storage specifier. + DS.SetStorageClassSpec(DeclSpec::SCS_unspecified, SourceLocation(), + PrevSpec, DiagID, getLangOptions()); + } + + // Ignore const/volatile/restrict qualifiers. + if (DS.getTypeQualifiers()) { + if (DS.getTypeQualifiers() & DeclSpec::TQ_const) + Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << 0 + << FixItHint::CreateRemoval(DS.getConstSpecLoc()); + if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) + Diag(DS.getVolatileSpecLoc(), diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << 1 + << FixItHint::CreateRemoval(DS.getVolatileSpecLoc()); + if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) + Diag(DS.getRestrictSpecLoc(), diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << 2 + << FixItHint::CreateRemoval(DS.getRestrictSpecLoc()); + + DS.ClearTypeQualifiers(); + } + + // C++ [class.union]p2: + // The member-specification of an anonymous union shall only + // define non-static data members. [Note: nested types and + // functions cannot be declared within an anonymous union. ] + for (DeclContext::decl_iterator Mem = Record->decls_begin(), + MemEnd = Record->decls_end(); + Mem != MemEnd; ++Mem) { + if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) { + // C++ [class.union]p3: + // An anonymous union shall not have private or protected + // members (clause 11). + assert(FD->getAccess() != AS_none); + if (FD->getAccess() != AS_public) { + Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member) + << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected); + Invalid = true; + } + + // C++ [class.union]p1 + // An object of a class with a non-trivial constructor, a non-trivial + // copy constructor, a non-trivial destructor, or a non-trivial copy + // assignment operator cannot be a member of a union, nor can an + // array of such objects. + if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(FD)) + Invalid = true; + } else if ((*Mem)->isImplicit()) { + // Any implicit members are fine. + } else if (isa<TagDecl>(*Mem) && (*Mem)->getDeclContext() != Record) { + // This is a type that showed up in an + // elaborated-type-specifier inside the anonymous struct or + // union, but which actually declares a type outside of the + // anonymous struct or union. It's okay. + } else if (RecordDecl *MemRecord = dyn_cast<RecordDecl>(*Mem)) { + if (!MemRecord->isAnonymousStructOrUnion() && + MemRecord->getDeclName()) { + // Visual C++ allows type definition in anonymous struct or union. + if (getLangOptions().Microsoft) + Diag(MemRecord->getLocation(), diag::ext_anonymous_record_with_type) + << (int)Record->isUnion(); + else { + // This is a nested type declaration. + Diag(MemRecord->getLocation(), diag::err_anonymous_record_with_type) + << (int)Record->isUnion(); + Invalid = true; + } + } + } else if (isa<AccessSpecDecl>(*Mem)) { + // Any access specifier is fine. + } else { + // We have something that isn't a non-static data + // member. Complain about it. + unsigned DK = diag::err_anonymous_record_bad_member; + if (isa<TypeDecl>(*Mem)) + DK = diag::err_anonymous_record_with_type; + else if (isa<FunctionDecl>(*Mem)) + DK = diag::err_anonymous_record_with_function; + else if (isa<VarDecl>(*Mem)) + DK = diag::err_anonymous_record_with_static; + + // Visual C++ allows type definition in anonymous struct or union. + if (getLangOptions().Microsoft && + DK == diag::err_anonymous_record_with_type) + Diag((*Mem)->getLocation(), diag::ext_anonymous_record_with_type) + << (int)Record->isUnion(); + else { + Diag((*Mem)->getLocation(), DK) + << (int)Record->isUnion(); + Invalid = true; + } + } + } + } + + if (!Record->isUnion() && !Owner->isRecord()) { + Diag(Record->getLocation(), diag::err_anonymous_struct_not_member) + << (int)getLangOptions().CPlusPlus; + Invalid = true; + } + + // Mock up a declarator. + Declarator Dc(DS, Declarator::TypeNameContext); + TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); + assert(TInfo && "couldn't build declarator info for anonymous struct/union"); + + // Create a declaration for this anonymous struct/union. + NamedDecl *Anon = 0; + if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) { + Anon = FieldDecl::Create(Context, OwningClass, + DS.getSourceRange().getBegin(), + Record->getLocation(), + /*IdentifierInfo=*/0, + Context.getTypeDeclType(Record), + TInfo, + /*BitWidth=*/0, /*Mutable=*/false, + /*HasInit=*/false); + Anon->setAccess(AS); + if (getLangOptions().CPlusPlus) + FieldCollector->Add(cast<FieldDecl>(Anon)); + } else { + DeclSpec::SCS SCSpec = DS.getStorageClassSpec(); + assert(SCSpec != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class VarDecl."); + VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec); + if (SCSpec == DeclSpec::SCS_mutable) { + // mutable can only appear on non-static class members, so it's always + // an error here + Diag(Record->getLocation(), diag::err_mutable_nonmember); + Invalid = true; + SC = SC_None; + } + SCSpec = DS.getStorageClassSpecAsWritten(); + VarDecl::StorageClass SCAsWritten + = StorageClassSpecToVarDeclStorageClass(SCSpec); + + Anon = VarDecl::Create(Context, Owner, + DS.getSourceRange().getBegin(), + Record->getLocation(), /*IdentifierInfo=*/0, + Context.getTypeDeclType(Record), + TInfo, SC, SCAsWritten); + } + Anon->setImplicit(); + + // Add the anonymous struct/union object to the current + // context. We'll be referencing this object when we refer to one of + // its members. + Owner->addDecl(Anon); + + // Inject the members of the anonymous struct/union into the owning + // context and into the identifier resolver chain for name lookup + // purposes. + llvm::SmallVector<NamedDecl*, 2> Chain; + Chain.push_back(Anon); + + if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS, + Chain, false)) + Invalid = true; + + // Mark this as an anonymous struct/union type. Note that we do not + // do this until after we have already checked and injected the + // members of this anonymous struct/union type, because otherwise + // the members could be injected twice: once by DeclContext when it + // builds its lookup table, and once by + // InjectAnonymousStructOrUnionMembers. + Record->setAnonymousStructOrUnion(true); + + if (Invalid) + Anon->setInvalidDecl(); + + return Anon; +} + +/// BuildMicrosoftCAnonymousStruct - Handle the declaration of an +/// Microsoft C anonymous structure. +/// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx +/// Example: +/// +/// struct A { int a; }; +/// struct B { struct A; int b; }; +/// +/// void foo() { +/// B var; +/// var.a = 3; +/// } +/// +Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, + RecordDecl *Record) { + + // If there is no Record, get the record via the typedef. + if (!Record) + Record = DS.getRepAsType().get()->getAsStructureType()->getDecl(); + + // Mock up a declarator. + Declarator Dc(DS, Declarator::TypeNameContext); + TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); + assert(TInfo && "couldn't build declarator info for anonymous struct"); + + // Create a declaration for this anonymous struct. + NamedDecl* Anon = FieldDecl::Create(Context, + cast<RecordDecl>(CurContext), + DS.getSourceRange().getBegin(), + DS.getSourceRange().getBegin(), + /*IdentifierInfo=*/0, + Context.getTypeDeclType(Record), + TInfo, + /*BitWidth=*/0, /*Mutable=*/false, + /*HasInit=*/false); + Anon->setImplicit(); + + // Add the anonymous struct object to the current context. + CurContext->addDecl(Anon); + + // Inject the members of the anonymous struct into the current + // context and into the identifier resolver chain for name lookup + // purposes. + llvm::SmallVector<NamedDecl*, 2> Chain; + Chain.push_back(Anon); + + if (InjectAnonymousStructOrUnionMembers(*this, S, CurContext, + Record->getDefinition(), + AS_none, Chain, true)) + Anon->setInvalidDecl(); + + return Anon; +} + +/// GetNameForDeclarator - Determine the full declaration name for the +/// given Declarator. +DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) { + return GetNameFromUnqualifiedId(D.getName()); +} + +/// \brief Retrieves the declaration name from a parsed unqualified-id. +DeclarationNameInfo +Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { + DeclarationNameInfo NameInfo; + NameInfo.setLoc(Name.StartLocation); + + switch (Name.getKind()) { + + case UnqualifiedId::IK_Identifier: + NameInfo.setName(Name.Identifier); + NameInfo.setLoc(Name.StartLocation); + return NameInfo; + + case UnqualifiedId::IK_OperatorFunctionId: + NameInfo.setName(Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator)); + NameInfo.setLoc(Name.StartLocation); + NameInfo.getInfo().CXXOperatorName.BeginOpNameLoc + = Name.OperatorFunctionId.SymbolLocations[0]; + NameInfo.getInfo().CXXOperatorName.EndOpNameLoc + = Name.EndLocation.getRawEncoding(); + return NameInfo; + + case UnqualifiedId::IK_LiteralOperatorId: + NameInfo.setName(Context.DeclarationNames.getCXXLiteralOperatorName( + Name.Identifier)); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setCXXLiteralOperatorNameLoc(Name.EndLocation); + return NameInfo; + + case UnqualifiedId::IK_ConversionFunctionId: { + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(Name.ConversionFunctionId, &TInfo); + if (Ty.isNull()) + return DeclarationNameInfo(); + NameInfo.setName(Context.DeclarationNames.getCXXConversionFunctionName( + Context.getCanonicalType(Ty))); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setNamedTypeInfo(TInfo); + return NameInfo; + } + + case UnqualifiedId::IK_ConstructorName: { + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(Name.ConstructorName, &TInfo); + if (Ty.isNull()) + return DeclarationNameInfo(); + NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(Ty))); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setNamedTypeInfo(TInfo); + return NameInfo; + } + + case UnqualifiedId::IK_ConstructorTemplateId: { + // In well-formed code, we can only have a constructor + // template-id that refers to the current context, so go there + // to find the actual type being constructed. + CXXRecordDecl *CurClass = dyn_cast<CXXRecordDecl>(CurContext); + if (!CurClass || CurClass->getIdentifier() != Name.TemplateId->Name) + return DeclarationNameInfo(); + + // Determine the type of the class being constructed. + QualType CurClassType = Context.getTypeDeclType(CurClass); + + // FIXME: Check two things: that the template-id names the same type as + // CurClassType, and that the template-id does not occur when the name + // was qualified. + + NameInfo.setName(Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(CurClassType))); + NameInfo.setLoc(Name.StartLocation); + // FIXME: should we retrieve TypeSourceInfo? + NameInfo.setNamedTypeInfo(0); + return NameInfo; + } + + case UnqualifiedId::IK_DestructorName: { + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(Name.DestructorName, &TInfo); + if (Ty.isNull()) + return DeclarationNameInfo(); + NameInfo.setName(Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(Ty))); + NameInfo.setLoc(Name.StartLocation); + NameInfo.setNamedTypeInfo(TInfo); + return NameInfo; + } + + case UnqualifiedId::IK_TemplateId: { + TemplateName TName = Name.TemplateId->Template.get(); + SourceLocation TNameLoc = Name.TemplateId->TemplateNameLoc; + return Context.getNameForTemplate(TName, TNameLoc); + } + + } // switch (Name.getKind()) + + assert(false && "Unknown name kind"); + return DeclarationNameInfo(); +} + +/// isNearlyMatchingFunction - Determine whether the C++ functions +/// Declaration and Definition are "nearly" matching. This heuristic +/// is used to improve diagnostics in the case where an out-of-line +/// function definition doesn't match any declaration within +/// the class or namespace. +static bool isNearlyMatchingFunction(ASTContext &Context, + FunctionDecl *Declaration, + FunctionDecl *Definition) { + if (Declaration->param_size() != Definition->param_size()) + return false; + for (unsigned Idx = 0; Idx < Declaration->param_size(); ++Idx) { + QualType DeclParamTy = Declaration->getParamDecl(Idx)->getType(); + QualType DefParamTy = Definition->getParamDecl(Idx)->getType(); + + if (!Context.hasSameUnqualifiedType(DeclParamTy.getNonReferenceType(), + DefParamTy.getNonReferenceType())) + return false; + } + + return true; +} + +/// NeedsRebuildingInCurrentInstantiation - Checks whether the given +/// declarator needs to be rebuilt in the current instantiation. +/// Any bits of declarator which appear before the name are valid for +/// consideration here. That's specifically the type in the decl spec +/// and the base type in any member-pointer chunks. +static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, + DeclarationName Name) { + // The types we specifically need to rebuild are: + // - typenames, typeofs, and decltypes + // - types which will become injected class names + // Of course, we also need to rebuild any type referencing such a + // type. It's safest to just say "dependent", but we call out a + // few cases here. + + DeclSpec &DS = D.getMutableDeclSpec(); + switch (DS.getTypeSpecType()) { + case DeclSpec::TST_typename: + case DeclSpec::TST_typeofType: + case DeclSpec::TST_decltype: + case DeclSpec::TST_underlyingType: { + // Grab the type from the parser. + TypeSourceInfo *TSI = 0; + QualType T = S.GetTypeFromParser(DS.getRepAsType(), &TSI); + if (T.isNull() || !T->isDependentType()) break; + + // Make sure there's a type source info. This isn't really much + // of a waste; most dependent types should have type source info + // attached already. + if (!TSI) + TSI = S.Context.getTrivialTypeSourceInfo(T, DS.getTypeSpecTypeLoc()); + + // Rebuild the type in the current instantiation. + TSI = S.RebuildTypeInCurrentInstantiation(TSI, D.getIdentifierLoc(), Name); + if (!TSI) return true; + + // Store the new type back in the decl spec. + ParsedType LocType = S.CreateParsedType(TSI->getType(), TSI); + DS.UpdateTypeRep(LocType); + break; + } + + case DeclSpec::TST_typeofExpr: { + Expr *E = DS.getRepAsExpr(); + ExprResult Result = S.RebuildExprInCurrentInstantiation(E); + if (Result.isInvalid()) return true; + DS.UpdateExprRep(Result.get()); + break; + } + + default: + // Nothing to do for these decl specs. + break; + } + + // It doesn't matter what order we do this in. + for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) { + DeclaratorChunk &Chunk = D.getTypeObject(I); + + // The only type information in the declarator which can come + // before the declaration name is the base type of a member + // pointer. + if (Chunk.Kind != DeclaratorChunk::MemberPointer) + continue; + + // Rebuild the scope specifier in-place. + CXXScopeSpec &SS = Chunk.Mem.Scope(); + if (S.RebuildNestedNameSpecifierInCurrentInstantiation(SS)) + return true; + } + + return false; +} + +Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D, + bool IsFunctionDefinition) { + return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), + IsFunctionDefinition); +} + +/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: +/// If T is the name of a class, then each of the following shall have a +/// name different from T: +/// - every static data member of class T; +/// - every member function of class T +/// - every member of class T that is itself a type; +/// \returns true if the declaration name violates these rules. +bool Sema::DiagnoseClassNameShadow(DeclContext *DC, + DeclarationNameInfo NameInfo) { + DeclarationName Name = NameInfo.getName(); + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getIdentifier() && Record->getDeclName() == Name) { + Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; + return true; + } + + return false; +} + +Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists, + bool IsFunctionDefinition) { + // TODO: consider using NameInfo for diagnostic. + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + + // All of these full declarators require an identifier. If it doesn't have + // one, the ParsedFreeStandingDeclSpec action should be used. + if (!Name) { + if (!D.isInvalidType()) // Reject this if we think it is valid. + Diag(D.getDeclSpec().getSourceRange().getBegin(), + diag::err_declarator_need_ident) + << D.getDeclSpec().getSourceRange() << D.getSourceRange(); + return 0; + } else if (DiagnoseUnexpandedParameterPack(NameInfo, UPPC_DeclarationType)) + return 0; + + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + while ((S->getFlags() & Scope::DeclScope) == 0 || + (S->getFlags() & Scope::TemplateParamScope) != 0) + S = S->getParent(); + + DeclContext *DC = CurContext; + if (D.getCXXScopeSpec().isInvalid()) + D.setInvalidType(); + else if (D.getCXXScopeSpec().isSet()) { + if (DiagnoseUnexpandedParameterPack(D.getCXXScopeSpec(), + UPPC_DeclarationQualifier)) + return 0; + + bool EnteringContext = !D.getDeclSpec().isFriendSpecified(); + DC = computeDeclContext(D.getCXXScopeSpec(), EnteringContext); + if (!DC) { + // If we could not compute the declaration context, it's because the + // declaration context is dependent but does not refer to a class, + // class template, or class template partial specialization. Complain + // and return early, to avoid the coming semantic disaster. + Diag(D.getIdentifierLoc(), + diag::err_template_qualified_declarator_no_match) + << (NestedNameSpecifier*)D.getCXXScopeSpec().getScopeRep() + << D.getCXXScopeSpec().getRange(); + return 0; + } + bool IsDependentContext = DC->isDependentContext(); + + if (!IsDependentContext && + RequireCompleteDeclContext(D.getCXXScopeSpec(), DC)) + return 0; + + if (isa<CXXRecordDecl>(DC)) { + if (!cast<CXXRecordDecl>(DC)->hasDefinition()) { + Diag(D.getIdentifierLoc(), + diag::err_member_def_undefined_record) + << Name << DC << D.getCXXScopeSpec().getRange(); + D.setInvalidType(); + } else if (isa<CXXRecordDecl>(CurContext) && + !D.getDeclSpec().isFriendSpecified()) { + // The user provided a superfluous scope specifier inside a class + // definition: + // + // class X { + // void X::f(); + // }; + if (CurContext->Equals(DC)) + Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification) + << Name << FixItHint::CreateRemoval(D.getCXXScopeSpec().getRange()); + else + Diag(D.getIdentifierLoc(), diag::err_member_qualification) + << Name << D.getCXXScopeSpec().getRange(); + + // Pretend that this qualifier was not here. + D.getCXXScopeSpec().clear(); + } + } + + // Check whether we need to rebuild the type of the given + // declaration in the current instantiation. + if (EnteringContext && IsDependentContext && + TemplateParamLists.size() != 0) { + ContextRAII SavedContext(*this, DC); + if (RebuildDeclaratorInCurrentInstantiation(*this, D, Name)) + D.setInvalidType(); + } + } + + if (DiagnoseClassNameShadow(DC, NameInfo)) + // If this is a typedef, we'll end up spewing multiple diagnostics. + // Just return early; it's safer. + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + return 0; + + NamedDecl *New; + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType R = TInfo->getType(); + + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_DeclarationType)) + D.setInvalidType(); + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, + ForRedeclaration); + + // See if this is a redefinition of a variable in the same scope. + if (!D.getCXXScopeSpec().isSet()) { + bool IsLinkageLookup = false; + + // If the declaration we're planning to build will be a function + // or object with linkage, then look for another declaration with + // linkage (C99 6.2.2p4-5 and C++ [basic.link]p6). + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + /* Do nothing*/; + else if (R->isFunctionType()) { + if (CurContext->isFunctionOrMethod() || + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + IsLinkageLookup = true; + } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern) + IsLinkageLookup = true; + else if (CurContext->getRedeclContext()->isTranslationUnit() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) + IsLinkageLookup = true; + + if (IsLinkageLookup) + Previous.clear(LookupRedeclarationWithLinkage); + + LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup); + } else { // Something like "int foo::x;" + LookupQualifiedName(Previous, DC); + + // Don't consider using declarations as previous declarations for + // out-of-line members. + RemoveUsingDecls(Previous); + + // C++ 7.3.1.2p2: + // Members (including explicit specializations of templates) of a named + // namespace can also be defined outside that namespace by explicit + // qualification of the name being defined, provided that the entity being + // defined was already declared in the namespace and the definition appears + // after the point of declaration in a namespace that encloses the + // declarations namespace. + // + // Note that we only check the context at this point. We don't yet + // have enough information to make sure that PrevDecl is actually + // the declaration we want to match. For example, given: + // + // class X { + // void f(); + // void f(float); + // }; + // + // void X::f(int) { } // ill-formed + // + // In this case, PrevDecl will point to the overload set + // containing the two f's declared in X, but neither of them + // matches. + + // First check whether we named the global scope. + if (isa<TranslationUnitDecl>(DC)) { + Diag(D.getIdentifierLoc(), diag::err_invalid_declarator_global_scope) + << Name << D.getCXXScopeSpec().getRange(); + } else { + DeclContext *Cur = CurContext; + while (isa<LinkageSpecDecl>(Cur)) + Cur = Cur->getParent(); + if (!Cur->Encloses(DC)) { + // The qualifying scope doesn't enclose the original declaration. + // Emit diagnostic based on current scope. + SourceLocation L = D.getIdentifierLoc(); + SourceRange R = D.getCXXScopeSpec().getRange(); + if (isa<FunctionDecl>(Cur)) + Diag(L, diag::err_invalid_declarator_in_function) << Name << R; + else + Diag(L, diag::err_invalid_declarator_scope) + << Name << cast<NamedDecl>(DC) << R; + D.setInvalidType(); + } + } + } + + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + if (!D.isInvalidType()) + if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), + Previous.getFoundDecl())) + D.setInvalidType(); + + // Just pretend that we didn't see the previous declaration. + Previous.clear(); + } + + // In C++, the previous declaration we find might be a tag type + // (class or enum). In this case, the new declaration will hide the + // tag type. Note that this does does not apply if we're declaring a + // typedef (C++ [dcl.typedef]p4). + if (Previous.isSingleTagDecl() && + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) + Previous.clear(); + + bool Redeclaration = false; + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { + if (TemplateParamLists.size()) { + Diag(D.getIdentifierLoc(), diag::err_template_typedef); + return 0; + } + + New = ActOnTypedefDeclarator(S, D, DC, R, TInfo, Previous, Redeclaration); + } else if (R->isFunctionType()) { + New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous, + move(TemplateParamLists), + IsFunctionDefinition, Redeclaration); + } else { + New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous, + move(TemplateParamLists), + Redeclaration); + } + + if (New == 0) + return 0; + + // If this has an identifier and is not an invalid redeclaration or + // function template specialization, add it to the scope stack. + if (New->getDeclName() && !(Redeclaration && New->isInvalidDecl())) + PushOnScopeChains(New, S); + + return New; +} + +/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array +/// types into constant array types in certain situations which would otherwise +/// be errors (for GCC compatibility). +static QualType TryToFixInvalidVariablyModifiedType(QualType T, + ASTContext &Context, + bool &SizeIsNegative, + llvm::APSInt &Oversized) { + // This method tries to turn a variable array into a constant + // array even when the size isn't an ICE. This is necessary + // for compatibility with code that depends on gcc's buggy + // constant expression folding, like struct {char x[(int)(char*)2];} + SizeIsNegative = false; + Oversized = 0; + + if (T->isDependentType()) + return QualType(); + + QualifierCollector Qs; + const Type *Ty = Qs.strip(T); + + if (const PointerType* PTy = dyn_cast<PointerType>(Ty)) { + QualType Pointee = PTy->getPointeeType(); + QualType FixedType = + TryToFixInvalidVariablyModifiedType(Pointee, Context, SizeIsNegative, + Oversized); + if (FixedType.isNull()) return FixedType; + FixedType = Context.getPointerType(FixedType); + return Qs.apply(Context, FixedType); + } + if (const ParenType* PTy = dyn_cast<ParenType>(Ty)) { + QualType Inner = PTy->getInnerType(); + QualType FixedType = + TryToFixInvalidVariablyModifiedType(Inner, Context, SizeIsNegative, + Oversized); + if (FixedType.isNull()) return FixedType; + FixedType = Context.getParenType(FixedType); + return Qs.apply(Context, FixedType); + } + + const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T); + if (!VLATy) + return QualType(); + // FIXME: We should probably handle this case + if (VLATy->getElementType()->isVariablyModifiedType()) + return QualType(); + + Expr::EvalResult EvalResult; + if (!VLATy->getSizeExpr() || + !VLATy->getSizeExpr()->Evaluate(EvalResult, Context) || + !EvalResult.Val.isInt()) + return QualType(); + + // Check whether the array size is negative. + llvm::APSInt &Res = EvalResult.Val.getInt(); + if (Res.isSigned() && Res.isNegative()) { + SizeIsNegative = true; + return QualType(); + } + + // Check whether the array is too large to be addressed. + unsigned ActiveSizeBits + = ConstantArrayType::getNumAddressingBits(Context, VLATy->getElementType(), + Res); + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { + Oversized = Res; + return QualType(); + } + + return Context.getConstantArrayType(VLATy->getElementType(), + Res, ArrayType::Normal, 0); +} + +/// \brief Register the given locally-scoped external C declaration so +/// that it can be found later for redeclarations +void +Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, + const LookupResult &Previous, + Scope *S) { + assert(ND->getLexicalDeclContext()->isFunctionOrMethod() && + "Decl is not a locally-scoped decl!"); + // Note that we have a locally-scoped external with this name. + LocallyScopedExternalDecls[ND->getDeclName()] = ND; + + if (!Previous.isSingleResult()) + return; + + NamedDecl *PrevDecl = Previous.getFoundDecl(); + + // If there was a previous declaration of this variable, it may be + // in our identifier chain. Update the identifier chain with the new + // declaration. + if (S && IdResolver.ReplaceDecl(PrevDecl, ND)) { + // The previous declaration was found on the identifer resolver + // chain, so remove it from its scope. + while (S && !S->isDeclScope(PrevDecl)) + S = S->getParent(); + + if (S) + S->RemoveDecl(PrevDecl); + } +} + +/// \brief Diagnose function specifiers on a declaration of an identifier that +/// does not identify a function. +void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { + // FIXME: We should probably indicate the identifier in question to avoid + // confusion for constructs like "inline int a(), b;" + if (D.getDeclSpec().isInlineSpecified()) + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_inline_non_function); + + if (D.getDeclSpec().isVirtualSpecified()) + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_non_function); + + if (D.getDeclSpec().isExplicitSpecified()) + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_non_function); +} + +NamedDecl* +Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, + QualType R, TypeSourceInfo *TInfo, + LookupResult &Previous, bool &Redeclaration) { + // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1). + if (D.getCXXScopeSpec().isSet()) { + Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator) + << D.getCXXScopeSpec().getRange(); + D.setInvalidType(); + // Pretend we didn't see the scope specifier. + DC = CurContext; + Previous.clear(); + } + + if (getLangOptions().CPlusPlus) { + // Check that there are no default arguments (C++ only). + CheckExtraCXXDefaultArguments(D); + } + + DiagnoseFunctionSpecifiers(D); + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + + if (D.getName().Kind != UnqualifiedId::IK_Identifier) { + Diag(D.getName().StartLocation, diag::err_typedef_not_identifier) + << D.getName().getSourceRange(); + return 0; + } + + TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, TInfo); + if (!NewTD) return 0; + + // Handle attributes prior to checking for duplicates in MergeVarDecl + ProcessDeclAttributes(S, NewTD, D); + + CheckTypedefForVariablyModifiedType(S, NewTD); + + return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); +} + +void +Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { + // C99 6.7.7p2: If a typedef name specifies a variably modified type + // then it shall have block scope. + // Note that variably modified types must be fixed before merging the decl so + // that redeclarations will match. + QualType T = NewTD->getUnderlyingType(); + if (T->isVariablyModifiedType()) { + getCurFunction()->setHasBranchProtectedScope(); + + if (S->getFnParent() == 0) { + bool SizeIsNegative; + llvm::APSInt Oversized; + QualType FixedTy = + TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); + if (!FixedTy.isNull()) { + Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); + NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); + } else { + if (SizeIsNegative) + Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); + else if (T->isVariableArrayType()) + Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); + else if (Oversized.getBoolValue()) + Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10); + else + Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); + NewTD->setInvalidDecl(); + } + } + } +} + + +/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which +/// declares a typedef-name, either using the 'typedef' type specifier or via +/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. +NamedDecl* +Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, + LookupResult &Previous, bool &Redeclaration) { + // Merge the decl with the existing one if appropriate. If the decl is + // in an outer scope, it isn't the same thing. + FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false, + /*ExplicitInstantiationOrSpecialization=*/false); + if (!Previous.empty()) { + Redeclaration = true; + MergeTypedefNameDecl(NewTD, Previous); + } + + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = NewTD->getIdentifier()) + if (!NewTD->isInvalidDecl() && + NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + if (II->isStr("FILE")) + Context.setFILEDecl(NewTD); + else if (II->isStr("jmp_buf")) + Context.setjmp_bufDecl(NewTD); + else if (II->isStr("sigjmp_buf")) + Context.setsigjmp_bufDecl(NewTD); + else if (II->isStr("__builtin_va_list")) + Context.setBuiltinVaListType(Context.getTypedefType(NewTD)); + } + + return NewTD; +} + +/// \brief Determines whether the given declaration is an out-of-scope +/// previous declaration. +/// +/// This routine should be invoked when name lookup has found a +/// previous declaration (PrevDecl) that is not in the scope where a +/// new declaration by the same name is being introduced. If the new +/// declaration occurs in a local scope, previous declarations with +/// linkage may still be considered previous declarations (C99 +/// 6.2.2p4-5, C++ [basic.link]p6). +/// +/// \param PrevDecl the previous declaration found by name +/// lookup +/// +/// \param DC the context in which the new declaration is being +/// declared. +/// +/// \returns true if PrevDecl is an out-of-scope previous declaration +/// for a new delcaration with the same name. +static bool +isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC, + ASTContext &Context) { + if (!PrevDecl) + return false; + + if (!PrevDecl->hasLinkage()) + return false; + + if (Context.getLangOptions().CPlusPlus) { + // C++ [basic.link]p6: + // If there is a visible declaration of an entity with linkage + // having the same name and type, ignoring entities declared + // outside the innermost enclosing namespace scope, the block + // scope declaration declares that same entity and receives the + // linkage of the previous declaration. + DeclContext *OuterContext = DC->getRedeclContext(); + if (!OuterContext->isFunctionOrMethod()) + // This rule only applies to block-scope declarations. + return false; + + DeclContext *PrevOuterContext = PrevDecl->getDeclContext(); + if (PrevOuterContext->isRecord()) + // We found a member function: ignore it. + return false; + + // Find the innermost enclosing namespace for the new and + // previous declarations. + OuterContext = OuterContext->getEnclosingNamespaceContext(); + PrevOuterContext = PrevOuterContext->getEnclosingNamespaceContext(); + + // The previous declaration is in a different namespace, so it + // isn't the same function. + if (!OuterContext->Equals(PrevOuterContext)) + return false; + } + + return true; +} + +static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { + CXXScopeSpec &SS = D.getCXXScopeSpec(); + if (!SS.isSet()) return; + DD->setQualifierInfo(SS.getWithLocInContext(DD->getASTContext())); +} + +NamedDecl* +Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, + QualType R, TypeSourceInfo *TInfo, + LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists, + bool &Redeclaration) { + DeclarationName Name = GetNameForDeclarator(D).getName(); + + // Check that there are no default arguments (C++ only). + if (getLangOptions().CPlusPlus) + CheckExtraCXXDefaultArguments(D); + + DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); + assert(SCSpec != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class VarDecl."); + VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec); + if (SCSpec == DeclSpec::SCS_mutable) { + // mutable can only appear on non-static class members, so it's always + // an error here + Diag(D.getIdentifierLoc(), diag::err_mutable_nonmember); + D.setInvalidType(); + SC = SC_None; + } + SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); + VarDecl::StorageClass SCAsWritten + = StorageClassSpecToVarDeclStorageClass(SCSpec); + + IdentifierInfo *II = Name.getAsIdentifierInfo(); + if (!II) { + Diag(D.getIdentifierLoc(), diag::err_bad_variable_name) + << Name.getAsString(); + return 0; + } + + DiagnoseFunctionSpecifiers(D); + + if (!DC->isRecord() && S->getFnParent() == 0) { + // C99 6.9p2: The storage-class specifiers auto and register shall not + // appear in the declaration specifiers in an external declaration. + if (SC == SC_Auto || SC == SC_Register) { + + // If this is a register variable with an asm label specified, then this + // is a GNU extension. + if (SC == SC_Register && D.getAsmLabel()) + Diag(D.getIdentifierLoc(), diag::err_unsupported_global_register); + else + Diag(D.getIdentifierLoc(), diag::err_typecheck_sclass_fscope); + D.setInvalidType(); + } + } + + bool isExplicitSpecialization = false; + VarDecl *NewVD; + if (!getLangOptions().CPlusPlus) { + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); + + if (D.isInvalidType()) + NewVD->setInvalidDecl(); + } else { + if (DC->isRecord() && !CurContext->isRecord()) { + // This is an out-of-line definition of a static data member. + if (SC == SC_Static) { + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_static_out_of_line) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + } else if (SC == SC_None) + SC = SC_Static; + } + if (SC == SC_Static) { + if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { + if (RD->isLocalClass()) + Diag(D.getIdentifierLoc(), + diag::err_static_data_member_not_allowed_in_local_class) + << Name << RD->getDeclName(); + + // C++ [class.union]p1: If a union contains a static data member, + // the program is ill-formed. + // + // We also disallow static data members in anonymous structs. + if (CurContext->isRecord() && (RD->isUnion() || !RD->getDeclName())) + Diag(D.getIdentifierLoc(), + diag::err_static_data_member_not_allowed_in_union_or_anon_struct) + << Name << RD->isUnion(); + } + } + + // Match up the template parameter lists with the scope specifier, then + // determine whether we have a template or a template specialization. + isExplicitSpecialization = false; + bool Invalid = false; + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getCXXScopeSpec(), + TemplateParamLists.get(), + TemplateParamLists.size(), + /*never a friend*/ false, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // There is no such thing as a variable template. + Diag(D.getIdentifierLoc(), diag::err_template_variable) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + return 0; + } else { + // There is an extraneous 'template<>' for this variable. Complain + // about it, but allow the declaration of the variable. + Diag(TemplateParams->getTemplateLoc(), + diag::err_template_variable_noparams) + << II + << SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc()); + } + } + + NewVD = VarDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + R, TInfo, SC, SCAsWritten); + + // If this decl has an auto type in need of deduction, make a note of the + // Decl so we can diagnose uses of it in its own initializer. + if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && + R->getContainedAutoType()) + ParsingInitForAutoVars.insert(NewVD); + + if (D.isInvalidType() || Invalid) + NewVD->setInvalidDecl(); + + SetNestedNameSpecifier(NewVD, D); + + if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { + NewVD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + } + } + + if (D.getDeclSpec().isThreadSpecified()) { + if (NewVD->hasLocalStorage()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); + else if (!Context.Target.isTLSSupported()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_unsupported); + else + NewVD->setThreadSpecified(true); + } + + // Set the lexical context. If the declarator has a C++ scope specifier, the + // lexical context will be different from the semantic context. + NewVD->setLexicalDeclContext(CurContext); + + // Handle attributes prior to checking for duplicates in MergeVarDecl + ProcessDeclAttributes(S, NewVD, D); + + // Handle GNU asm-label extension (encoded as an attribute). + if (Expr *E = (Expr*)D.getAsmLabel()) { + // The parser guarantees this is a string. + StringLiteral *SE = cast<StringLiteral>(E); + llvm::StringRef Label = SE->getString(); + if (S->getFnParent() != 0) { + switch (SC) { + case SC_None: + case SC_Auto: + Diag(E->getExprLoc(), diag::warn_asm_label_on_auto_decl) << Label; + break; + case SC_Register: + if (!Context.Target.isValidGCCRegisterName(Label)) + Diag(E->getExprLoc(), diag::err_asm_unknown_register_name) << Label; + break; + case SC_Static: + case SC_Extern: + case SC_PrivateExtern: + break; + } + } + + NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), + Context, Label)); + } + + // Diagnose shadowed variables before filtering for scope. + if (!D.getCXXScopeSpec().isSet()) + CheckShadow(S, NewVD, Previous); + + // Don't consider existing declarations that are in a different + // scope and are out-of-semantic-context declarations (if the new + // declaration has linkage). + FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(), + isExplicitSpecialization); + + if (!getLangOptions().CPlusPlus) + CheckVariableDeclaration(NewVD, Previous, Redeclaration); + else { + // Merge the decl with the existing one if appropriate. + if (!Previous.empty()) { + if (Previous.isSingleResult() && + isa<FieldDecl>(Previous.getFoundDecl()) && + D.getCXXScopeSpec().isSet()) { + // The user tried to define a non-static data member + // out-of-line (C++ [dcl.meaning]p1). + Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line) + << D.getCXXScopeSpec().getRange(); + Previous.clear(); + NewVD->setInvalidDecl(); + } + } else if (D.getCXXScopeSpec().isSet()) { + // No previous declaration in the qualifying scope. + Diag(D.getIdentifierLoc(), diag::err_no_member) + << Name << computeDeclContext(D.getCXXScopeSpec(), true) + << D.getCXXScopeSpec().getRange(); + NewVD->setInvalidDecl(); + } + + CheckVariableDeclaration(NewVD, Previous, Redeclaration); + + // This is an explicit specialization of a static data member. Check it. + if (isExplicitSpecialization && !NewVD->isInvalidDecl() && + CheckMemberSpecialization(NewVD, Previous)) + NewVD->setInvalidDecl(); + } + + // attributes declared post-definition are currently ignored + // FIXME: This should be handled in attribute merging, not + // here. + if (Previous.isSingleResult()) { + VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl()); + if (Def && (Def = Def->getDefinition()) && + Def != NewVD && D.hasAttributes()) { + Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + + // If this is a locally-scoped extern C variable, update the map of + // such variables. + if (CurContext->isFunctionOrMethod() && NewVD->isExternC() && + !NewVD->isInvalidDecl()) + RegisterLocallyScopedExternCDecl(NewVD, Previous, S); + + // If there's a #pragma GCC visibility in scope, and this isn't a class + // member, set the visibility of this variable. + if (NewVD->getLinkage() == ExternalLinkage && !DC->isRecord()) + AddPushedVisibilityAttribute(NewVD); + + MarkUnusedFileScopedDecl(NewVD); + + return NewVD; +} + +/// \brief Diagnose variable or built-in function shadowing. Implements +/// -Wshadow. +/// +/// This method is called whenever a VarDecl is added to a "useful" +/// scope. +/// +/// \param S the scope in which the shadowing name is being declared +/// \param R the lookup of the name +/// +void Sema::CheckShadow(Scope *S, VarDecl *D, const LookupResult& R) { + // Return if warning is ignored. + if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, R.getNameLoc()) == + Diagnostic::Ignored) + return; + + // Don't diagnose declarations at file scope. + if (D->hasGlobalStorage()) + return; + + DeclContext *NewDC = D->getDeclContext(); + + // Only diagnose if we're shadowing an unambiguous field or variable. + if (R.getResultKind() != LookupResult::Found) + return; + + NamedDecl* ShadowedDecl = R.getFoundDecl(); + if (!isa<VarDecl>(ShadowedDecl) && !isa<FieldDecl>(ShadowedDecl)) + return; + + // Fields are not shadowed by variables in C++ static methods. + if (isa<FieldDecl>(ShadowedDecl)) + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewDC)) + if (MD->isStatic()) + return; + + if (VarDecl *shadowedVar = dyn_cast<VarDecl>(ShadowedDecl)) + if (shadowedVar->isExternC()) { + // For shadowing external vars, make sure that we point to the global + // declaration, not a locally scoped extern declaration. + for (VarDecl::redecl_iterator + I = shadowedVar->redecls_begin(), E = shadowedVar->redecls_end(); + I != E; ++I) + if (I->isFileVarDecl()) { + ShadowedDecl = *I; + break; + } + } + + DeclContext *OldDC = ShadowedDecl->getDeclContext(); + + // Only warn about certain kinds of shadowing for class members. + if (NewDC && NewDC->isRecord()) { + // In particular, don't warn about shadowing non-class members. + if (!OldDC->isRecord()) + return; + + // TODO: should we warn about static data members shadowing + // static data members from base classes? + + // TODO: don't diagnose for inaccessible shadowed members. + // This is hard to do perfectly because we might friend the + // shadowing context, but that's just a false negative. + } + + // Determine what kind of declaration we're shadowing. + unsigned Kind; + if (isa<RecordDecl>(OldDC)) { + if (isa<FieldDecl>(ShadowedDecl)) + Kind = 3; // field + else + Kind = 2; // static data member + } else if (OldDC->isFileContext()) + Kind = 1; // global + else + Kind = 0; // local + + DeclarationName Name = R.getLookupName(); + + // Emit warning and note. + Diag(R.getNameLoc(), diag::warn_decl_shadow) << Name << Kind << OldDC; + Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); +} + +/// \brief Check -Wshadow without the advantage of a previous lookup. +void Sema::CheckShadow(Scope *S, VarDecl *D) { + if (Diags.getDiagnosticLevel(diag::warn_decl_shadow, D->getLocation()) == + Diagnostic::Ignored) + return; + + LookupResult R(*this, D->getDeclName(), D->getLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + LookupName(R, S); + CheckShadow(S, D, R); +} + +/// \brief Perform semantic checking on a newly-created variable +/// declaration. +/// +/// This routine performs all of the type-checking required for a +/// variable declaration once it has been built. It is used both to +/// check variables after they have been parsed and their declarators +/// have been translated into a declaration, and to check variables +/// that have been instantiated from a template. +/// +/// Sets NewVD->isInvalidDecl() if an error was encountered. +void Sema::CheckVariableDeclaration(VarDecl *NewVD, + LookupResult &Previous, + bool &Redeclaration) { + // If the decl is already known invalid, don't check it. + if (NewVD->isInvalidDecl()) + return; + + QualType T = NewVD->getType(); + + if (T->isObjCObjectType()) { + Diag(NewVD->getLocation(), diag::err_statically_allocated_object); + return NewVD->setInvalidDecl(); + } + + // Emit an error if an address space was applied to decl with local storage. + // This includes arrays of objects with address space qualifiers, but not + // automatic variables that point to other address spaces. + // ISO/IEC TR 18037 S5.1.2 + if (NewVD->hasLocalStorage() && T.getAddressSpace() != 0) { + Diag(NewVD->getLocation(), diag::err_as_qualified_auto_decl); + return NewVD->setInvalidDecl(); + } + + if (NewVD->hasLocalStorage() && T.isObjCGCWeak() + && !NewVD->hasAttr<BlocksAttr>()) { + if (getLangOptions().getGCMode() != LangOptions::NonGC) + Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local); + else + Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); + } + + bool isVM = T->isVariablyModifiedType(); + if (isVM || NewVD->hasAttr<CleanupAttr>() || + NewVD->hasAttr<BlocksAttr>()) + getCurFunction()->setHasBranchProtectedScope(); + + if ((isVM && NewVD->hasLinkage()) || + (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { + bool SizeIsNegative; + llvm::APSInt Oversized; + QualType FixedTy = + TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, + Oversized); + + if (FixedTy.isNull() && T->isVariableArrayType()) { + const VariableArrayType *VAT = Context.getAsVariableArrayType(T); + // FIXME: This won't give the correct result for + // int a[10][n]; + SourceRange SizeRange = VAT->getSizeExpr()->getSourceRange(); + + if (NewVD->isFileVarDecl()) + Diag(NewVD->getLocation(), diag::err_vla_decl_in_file_scope) + << SizeRange; + else if (NewVD->getStorageClass() == SC_Static) + Diag(NewVD->getLocation(), diag::err_vla_decl_has_static_storage) + << SizeRange; + else + Diag(NewVD->getLocation(), diag::err_vla_decl_has_extern_linkage) + << SizeRange; + return NewVD->setInvalidDecl(); + } + + if (FixedTy.isNull()) { + if (NewVD->isFileVarDecl()) + Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope); + else + Diag(NewVD->getLocation(), diag::err_vm_decl_has_extern_linkage); + return NewVD->setInvalidDecl(); + } + + Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); + NewVD->setType(FixedTy); + } + + if (Previous.empty() && NewVD->isExternC()) { + // Since we did not find anything by this name and we're declaring + // an extern "C" variable, look for a non-visible extern "C" + // declaration with the same name. + llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos + = LocallyScopedExternalDecls.find(NewVD->getDeclName()); + if (Pos != LocallyScopedExternalDecls.end()) + Previous.addDecl(Pos->second); + } + + if (T->isVoidType() && !NewVD->hasExternalStorage()) { + Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) + << T; + return NewVD->setInvalidDecl(); + } + + if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) { + Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); + return NewVD->setInvalidDecl(); + } + + if (isVM && NewVD->hasAttr<BlocksAttr>()) { + Diag(NewVD->getLocation(), diag::err_block_on_vm); + return NewVD->setInvalidDecl(); + } + + // Function pointers and references cannot have qualified function type, only + // function pointer-to-members can do that. + QualType Pointee; + unsigned PtrOrRef = 0; + if (const PointerType *Ptr = T->getAs<PointerType>()) + Pointee = Ptr->getPointeeType(); + else if (const ReferenceType *Ref = T->getAs<ReferenceType>()) { + Pointee = Ref->getPointeeType(); + PtrOrRef = 1; + } + if (!Pointee.isNull() && Pointee->isFunctionProtoType() && + Pointee->getAs<FunctionProtoType>()->getTypeQuals() != 0) { + Diag(NewVD->getLocation(), diag::err_invalid_qualified_function_pointer) + << PtrOrRef; + return NewVD->setInvalidDecl(); + } + + if (!Previous.empty()) { + Redeclaration = true; + MergeVarDecl(NewVD, Previous); + } +} + +/// \brief Data used with FindOverriddenMethod +struct FindOverriddenMethodData { + Sema *S; + CXXMethodDecl *Method; +}; + +/// \brief Member lookup function that determines whether a given C++ +/// method overrides a method in a base class, to be used with +/// CXXRecordDecl::lookupInBases(). +static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData) { + RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); + + FindOverriddenMethodData *Data + = reinterpret_cast<FindOverriddenMethodData*>(UserData); + + DeclarationName Name = Data->Method->getDeclName(); + + // FIXME: Do we care about other names here too? + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + // We really want to find the base class destructor here. + QualType T = Data->S->Context.getTypeDeclType(BaseRecord); + CanQualType CT = Data->S->Context.getCanonicalType(T); + + Name = Data->S->Context.DeclarationNames.getCXXDestructorName(CT); + } + + for (Path.Decls = BaseRecord->lookup(Name); + Path.Decls.first != Path.Decls.second; + ++Path.Decls.first) { + NamedDecl *D = *Path.Decls.first; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false)) + return true; + } + } + + return false; +} + +/// AddOverriddenMethods - See if a method overrides any in the base classes, +/// and if so, check that it's a valid override and remember it. +bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { + // Look for virtual methods in base classes that this method might override. + CXXBasePaths Paths; + FindOverriddenMethodData Data; + Data.Method = MD; + Data.S = this; + bool AddedAny = false; + if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) { + for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(), + E = Paths.found_decls_end(); I != E; ++I) { + if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) { + if (!CheckOverridingFunctionReturnType(MD, OldMD) && + !CheckOverridingFunctionExceptionSpec(MD, OldMD) && + !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { + MD->addOverriddenMethod(OldMD->getCanonicalDecl()); + AddedAny = true; + } + } + } + } + + return AddedAny; +} + +static void DiagnoseInvalidRedeclaration(Sema &S, FunctionDecl *NewFD) { + LookupResult Prev(S, NewFD->getDeclName(), NewFD->getLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + S.LookupQualifiedName(Prev, NewFD->getDeclContext()); + assert(!Prev.isAmbiguous() && + "Cannot have an ambiguity in previous-declaration lookup"); + for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end(); + Func != FuncEnd; ++Func) { + if (isa<FunctionDecl>(*Func) && + isNearlyMatchingFunction(S.Context, cast<FunctionDecl>(*Func), NewFD)) + S.Diag((*Func)->getLocation(), diag::note_member_def_close_match); + } +} + +NamedDecl* +Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, + QualType R, TypeSourceInfo *TInfo, + LookupResult &Previous, + MultiTemplateParamsArg TemplateParamLists, + bool IsFunctionDefinition, bool &Redeclaration) { + assert(R.getTypePtr()->isFunctionType()); + + // TODO: consider using NameInfo for diagnostic. + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + FunctionDecl::StorageClass SC = SC_None; + switch (D.getDeclSpec().getStorageClassSpec()) { + default: assert(0 && "Unknown storage class!"); + case DeclSpec::SCS_auto: + case DeclSpec::SCS_register: + case DeclSpec::SCS_mutable: + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_typecheck_sclass_func); + D.setInvalidType(); + break; + case DeclSpec::SCS_unspecified: SC = SC_None; break; + case DeclSpec::SCS_extern: SC = SC_Extern; break; + case DeclSpec::SCS_static: { + if (CurContext->getRedeclContext()->isFunctionOrMethod()) { + // C99 6.7.1p5: + // The declaration of an identifier for a function that has + // block scope shall have no explicit storage-class specifier + // other than extern + // See also (C++ [dcl.stc]p4). + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_static_block_func); + SC = SC_None; + } else + SC = SC_Static; + break; + } + case DeclSpec::SCS_private_extern: SC = SC_PrivateExtern; break; + } + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + + // Do not allow returning a objc interface by-value. + if (R->getAs<FunctionType>()->getResultType()->isObjCObjectType()) { + Diag(D.getIdentifierLoc(), + diag::err_object_cannot_be_passed_returned_by_value) << 0 + << R->getAs<FunctionType>()->getResultType(); + D.setInvalidType(); + } + + FunctionDecl *NewFD; + bool isInline = D.getDeclSpec().isInlineSpecified(); + bool isFriend = false; + DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); + FunctionDecl::StorageClass SCAsWritten + = StorageClassSpecToFunctionDeclStorageClass(SCSpec); + FunctionTemplateDecl *FunctionTemplate = 0; + bool isExplicitSpecialization = false; + bool isFunctionTemplateSpecialization = false; + + if (!getLangOptions().CPlusPlus) { + // Determine whether the function was written with a + // prototype. This true when: + // - there is a prototype in the declarator, or + // - the type R of the function is some kind of typedef or other reference + // to a type name (which eventually refers to a function type). + bool HasPrototype = + (D.isFunctionDeclarator() && D.getFunctionTypeInfo().hasPrototype) || + (!isa<FunctionType>(R.getTypePtr()) && R->isFunctionProtoType()); + + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), + NameInfo, R, TInfo, SC, SCAsWritten, isInline, + HasPrototype); + if (D.isInvalidType()) + NewFD->setInvalidDecl(); + + // Set the lexical context. + NewFD->setLexicalDeclContext(CurContext); + // Filter out previous declarations that don't match the scope. + FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(), + /*ExplicitInstantiationOrSpecialization=*/false); + } else { + isFriend = D.getDeclSpec().isFriendSpecified(); + bool isVirtual = D.getDeclSpec().isVirtualSpecified(); + bool isExplicit = D.getDeclSpec().isExplicitSpecified(); + bool isVirtualOkay = false; + + // Check that the return type is not an abstract class type. + // For record types, this is done by the AbstractClassUsageDiagnoser once + // the class has been completely parsed. + if (!DC->isRecord() && + RequireNonAbstractType(D.getIdentifierLoc(), + R->getAs<FunctionType>()->getResultType(), + diag::err_abstract_type_in_decl, + AbstractReturnType)) + D.setInvalidType(); + + if (Name.getNameKind() == DeclarationName::CXXConstructorName) { + // This is a C++ constructor declaration. + assert(DC->isRecord() && + "Constructors can only be declared in a member context"); + + R = CheckConstructorDeclarator(D, R, SC); + + // Create the new declaration + CXXConstructorDecl *NewCD = CXXConstructorDecl::Create( + Context, + cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), + NameInfo, R, TInfo, + isExplicit, isInline, + /*isImplicitlyDeclared=*/false); + + NewFD = NewCD; + } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + // This is a C++ destructor declaration. + if (DC->isRecord()) { + R = CheckDestructorDeclarator(D, R, SC); + CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); + + CXXDestructorDecl *NewDD = CXXDestructorDecl::Create(Context, Record, + D.getSourceRange().getBegin(), + NameInfo, R, TInfo, + isInline, + /*isImplicitlyDeclared=*/false); + NewFD = NewDD; + isVirtualOkay = true; + + // If the class is complete, then we now create the implicit exception + // specification. If the class is incomplete or dependent, we can't do + // it yet. + if (getLangOptions().CPlusPlus0x && !Record->isDependentType() && + Record->getDefinition() && !Record->isBeingDefined() && + R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) { + AdjustDestructorExceptionSpec(Record, NewDD); + } + + } else { + Diag(D.getIdentifierLoc(), diag::err_destructor_not_member); + + // Create a FunctionDecl to satisfy the function definition parsing + // code path. + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), + D.getIdentifierLoc(), Name, R, TInfo, + SC, SCAsWritten, isInline, + /*hasPrototype=*/true); + D.setInvalidType(); + } + } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + if (!DC->isRecord()) { + Diag(D.getIdentifierLoc(), + diag::err_conv_function_not_member); + return 0; + } + + CheckConversionDeclarator(D, R, SC); + NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), + NameInfo, R, TInfo, + isInline, isExplicit, + SourceLocation()); + + isVirtualOkay = true; + } else if (DC->isRecord()) { + // If the of the function is the same as the name of the record, then this + // must be an invalid constructor that has a return type. + // (The parser checks for a return type and makes the declarator a + // constructor if it has no return type). + // must have an invalid constructor that has a return type + if (Name.getAsIdentifierInfo() && + Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){ + Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + return 0; + } + + bool isStatic = SC == SC_Static; + + // [class.free]p1: + // Any allocation function for a class T is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New) + isStatic = true; + + // [class.free]p6 Any deallocation function for a class X is a static member + // (even if not explicitly declared static). + if (Name.getCXXOverloadedOperator() == OO_Delete || + Name.getCXXOverloadedOperator() == OO_Array_Delete) + isStatic = true; + + // This is a C++ method declaration. + CXXMethodDecl *NewMD = CXXMethodDecl::Create( + Context, cast<CXXRecordDecl>(DC), + D.getSourceRange().getBegin(), + NameInfo, R, TInfo, + isStatic, SCAsWritten, isInline, + SourceLocation()); + NewFD = NewMD; + + isVirtualOkay = !isStatic; + } else { + // Determine whether the function was written with a + // prototype. This true when: + // - we're in C++ (where every function has a prototype), + NewFD = FunctionDecl::Create(Context, DC, D.getSourceRange().getBegin(), + NameInfo, R, TInfo, SC, SCAsWritten, isInline, + true/*HasPrototype*/); + } + + if (isFriend && !isInline && IsFunctionDefinition) { + // C++ [class.friend]p5 + // A function can be defined in a friend declaration of a + // class . . . . Such a function is implicitly inline. + NewFD->setImplicitlyInline(); + } + + SetNestedNameSpecifier(NewFD, D); + isExplicitSpecialization = false; + isFunctionTemplateSpecialization = false; + if (D.isInvalidType()) + NewFD->setInvalidDecl(); + + // Set the lexical context. If the declarator has a C++ + // scope specifier, or is the object of a friend declaration, the + // lexical context will be different from the semantic context. + NewFD->setLexicalDeclContext(CurContext); + + // Match up the template parameter lists with the scope specifier, then + // determine whether we have a template or a template specialization. + bool Invalid = false; + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier( + D.getDeclSpec().getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getCXXScopeSpec(), + TemplateParamLists.get(), + TemplateParamLists.size(), + isFriend, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // This is a function template + + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return 0; + + // A destructor cannot be a template. + if (Name.getNameKind() == DeclarationName::CXXDestructorName) { + Diag(NewFD->getLocation(), diag::err_destructor_template); + return 0; + } + + FunctionTemplate = FunctionTemplateDecl::Create(Context, DC, + NewFD->getLocation(), + Name, TemplateParams, + NewFD); + FunctionTemplate->setLexicalDeclContext(CurContext); + NewFD->setDescribedFunctionTemplate(FunctionTemplate); + + // For source fidelity, store the other template param lists. + if (TemplateParamLists.size() > 1) { + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size() - 1, + TemplateParamLists.release()); + } + } else { + // This is a function template specialization. + isFunctionTemplateSpecialization = true; + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + + // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". + if (isFriend) { + // We want to remove the "template<>", found here. + SourceRange RemoveRange = TemplateParams->getSourceRange(); + + // If we remove the template<> and the name is not a + // template-id, we're actually silently creating a problem: + // the friend declaration will refer to an untemplated decl, + // and clearly the user wants a template specialization. So + // we need to insert '<>' after the name. + SourceLocation InsertLoc; + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + InsertLoc = D.getName().getSourceRange().getEnd(); + InsertLoc = PP.getLocForEndOfToken(InsertLoc); + } + + Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend) + << Name << RemoveRange + << FixItHint::CreateRemoval(RemoveRange) + << FixItHint::CreateInsertion(InsertLoc, "<>"); + } + } + } + else { + // All template param lists were matched against the scope specifier: + // this is NOT (an explicit specialization of) a template. + if (TemplateParamLists.size() > 0) + // For source fidelity, store all the template param lists. + NewFD->setTemplateParameterListsInfo(Context, + TemplateParamLists.size(), + TemplateParamLists.release()); + } + + if (Invalid) { + NewFD->setInvalidDecl(); + if (FunctionTemplate) + FunctionTemplate->setInvalidDecl(); + } + + // C++ [dcl.fct.spec]p5: + // The virtual specifier shall only be used in declarations of + // nonstatic class member functions that appear within a + // member-specification of a class declaration; see 10.3. + // + if (isVirtual && !NewFD->isInvalidDecl()) { + if (!isVirtualOkay) { + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_non_function); + } else if (!CurContext->isRecord()) { + // 'virtual' was specified outside of the class. + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_out_of_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); + } else if (NewFD->getDescribedFunctionTemplate()) { + // C++ [temp.mem]p3: + // A member function template shall not be virtual. + Diag(D.getDeclSpec().getVirtualSpecLoc(), + diag::err_virtual_member_function_template) + << FixItHint::CreateRemoval(D.getDeclSpec().getVirtualSpecLoc()); + } else { + // Okay: Add virtual to the method. + NewFD->setVirtualAsWritten(true); + } + } + + // C++ [dcl.fct.spec]p3: + // The inline specifier shall not appear on a block scope function declaration. + if (isInline && !NewFD->isInvalidDecl()) { + if (CurContext->isFunctionOrMethod()) { + // 'inline' is not allowed on block scope function declaration. + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_inline_declaration_block_scope) << Name + << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); + } + } + + // C++ [dcl.fct.spec]p6: + // The explicit specifier shall be used only in the declaration of a + // constructor or conversion function within its class definition; see 12.3.1 + // and 12.3.2. + if (isExplicit && !NewFD->isInvalidDecl()) { + if (!CurContext->isRecord()) { + // 'explicit' was specified outside of the class. + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_out_of_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); + } else if (!isa<CXXConstructorDecl>(NewFD) && + !isa<CXXConversionDecl>(NewFD)) { + // 'explicit' was specified on a function that wasn't a constructor + // or conversion function. + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_non_ctor_or_conv_function) + << FixItHint::CreateRemoval(D.getDeclSpec().getExplicitSpecLoc()); + } + } + + // Filter out previous declarations that don't match the scope. + FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(), + isExplicitSpecialization || + isFunctionTemplateSpecialization); + + if (isFriend) { + // For now, claim that the objects have no previous declaration. + if (FunctionTemplate) { + FunctionTemplate->setObjectOfFriendDecl(false); + FunctionTemplate->setAccess(AS_public); + } + NewFD->setObjectOfFriendDecl(false); + NewFD->setAccess(AS_public); + } + + if (isa<CXXMethodDecl>(NewFD) && DC == CurContext && IsFunctionDefinition) { + // A method is implicitly inline if it's defined in its class + // definition. + NewFD->setImplicitlyInline(); + } + + if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) && + !CurContext->isRecord()) { + // C++ [class.static]p1: + // A data or function member of a class may be declared static + // in a class definition, in which case it is a static member of + // the class. + + // Complain about the 'static' specifier if it's on an out-of-line + // member function definition. + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::err_static_out_of_line) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + } + } + + // Handle GNU asm-label extension (encoded as an attribute). + if (Expr *E = (Expr*) D.getAsmLabel()) { + // The parser guarantees this is a string. + StringLiteral *SE = cast<StringLiteral>(E); + NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getStrTokenLoc(0), Context, + SE->getString())); + } + + // Copy the parameter declarations from the declarator D to the function + // declaration NewFD, if they are available. First scavenge them into Params. + llvm::SmallVector<ParmVarDecl*, 16> Params; + if (D.isFunctionDeclarator()) { + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + + // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs + // function that takes no arguments, not a function that takes a + // single void argument. + // We let through "const void" here because Sema::GetTypeForDeclarator + // already checks for that case. + if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && + FTI.ArgInfo[0].Param && + cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { + // Empty arg list, don't push any params. + ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[0].Param); + + // In C++, the empty parameter-type-list must be spelled "void"; a + // typedef of void is not permitted. + if (getLangOptions().CPlusPlus && + Param->getType().getUnqualifiedType() != Context.VoidTy) { + bool IsTypeAlias = false; + if (const TypedefType *TT = Param->getType()->getAs<TypedefType>()) + IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl()); + else if (const TemplateSpecializationType *TST = + Param->getType()->getAs<TemplateSpecializationType>()) + IsTypeAlias = TST->isTypeAlias(); + Diag(Param->getLocation(), diag::err_param_typedef_of_void) + << IsTypeAlias; + } + } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { + for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { + ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param); + assert(Param->getDeclContext() != NewFD && "Was set before ?"); + Param->setDeclContext(NewFD); + Params.push_back(Param); + + if (Param->isInvalidDecl()) + NewFD->setInvalidDecl(); + } + } + + } else if (const FunctionProtoType *FT = R->getAs<FunctionProtoType>()) { + // When we're declaring a function with a typedef, typeof, etc as in the + // following example, we'll need to synthesize (unnamed) + // parameters for use in the declaration. + // + // @code + // typedef void fn(int); + // fn f; + // @endcode + + // Synthesize a parameter for each argument type. + for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), + AE = FT->arg_type_end(); AI != AE; ++AI) { + ParmVarDecl *Param = + BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI); + Param->setScopeInfo(0, Params.size()); + Params.push_back(Param); + } + } else { + assert(R->isFunctionNoProtoType() && NewFD->getNumParams() == 0 && + "Should not need args for typedef of non-prototype fn"); + } + // Finally, we know we have the right number of parameters, install them. + NewFD->setParams(Params.data(), Params.size()); + + // Process the non-inheritable attributes on this declaration. + ProcessDeclAttributes(S, NewFD, D, + /*NonInheritable=*/true, /*Inheritable=*/false); + + if (!getLangOptions().CPlusPlus) { + // Perform semantic checking on the function declaration. + bool isExplicitSpecialization=false; + CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, + Redeclaration); + assert((NewFD->isInvalidDecl() || !Redeclaration || + Previous.getResultKind() != LookupResult::FoundOverloaded) && + "previous declaration set still overloaded"); + } else { + // If the declarator is a template-id, translate the parser's template + // argument list into our AST format. + bool HasExplicitTemplateArgs = false; + TemplateArgumentListInfo TemplateArgs; + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, + TemplateArgs); + TemplateArgsPtr.release(); + + HasExplicitTemplateArgs = true; + + if (NewFD->isInvalidDecl()) { + HasExplicitTemplateArgs = false; + } else if (FunctionTemplate) { + // Function template with explicit template arguments. + Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec) + << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc); + + HasExplicitTemplateArgs = false; + } else if (!isFunctionTemplateSpecialization && + !D.getDeclSpec().isFriendSpecified()) { + // We have encountered something that the user meant to be a + // specialization (because it has explicitly-specified template + // arguments) but that was not introduced with a "template<>" (or had + // too few of them). + Diag(D.getIdentifierLoc(), diag::err_template_spec_needs_header) + << SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc) + << FixItHint::CreateInsertion( + D.getDeclSpec().getSourceRange().getBegin(), + "template<> "); + isFunctionTemplateSpecialization = true; + } else { + // "friend void foo<>(int);" is an implicit specialization decl. + isFunctionTemplateSpecialization = true; + } + } else if (isFriend && isFunctionTemplateSpecialization) { + // This combination is only possible in a recovery case; the user + // wrote something like: + // template <> friend void foo(int); + // which we're recovering from as if the user had written: + // friend void foo<>(int); + // Go ahead and fake up a template id. + HasExplicitTemplateArgs = true; + TemplateArgs.setLAngleLoc(D.getIdentifierLoc()); + TemplateArgs.setRAngleLoc(D.getIdentifierLoc()); + } + + // If it's a friend (and only if it's a friend), it's possible + // that either the specialized function type or the specialized + // template is dependent, and therefore matching will fail. In + // this case, don't check the specialization yet. + if (isFunctionTemplateSpecialization && isFriend && + (NewFD->getType()->isDependentType() || DC->isDependentContext())) { + assert(HasExplicitTemplateArgs && + "friend function specialization without template args"); + if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs, + Previous)) + NewFD->setInvalidDecl(); + } else if (isFunctionTemplateSpecialization) { + if (CurContext->isDependentContext() && CurContext->isRecord() + && !isFriend) { + Diag(NewFD->getLocation(), diag::err_function_specialization_in_class) + << NewFD->getDeclName(); + NewFD->setInvalidDecl(); + return 0; + } else if (CheckFunctionTemplateSpecialization(NewFD, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), + Previous)) + NewFD->setInvalidDecl(); + + // C++ [dcl.stc]p1: + // A storage-class-specifier shall not be specified in an explicit + // specialization (14.7.3) + if (SC != SC_None) { + Diag(NewFD->getLocation(), + diag::err_explicit_specialization_storage_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + } + + } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD)) { + if (CheckMemberSpecialization(NewFD, Previous)) + NewFD->setInvalidDecl(); + } + + // Perform semantic checking on the function declaration. + CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, + Redeclaration); + + assert((NewFD->isInvalidDecl() || !Redeclaration || + Previous.getResultKind() != LookupResult::FoundOverloaded) && + "previous declaration set still overloaded"); + + NamedDecl *PrincipalDecl = (FunctionTemplate + ? cast<NamedDecl>(FunctionTemplate) + : NewFD); + + if (isFriend && Redeclaration) { + AccessSpecifier Access = AS_public; + if (!NewFD->isInvalidDecl()) + Access = NewFD->getPreviousDeclaration()->getAccess(); + + NewFD->setAccess(Access); + if (FunctionTemplate) FunctionTemplate->setAccess(Access); + + PrincipalDecl->setObjectOfFriendDecl(true); + } + + if (NewFD->isOverloadedOperator() && !DC->isRecord() && + PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + PrincipalDecl->setNonMemberOperator(); + + // If we have a function template, check the template parameter + // list. This will check and merge default template arguments. + if (FunctionTemplate) { + FunctionTemplateDecl *PrevTemplate = FunctionTemplate->getPreviousDeclaration(); + CheckTemplateParameterList(FunctionTemplate->getTemplateParameters(), + PrevTemplate? PrevTemplate->getTemplateParameters() : 0, + D.getDeclSpec().isFriendSpecified() + ? (IsFunctionDefinition + ? TPC_FriendFunctionTemplateDefinition + : TPC_FriendFunctionTemplate) + : (D.getCXXScopeSpec().isSet() && + DC && DC->isRecord() && + DC->isDependentContext()) + ? TPC_ClassTemplateMember + : TPC_FunctionTemplate); + } + + if (NewFD->isInvalidDecl()) { + // Ignore all the rest of this. + } else if (!Redeclaration) { + // Fake up an access specifier if it's supposed to be a class member. + if (isa<CXXRecordDecl>(NewFD->getDeclContext())) + NewFD->setAccess(AS_public); + + // Qualified decls generally require a previous declaration. + if (D.getCXXScopeSpec().isSet()) { + // ...with the major exception of templated-scope or + // dependent-scope friend declarations. + + // TODO: we currently also suppress this check in dependent + // contexts because (1) the parameter depth will be off when + // matching friend templates and (2) we might actually be + // selecting a friend based on a dependent factor. But there + // are situations where these conditions don't apply and we + // can actually do this check immediately. + if (isFriend && + (TemplateParamLists.size() || + D.getCXXScopeSpec().getScopeRep()->isDependent() || + CurContext->isDependentContext())) { + // ignore these + } else { + // The user tried to provide an out-of-line definition for a + // function that is a member of a class or namespace, but there + // was no such member function declared (C++ [class.mfct]p2, + // C++ [namespace.memdef]p2). For example: + // + // class X { + // void f() const; + // }; + // + // void X::f() { } // ill-formed + // + // Complain about this problem, and attempt to suggest close + // matches (e.g., those that differ only in cv-qualifiers and + // whether the parameter types are references). + Diag(D.getIdentifierLoc(), diag::err_member_def_does_not_match) + << Name << DC << D.getCXXScopeSpec().getRange(); + NewFD->setInvalidDecl(); + + DiagnoseInvalidRedeclaration(*this, NewFD); + } + + // Unqualified local friend declarations are required to resolve + // to something. + } else if (isFriend && cast<CXXRecordDecl>(CurContext)->isLocalClass()) { + Diag(D.getIdentifierLoc(), diag::err_no_matching_local_friend); + NewFD->setInvalidDecl(); + DiagnoseInvalidRedeclaration(*this, NewFD); + } + + } else if (!IsFunctionDefinition && D.getCXXScopeSpec().isSet() && + !isFriend && !isFunctionTemplateSpecialization && + !isExplicitSpecialization) { + // An out-of-line member function declaration must also be a + // definition (C++ [dcl.meaning]p1). + // Note that this is not the case for explicit specializations of + // function templates or member functions of class templates, per + // C++ [temp.expl.spec]p2. We also allow these declarations as an extension + // for compatibility with old SWIG code which likes to generate them. + Diag(NewFD->getLocation(), diag::ext_out_of_line_declaration) + << D.getCXXScopeSpec().getRange(); + } + } + + + // Handle attributes. We need to have merged decls when handling attributes + // (for example to check for conflicts, etc). + // FIXME: This needs to happen before we merge declarations. Then, + // let attribute merging cope with attribute conflicts. + ProcessDeclAttributes(S, NewFD, D, + /*NonInheritable=*/false, /*Inheritable=*/true); + + // attributes declared post-definition are currently ignored + // FIXME: This should happen during attribute merging + if (Redeclaration && Previous.isSingleResult()) { + const FunctionDecl *Def; + FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl()); + if (PrevFD && PrevFD->isDefined(Def) && D.hasAttributes()) { + Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition); + Diag(Def->getLocation(), diag::note_previous_definition); + } + } + + AddKnownFunctionAttributes(NewFD); + + if (NewFD->hasAttr<OverloadableAttr>() && + !NewFD->getType()->getAs<FunctionProtoType>()) { + Diag(NewFD->getLocation(), + diag::err_attribute_overloadable_no_prototype) + << NewFD; + + // Turn this into a variadic function with no parameters. + const FunctionType *FT = NewFD->getType()->getAs<FunctionType>(); + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = true; + EPI.ExtInfo = FT->getExtInfo(); + + QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI); + NewFD->setType(R); + } + + // If there's a #pragma GCC visibility in scope, and this isn't a class + // member, set the visibility of this function. + if (NewFD->getLinkage() == ExternalLinkage && !DC->isRecord()) + AddPushedVisibilityAttribute(NewFD); + + // If this is a locally-scoped extern C function, update the + // map of such names. + if (CurContext->isFunctionOrMethod() && NewFD->isExternC() + && !NewFD->isInvalidDecl()) + RegisterLocallyScopedExternCDecl(NewFD, Previous, S); + + // Set this FunctionDecl's range up to the right paren. + NewFD->setRangeEnd(D.getSourceRange().getEnd()); + + if (getLangOptions().CPlusPlus) { + if (FunctionTemplate) { + if (NewFD->isInvalidDecl()) + FunctionTemplate->setInvalidDecl(); + return FunctionTemplate; + } + } + + MarkUnusedFileScopedDecl(NewFD); + + if (getLangOptions().CUDA) + if (IdentifierInfo *II = NewFD->getIdentifier()) + if (!NewFD->isInvalidDecl() && + NewFD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { + if (II->isStr("cudaConfigureCall")) { + if (!R->getAs<FunctionType>()->getResultType()->isScalarType()) + Diag(NewFD->getLocation(), diag::err_config_scalar_return); + + Context.setcudaConfigureCallDecl(NewFD); + } + } + + return NewFD; +} + +/// \brief Perform semantic checking of a new function declaration. +/// +/// Performs semantic analysis of the new function declaration +/// NewFD. This routine performs all semantic checking that does not +/// require the actual declarator involved in the declaration, and is +/// used both for the declaration of functions as they are parsed +/// (called via ActOnDeclarator) and for the declaration of functions +/// that have been instantiated via C++ template instantiation (called +/// via InstantiateDecl). +/// +/// \param IsExplicitSpecialiation whether this new function declaration is +/// an explicit specialization of the previous declaration. +/// +/// This sets NewFD->isInvalidDecl() to true if there was an error. +void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, + LookupResult &Previous, + bool IsExplicitSpecialization, + bool &Redeclaration) { + // If NewFD is already known erroneous, don't do any of this checking. + if (NewFD->isInvalidDecl()) { + // If this is a class member, mark the class invalid immediately. + // This avoids some consistency errors later. + if (isa<CXXMethodDecl>(NewFD)) + cast<CXXMethodDecl>(NewFD)->getParent()->setInvalidDecl(); + + return; + } + + if (NewFD->getResultType()->isVariablyModifiedType()) { + // Functions returning a variably modified type violate C99 6.7.5.2p2 + // because all functions have linkage. + Diag(NewFD->getLocation(), diag::err_vm_func_decl); + return NewFD->setInvalidDecl(); + } + + if (NewFD->isMain()) + CheckMain(NewFD); + + // Check for a previous declaration of this name. + if (Previous.empty() && NewFD->isExternC()) { + // Since we did not find anything by this name and we're declaring + // an extern "C" function, look for a non-visible extern "C" + // declaration with the same name. + llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos + = LocallyScopedExternalDecls.find(NewFD->getDeclName()); + if (Pos != LocallyScopedExternalDecls.end()) + Previous.addDecl(Pos->second); + } + + // Merge or overload the declaration with an existing declaration of + // the same name, if appropriate. + if (!Previous.empty()) { + // Determine whether NewFD is an overload of PrevDecl or + // a declaration that requires merging. If it's an overload, + // there's no more work to do here; we'll just add the new + // function to the scope. + + NamedDecl *OldDecl = 0; + if (!AllowOverloadingOfFunction(Previous, Context)) { + Redeclaration = true; + OldDecl = Previous.getFoundDecl(); + } else { + switch (CheckOverload(S, NewFD, Previous, OldDecl, + /*NewIsUsingDecl*/ false)) { + case Ovl_Match: + Redeclaration = true; + break; + + case Ovl_NonFunction: + Redeclaration = true; + break; + + case Ovl_Overload: + Redeclaration = false; + break; + } + + if (!getLangOptions().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) { + // If a function name is overloadable in C, then every function + // with that name must be marked "overloadable". + Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) + << Redeclaration << NewFD; + NamedDecl *OverloadedDecl = 0; + if (Redeclaration) + OverloadedDecl = OldDecl; + else if (!Previous.empty()) + OverloadedDecl = Previous.getRepresentativeDecl(); + if (OverloadedDecl) + Diag(OverloadedDecl->getLocation(), + diag::note_attribute_overloadable_prev_overload); + NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(), + Context)); + } + } + + if (Redeclaration) { + // NewFD and OldDecl represent declarations that need to be + // merged. + if (MergeFunctionDecl(NewFD, OldDecl)) + return NewFD->setInvalidDecl(); + + Previous.clear(); + Previous.addDecl(OldDecl); + + if (FunctionTemplateDecl *OldTemplateDecl + = dyn_cast<FunctionTemplateDecl>(OldDecl)) { + NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); + FunctionTemplateDecl *NewTemplateDecl + = NewFD->getDescribedFunctionTemplate(); + assert(NewTemplateDecl && "Template/non-template mismatch"); + if (CXXMethodDecl *Method + = dyn_cast<CXXMethodDecl>(NewTemplateDecl->getTemplatedDecl())) { + Method->setAccess(OldTemplateDecl->getAccess()); + NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); + } + + // If this is an explicit specialization of a member that is a function + // template, mark it as a member specialization. + if (IsExplicitSpecialization && + NewTemplateDecl->getInstantiatedFromMemberTemplate()) { + NewTemplateDecl->setMemberSpecialization(); + assert(OldTemplateDecl->isMemberSpecialization()); + } + } else { + if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions + NewFD->setAccess(OldDecl->getAccess()); + NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); + } + } + } + + // Semantic checking for this function declaration (in isolation). + if (getLangOptions().CPlusPlus) { + // C++-specific checks. + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(NewFD)) { + CheckConstructor(Constructor); + } else if (CXXDestructorDecl *Destructor = + dyn_cast<CXXDestructorDecl>(NewFD)) { + CXXRecordDecl *Record = Destructor->getParent(); + QualType ClassType = Context.getTypeDeclType(Record); + + // FIXME: Shouldn't we be able to perform this check even when the class + // type is dependent? Both gcc and edg can handle that. + if (!ClassType->isDependentType()) { + DeclarationName Name + = Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(ClassType)); + if (NewFD->getDeclName() != Name) { + Diag(NewFD->getLocation(), diag::err_destructor_name); + return NewFD->setInvalidDecl(); + } + } + } else if (CXXConversionDecl *Conversion + = dyn_cast<CXXConversionDecl>(NewFD)) { + ActOnConversionDeclarator(Conversion); + } + + // Find any virtual functions that this function overrides. + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) { + if (!Method->isFunctionTemplateSpecialization() && + !Method->getDescribedFunctionTemplate()) { + if (AddOverriddenMethods(Method->getParent(), Method)) { + // If the function was marked as "static", we have a problem. + if (NewFD->getStorageClass() == SC_Static) { + Diag(NewFD->getLocation(), diag::err_static_overrides_virtual) + << NewFD->getDeclName(); + for (CXXMethodDecl::method_iterator + Overridden = Method->begin_overridden_methods(), + OverriddenEnd = Method->end_overridden_methods(); + Overridden != OverriddenEnd; + ++Overridden) { + Diag((*Overridden)->getLocation(), + diag::note_overridden_virtual_function); + } + } + } + } + } + + // Extra checking for C++ overloaded operators (C++ [over.oper]). + if (NewFD->isOverloadedOperator() && + CheckOverloadedOperatorDeclaration(NewFD)) + return NewFD->setInvalidDecl(); + + // Extra checking for C++0x literal operators (C++0x [over.literal]). + if (NewFD->getLiteralIdentifier() && + CheckLiteralOperatorDeclaration(NewFD)) + return NewFD->setInvalidDecl(); + + // In C++, check default arguments now that we have merged decls. Unless + // the lexical context is the class, because in this case this is done + // during delayed parsing anyway. + if (!CurContext->isRecord()) + CheckCXXDefaultArguments(NewFD); + + // If this function declares a builtin function, check the type of this + // declaration against the expected type for the builtin. + if (unsigned BuiltinID = NewFD->getBuiltinID()) { + ASTContext::GetBuiltinTypeError Error; + QualType T = Context.GetBuiltinType(BuiltinID, Error); + if (!T.isNull() && !Context.hasSameType(T, NewFD->getType())) { + // The type of this function differs from the type of the builtin, + // so forget about the builtin entirely. + Context.BuiltinInfo.ForgetBuiltin(BuiltinID, Context.Idents); + } + } + } +} + +void Sema::CheckMain(FunctionDecl* FD) { + // C++ [basic.start.main]p3: A program that declares main to be inline + // or static is ill-formed. + // C99 6.7.4p4: In a hosted environment, the inline function specifier + // shall not appear in a declaration of main. + // static main is not an error under C99, but we should warn about it. + bool isInline = FD->isInlineSpecified(); + bool isStatic = FD->getStorageClass() == SC_Static; + if (isInline || isStatic) { + unsigned diagID = diag::warn_unusual_main_decl; + if (isInline || getLangOptions().CPlusPlus) + diagID = diag::err_unusual_main_decl; + + int which = isStatic + (isInline << 1) - 1; + Diag(FD->getLocation(), diagID) << which; + } + + QualType T = FD->getType(); + assert(T->isFunctionType() && "function decl is not of function type"); + const FunctionType* FT = T->getAs<FunctionType>(); + + if (!Context.hasSameUnqualifiedType(FT->getResultType(), Context.IntTy)) { + Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint); + FD->setInvalidDecl(true); + } + + // Treat protoless main() as nullary. + if (isa<FunctionNoProtoType>(FT)) return; + + const FunctionProtoType* FTP = cast<const FunctionProtoType>(FT); + unsigned nparams = FTP->getNumArgs(); + assert(FD->getNumParams() == nparams); + + bool HasExtraParameters = (nparams > 3); + + // Darwin passes an undocumented fourth argument of type char**. If + // other platforms start sprouting these, the logic below will start + // getting shifty. + if (nparams == 4 && Context.Target.getTriple().isOSDarwin()) + HasExtraParameters = false; + + if (HasExtraParameters) { + Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams; + FD->setInvalidDecl(true); + nparams = 3; + } + + // FIXME: a lot of the following diagnostics would be improved + // if we had some location information about types. + + QualType CharPP = + Context.getPointerType(Context.getPointerType(Context.CharTy)); + QualType Expected[] = { Context.IntTy, CharPP, CharPP, CharPP }; + + for (unsigned i = 0; i < nparams; ++i) { + QualType AT = FTP->getArgType(i); + + bool mismatch = true; + + if (Context.hasSameUnqualifiedType(AT, Expected[i])) + mismatch = false; + else if (Expected[i] == CharPP) { + // As an extension, the following forms are okay: + // char const ** + // char const * const * + // char * const * + + QualifierCollector qs; + const PointerType* PT; + if ((PT = qs.strip(AT)->getAs<PointerType>()) && + (PT = qs.strip(PT->getPointeeType())->getAs<PointerType>()) && + (QualType(qs.strip(PT->getPointeeType()), 0) == Context.CharTy)) { + qs.removeConst(); + mismatch = !qs.empty(); + } + } + + if (mismatch) { + Diag(FD->getLocation(), diag::err_main_arg_wrong) << i << Expected[i]; + // TODO: suggest replacing given type with expected type + FD->setInvalidDecl(true); + } + } + + if (nparams == 1 && !FD->isInvalidDecl()) { + Diag(FD->getLocation(), diag::warn_main_one_arg); + } + + if (!FD->isInvalidDecl() && FD->getDescribedFunctionTemplate()) { + Diag(FD->getLocation(), diag::err_main_template_decl); + FD->setInvalidDecl(); + } +} + +bool Sema::CheckForConstantInitializer(Expr *Init, QualType DclT) { + // FIXME: Need strict checking. In C89, we need to check for + // any assignment, increment, decrement, function-calls, or + // commas outside of a sizeof. In C99, it's the same list, + // except that the aforementioned are allowed in unevaluated + // expressions. Everything else falls under the + // "may accept other forms of constant expressions" exception. + // (We never end up here for C++, so the constant expression + // rules there don't matter.) + if (Init->isConstantInitializer(Context, false)) + return false; + Diag(Init->getExprLoc(), diag::err_init_element_not_constant) + << Init->getSourceRange(); + return true; +} + +namespace { + // Visits an initialization expression to see if OrigDecl is evaluated in + // its own initialization and throws a warning if it does. + class SelfReferenceChecker + : public EvaluatedExprVisitor<SelfReferenceChecker> { + Sema &S; + Decl *OrigDecl; + + public: + typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited; + + SelfReferenceChecker(Sema &S, Decl *OrigDecl) : Inherited(S.Context), + S(S), OrigDecl(OrigDecl) { } + + void VisitExpr(Expr *E) { + if (isa<ObjCMessageExpr>(*E)) return; + Inherited::VisitExpr(E); + } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + CheckForSelfReference(E); + Inherited::VisitImplicitCastExpr(E); + } + + void CheckForSelfReference(ImplicitCastExpr *E) { + if (E->getCastKind() != CK_LValueToRValue) return; + Expr* SubExpr = E->getSubExpr()->IgnoreParenImpCasts(); + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr); + if (!DRE) return; + Decl* ReferenceDecl = DRE->getDecl(); + if (OrigDecl != ReferenceDecl) return; + LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName, + Sema::NotForRedeclaration); + S.DiagRuntimeBehavior(SubExpr->getLocStart(), SubExpr, + S.PDiag(diag::warn_uninit_self_reference_in_init) + << Result.getLookupName() + << OrigDecl->getLocation() + << SubExpr->getSourceRange()); + } + }; +} + +/// AddInitializerToDecl - Adds the initializer Init to the +/// declaration dcl. If DirectInit is true, this is C++ direct +/// initialization rather than copy initialization. +void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, + bool DirectInit, bool TypeMayContainAuto) { + // If there is no declaration, there was an error parsing it. Just ignore + // the initializer. + if (RealDecl == 0 || RealDecl->isInvalidDecl()) + return; + + // Check for self-references within variable initializers. + if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) { + // Variables declared within a function/method body are handled + // by a dataflow analysis. + if (!vd->hasLocalStorage() && !vd->isStaticLocal()) + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + else { + SelfReferenceChecker(*this, RealDecl).VisitExpr(Init); + } + + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) { + // With declarators parsed the way they are, the parser cannot + // distinguish between a normal initializer and a pure-specifier. + // Thus this grotesque test. + IntegerLiteral *IL; + if ((IL = dyn_cast<IntegerLiteral>(Init)) && IL->getValue() == 0 && + Context.getCanonicalType(IL->getType()) == Context.IntTy) + CheckPureMethod(Method, Init->getSourceRange()); + else { + Diag(Method->getLocation(), diag::err_member_function_initialization) + << Method->getDeclName() << Init->getSourceRange(); + Method->setInvalidDecl(); + } + return; + } + + VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl); + if (!VDecl) { + if (getLangOptions().CPlusPlus && + RealDecl->getLexicalDeclContext()->isRecord() && + isa<NamedDecl>(RealDecl)) + Diag(RealDecl->getLocation(), diag::err_member_initialization); + else + Diag(RealDecl->getLocation(), diag::err_illegal_initializer); + RealDecl->setInvalidDecl(); + return; + } + + // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) + Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) + << VDecl->getDeclName() << VDecl->getType() << Init->getType() + << Init->getSourceRange(); + if (!DeducedType) { + RealDecl->setInvalidDecl(); + return; + } + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); + + // If this is a redeclaration, check that the type we just deduced matches + // the previously declared type. + if (VarDecl *Old = VDecl->getPreviousDeclaration()) + MergeVarDeclTypes(VDecl, Old); + } + + + // A definition must end up with a complete type, which means it must be + // complete with the restriction that an array type might be completed by the + // initializer; note that later code assumes this restriction. + QualType BaseDeclType = VDecl->getType(); + if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) + BaseDeclType = Array->getElementType(); + if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, + diag::err_typecheck_decl_incomplete_type)) { + RealDecl->setInvalidDecl(); + return; + } + + // The variable can not have an abstract class type. + if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), + diag::err_abstract_type_in_decl, + AbstractVariableType)) + VDecl->setInvalidDecl(); + + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { + Diag(VDecl->getLocation(), diag::err_redefinition) + << VDecl->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + VDecl->setInvalidDecl(); + return; + } + + const VarDecl* PrevInit = 0; + if (getLangOptions().CPlusPlus) { + // C++ [class.static.data]p4 + // If a static data member is of const integral or const + // enumeration type, its declaration in the class definition can + // specify a constant-initializer which shall be an integral + // constant expression (5.19). In that case, the member can appear + // in integral constant expressions. The member shall still be + // defined in a namespace scope if it is used in the program and the + // namespace scope definition shall not contain an initializer. + // + // We already performed a redefinition check above, but for static + // data members we also need to check whether there was an in-class + // declaration with an initializer. + if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { + Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); + Diag(PrevInit->getLocation(), diag::note_previous_definition); + return; + } + + if (VDecl->hasLocalStorage()) + getCurFunction()->setHasBranchProtectedScope(); + + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) { + VDecl->setInvalidDecl(); + return; + } + } + + // Capture the variable that is being initialized and the style of + // initialization. + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + + // FIXME: Poor source location information. + InitializationKind Kind + = DirectInit? InitializationKind::CreateDirect(VDecl->getLocation(), + Init->getLocStart(), + Init->getLocEnd()) + : InitializationKind::CreateCopy(VDecl->getLocation(), + Init->getLocStart()); + + // Get the decls type and save a reference for later, since + // CheckInitializerTypes may change it. + QualType DclT = VDecl->getType(), SavT = DclT; + if (VDecl->isLocalVarDecl()) { + if (VDecl->hasExternalStorage()) { // C99 6.7.8p5 + Diag(VDecl->getLocation(), diag::err_block_extern_cant_init); + VDecl->setInvalidDecl(); + } else if (!VDecl->isInvalidDecl()) { + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Init, 1), + &DclT); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + + Init = Result.takeAs<Expr>(); + + // C++ 3.6.2p2, allow dynamic initialization of static initializers. + // Don't check invalid declarations to avoid emitting useless diagnostics. + if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { + if (VDecl->getStorageClass() == SC_Static) // C99 6.7.8p4. + CheckForConstantInitializer(Init, DclT); + } + } + } else if (VDecl->isStaticDataMember() && + VDecl->getLexicalDeclContext()->isRecord()) { + // This is an in-class initialization for a static data member, e.g., + // + // struct S { + // static const int value = 17; + // }; + + // Try to perform the initialization regardless. + if (!VDecl->isInvalidDecl()) { + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Init, 1), + &DclT); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + + Init = Result.takeAs<Expr>(); + } + + // C++ [class.mem]p4: + // A member-declarator can contain a constant-initializer only + // if it declares a static member (9.4) of const integral or + // const enumeration type, see 9.4.2. + QualType T = VDecl->getType(); + + // Do nothing on dependent types. + if (T->isDependentType()) { + + // Require constness. + } else if (!T.isConstQualified()) { + Diag(VDecl->getLocation(), diag::err_in_class_initializer_non_const) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); + + // We allow integer constant expressions in all cases. + } else if (T->isIntegralOrEnumerationType()) { + if (!Init->isValueDependent()) { + // Check whether the expression is a constant expression. + llvm::APSInt Value; + SourceLocation Loc; + if (!Init->isIntegerConstantExpr(Value, Context, &Loc)) { + Diag(Loc, diag::err_in_class_initializer_non_constant) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); + } + } + + // We allow floating-point constants as an extension in C++03, and + // C++0x has far more complicated rules that we don't really + // implement fully. + } else { + bool Allowed = false; + if (getLangOptions().CPlusPlus0x) { + Allowed = T->isLiteralType(); + } else if (T->isFloatingType()) { // also permits complex, which is ok + Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) + << T << Init->getSourceRange(); + Allowed = true; + } + + if (!Allowed) { + Diag(VDecl->getLocation(), diag::err_in_class_initializer_bad_type) + << T << Init->getSourceRange(); + VDecl->setInvalidDecl(); + + // TODO: there are probably expressions that pass here that shouldn't. + } else if (!Init->isValueDependent() && + !Init->isConstantInitializer(Context, false)) { + Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); + } + } + } else if (VDecl->isFileVarDecl()) { + if (VDecl->getStorageClassAsWritten() == SC_Extern && + (!getLangOptions().CPlusPlus || + !Context.getBaseElementType(VDecl->getType()).isConstQualified())) + Diag(VDecl->getLocation(), diag::warn_extern_init); + if (!VDecl->isInvalidDecl()) { + InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Init, 1), + &DclT); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + + Init = Result.takeAs<Expr>(); + } + + // C++ 3.6.2p2, allow dynamic initialization of static initializers. + // Don't check invalid declarations to avoid emitting useless diagnostics. + if (!getLangOptions().CPlusPlus && !VDecl->isInvalidDecl()) { + // C99 6.7.8p4. All file scoped initializers need to be constant. + CheckForConstantInitializer(Init, DclT); + } + } + // If the type changed, it means we had an incomplete type that was + // completed by the initializer. For example: + // int ary[] = { 1, 3, 5 }; + // "ary" transitions from a VariableArrayType to a ConstantArrayType. + if (!VDecl->isInvalidDecl() && (DclT != SavT)) { + VDecl->setType(DclT); + Init->setType(DclT); + } + + + // If this variable is a local declaration with record type, make sure it + // doesn't have a flexible member initialization. We only support this as a + // global/static definition. + if (VDecl->hasLocalStorage()) + if (const RecordType *RT = VDecl->getType()->getAs<RecordType>()) + if (RT->getDecl()->hasFlexibleArrayMember()) { + // Check whether the initializer tries to initialize the flexible + // array member itself to anything other than an empty initializer list. + if (InitListExpr *ILE = dyn_cast<InitListExpr>(Init)) { + unsigned Index = std::distance(RT->getDecl()->field_begin(), + RT->getDecl()->field_end()) - 1; + if (Index < ILE->getNumInits() && + !(isa<InitListExpr>(ILE->getInit(Index)) && + cast<InitListExpr>(ILE->getInit(Index))->getNumInits() == 0)) { + Diag(VDecl->getLocation(), diag::err_nonstatic_flexible_variable); + VDecl->setInvalidDecl(); + } + } + } + + // Check any implicit conversions within the expression. + CheckImplicitConversions(Init, VDecl->getLocation()); + + Init = MaybeCreateExprWithCleanups(Init); + // Attach the initializer to the decl. + VDecl->setInit(Init); + + CheckCompleteVariableDeclaration(VDecl); +} + +/// ActOnInitializerError - Given that there was an error parsing an +/// initializer for the given declaration, try to return to some form +/// of sanity. +void Sema::ActOnInitializerError(Decl *D) { + // Our main concern here is re-establishing invariants like "a + // variable's type is either dependent or complete". + if (!D || D->isInvalidDecl()) return; + + VarDecl *VD = dyn_cast<VarDecl>(D); + if (!VD) return; + + // Auto types are meaningless if we can't make sense of the initializer. + if (ParsingInitForAutoVars.count(D)) { + D->setInvalidDecl(); + return; + } + + QualType Ty = VD->getType(); + if (Ty->isDependentType()) return; + + // Require a complete type. + if (RequireCompleteType(VD->getLocation(), + Context.getBaseElementType(Ty), + diag::err_typecheck_decl_incomplete_type)) { + VD->setInvalidDecl(); + return; + } + + // Require an abstract type. + if (RequireNonAbstractType(VD->getLocation(), Ty, + diag::err_abstract_type_in_decl, + AbstractVariableType)) { + VD->setInvalidDecl(); + return; + } + + // Don't bother complaining about constructors or destructors, + // though. +} + +void Sema::ActOnUninitializedDecl(Decl *RealDecl, + bool TypeMayContainAuto) { + // If there is no declaration, there was an error parsing it. Just ignore it. + if (RealDecl == 0) + return; + + if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) { + QualType Type = Var->getType(); + + // C++0x [dcl.spec.auto]p3 + if (TypeMayContainAuto && Type->getContainedAutoType()) { + Diag(Var->getLocation(), diag::err_auto_var_requires_init) + << Var->getDeclName() << Type; + Var->setInvalidDecl(); + return; + } + + switch (Var->isThisDeclarationADefinition()) { + case VarDecl::Definition: + if (!Var->isStaticDataMember() || !Var->getAnyInitializer()) + break; + + // We have an out-of-line definition of a static data member + // that has an in-class initializer, so we type-check this like + // a declaration. + // + // Fall through + + case VarDecl::DeclarationOnly: + // It's only a declaration. + + // Block scope. C99 6.7p7: If an identifier for an object is + // declared with no linkage (C99 6.2.2p6), the type for the + // object shall be complete. + if (!Type->isDependentType() && Var->isLocalVarDecl() && + !Var->getLinkage() && !Var->isInvalidDecl() && + RequireCompleteType(Var->getLocation(), Type, + diag::err_typecheck_decl_incomplete_type)) + Var->setInvalidDecl(); + + // Make sure that the type is not abstract. + if (!Type->isDependentType() && !Var->isInvalidDecl() && + RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) + Var->setInvalidDecl(); + return; + + case VarDecl::TentativeDefinition: + // File scope. C99 6.9.2p2: A declaration of an identifier for an + // object that has file scope without an initializer, and without a + // storage-class specifier or with the storage-class specifier "static", + // constitutes a tentative definition. Note: A tentative definition with + // external linkage is valid (C99 6.2.2p5). + if (!Var->isInvalidDecl()) { + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(Type)) { + if (RequireCompleteType(Var->getLocation(), + ArrayT->getElementType(), + diag::err_illegal_decl_array_incomplete_type)) + Var->setInvalidDecl(); + } else if (Var->getStorageClass() == SC_Static) { + // C99 6.9.2p3: If the declaration of an identifier for an object is + // a tentative definition and has internal linkage (C99 6.2.2p3), the + // declared type shall not be an incomplete type. + // NOTE: code such as the following + // static struct s; + // struct s { int a; }; + // is accepted by gcc. Hence here we issue a warning instead of + // an error and we do not invalidate the static declaration. + // NOTE: to avoid multiple warnings, only check the first declaration. + if (Var->getPreviousDeclaration() == 0) + RequireCompleteType(Var->getLocation(), Type, + diag::ext_typecheck_decl_incomplete_type); + } + } + + // Record the tentative definition; we're done. + if (!Var->isInvalidDecl()) + TentativeDefinitions.push_back(Var); + return; + } + + // Provide a specific diagnostic for uninitialized variable + // definitions with incomplete array type. + if (Type->isIncompleteArrayType()) { + Diag(Var->getLocation(), + diag::err_typecheck_incomplete_array_needs_initializer); + Var->setInvalidDecl(); + return; + } + + // Provide a specific diagnostic for uninitialized variable + // definitions with reference type. + if (Type->isReferenceType()) { + Diag(Var->getLocation(), diag::err_reference_var_requires_init) + << Var->getDeclName() + << SourceRange(Var->getLocation(), Var->getLocation()); + Var->setInvalidDecl(); + return; + } + + // Do not attempt to type-check the default initializer for a + // variable with dependent type. + if (Type->isDependentType()) + return; + + if (Var->isInvalidDecl()) + return; + + if (RequireCompleteType(Var->getLocation(), + Context.getBaseElementType(Type), + diag::err_typecheck_decl_incomplete_type)) { + Var->setInvalidDecl(); + return; + } + + // The variable can not have an abstract class type. + if (RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) { + Var->setInvalidDecl(); + return; + } + + // Check for jumps past the implicit initializer. C++0x + // clarifies that this applies to a "variable with automatic + // storage duration", not a "local variable". + // C++0x [stmt.dcl]p3 + // A program that jumps from a point where a variable with automatic + // storage duration is not in scope to a point where it is in scope is + // ill-formed unless the variable has scalar type, class type with a + // trivial default constructor and a trivial destructor, a cv-qualified + // version of one of these types, or an array of one of the preceding + // types and is declared without an initializer. + if (getLangOptions().CPlusPlus && Var->hasLocalStorage()) { + if (const RecordType *Record + = Context.getBaseElementType(Type)->getAs<RecordType>()) { + CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record->getDecl()); + if ((!getLangOptions().CPlusPlus0x && !CXXRecord->isPOD()) || + (getLangOptions().CPlusPlus0x && + (!CXXRecord->hasTrivialDefaultConstructor() || + !CXXRecord->hasTrivialDestructor()))) + getCurFunction()->setHasBranchProtectedScope(); + } + } + + // C++03 [dcl.init]p9: + // If no initializer is specified for an object, and the + // object is of (possibly cv-qualified) non-POD class type (or + // array thereof), the object shall be default-initialized; if + // the object is of const-qualified type, the underlying class + // type shall have a user-declared default + // constructor. Otherwise, if no initializer is specified for + // a non- static object, the object and its subobjects, if + // any, have an indeterminate initial value); if the object + // or any of its subobjects are of const-qualified type, the + // program is ill-formed. + // C++0x [dcl.init]p11: + // If no initializer is specified for an object, the object is + // default-initialized; [...]. + InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); + InitializationKind Kind + = InitializationKind::CreateDefault(Var->getLocation()); + + InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); + ExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); + if (Init.isInvalid()) + Var->setInvalidDecl(); + else if (Init.get()) + Var->setInit(MaybeCreateExprWithCleanups(Init.get())); + + CheckCompleteVariableDeclaration(Var); + } +} + +void Sema::ActOnCXXForRangeDecl(Decl *D) { + VarDecl *VD = dyn_cast<VarDecl>(D); + if (!VD) { + Diag(D->getLocation(), diag::err_for_range_decl_must_be_var); + D->setInvalidDecl(); + return; + } + + VD->setCXXForRangeDecl(true); + + // for-range-declaration cannot be given a storage class specifier. + int Error = -1; + switch (VD->getStorageClassAsWritten()) { + case SC_None: + break; + case SC_Extern: + Error = 0; + break; + case SC_Static: + Error = 1; + break; + case SC_PrivateExtern: + Error = 2; + break; + case SC_Auto: + Error = 3; + break; + case SC_Register: + Error = 4; + break; + } + // FIXME: constexpr isn't allowed here. + //if (DS.isConstexprSpecified()) + // Error = 5; + if (Error != -1) { + Diag(VD->getOuterLocStart(), diag::err_for_range_storage_class) + << VD->getDeclName() << Error; + D->setInvalidDecl(); + } +} + +void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { + if (var->isInvalidDecl()) return; + + // All the following checks are C++ only. + if (!getLangOptions().CPlusPlus) return; + + QualType baseType = Context.getBaseElementType(var->getType()); + if (baseType->isDependentType()) return; + + // __block variables might require us to capture a copy-initializer. + if (var->hasAttr<BlocksAttr>()) { + // It's currently invalid to ever have a __block variable with an + // array type; should we diagnose that here? + + // Regardless, we don't want to ignore array nesting when + // constructing this copy. + QualType type = var->getType(); + + if (type->isStructureOrClassType()) { + SourceLocation poi = var->getLocation(); + Expr *varRef = new (Context) DeclRefExpr(var, type, VK_LValue, poi); + ExprResult result = + PerformCopyInitialization( + InitializedEntity::InitializeBlock(poi, type, false), + poi, Owned(varRef)); + if (!result.isInvalid()) { + result = MaybeCreateExprWithCleanups(result); + Expr *init = result.takeAs<Expr>(); + Context.setBlockVarCopyInits(var, init); + } + } + } + + // Check for global constructors. + if (!var->getDeclContext()->isDependentContext() && + var->hasGlobalStorage() && + !var->isStaticLocal() && + var->getInit() && + !var->getInit()->isConstantInitializer(Context, + baseType->isReferenceType())) + Diag(var->getLocation(), diag::warn_global_constructor) + << var->getInit()->getSourceRange(); + + // Require the destructor. + if (const RecordType *recordType = baseType->getAs<RecordType>()) + FinalizeVarWithDestructor(var, recordType); +} + +/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform +/// any semantic actions necessary after any initializer has been attached. +void +Sema::FinalizeDeclaration(Decl *ThisDecl) { + // Note that we are no longer parsing the initializer for this declaration. + ParsingInitForAutoVars.erase(ThisDecl); +} + +Sema::DeclGroupPtrTy +Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, + Decl **Group, unsigned NumDecls) { + llvm::SmallVector<Decl*, 8> Decls; + + if (DS.isTypeSpecOwned()) + Decls.push_back(DS.getRepAsDecl()); + + for (unsigned i = 0; i != NumDecls; ++i) + if (Decl *D = Group[i]) + Decls.push_back(D); + + return BuildDeclaratorGroup(Decls.data(), Decls.size(), + DS.getTypeSpecType() == DeclSpec::TST_auto); +} + +/// BuildDeclaratorGroup - convert a list of declarations into a declaration +/// group, performing any necessary semantic checking. +Sema::DeclGroupPtrTy +Sema::BuildDeclaratorGroup(Decl **Group, unsigned NumDecls, + bool TypeMayContainAuto) { + // C++0x [dcl.spec.auto]p7: + // If the type deduced for the template parameter U is not the same in each + // deduction, the program is ill-formed. + // FIXME: When initializer-list support is added, a distinction is needed + // between the deduced type U and the deduced type which 'auto' stands for. + // auto a = 0, b = { 1, 2, 3 }; + // is legal because the deduced type U is 'int' in both cases. + if (TypeMayContainAuto && NumDecls > 1) { + QualType Deduced; + CanQualType DeducedCanon; + VarDecl *DeducedDecl = 0; + for (unsigned i = 0; i != NumDecls; ++i) { + if (VarDecl *D = dyn_cast<VarDecl>(Group[i])) { + AutoType *AT = D->getType()->getContainedAutoType(); + // Don't reissue diagnostics when instantiating a template. + if (AT && D->isInvalidDecl()) + break; + if (AT && AT->isDeduced()) { + QualType U = AT->getDeducedType(); + CanQualType UCanon = Context.getCanonicalType(U); + if (Deduced.isNull()) { + Deduced = U; + DeducedCanon = UCanon; + DeducedDecl = D; + } else if (DeducedCanon != UCanon) { + Diag(D->getTypeSourceInfo()->getTypeLoc().getBeginLoc(), + diag::err_auto_different_deductions) + << Deduced << DeducedDecl->getDeclName() + << U << D->getDeclName() + << DeducedDecl->getInit()->getSourceRange() + << D->getInit()->getSourceRange(); + D->setInvalidDecl(); + break; + } + } + } + } + } + + return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Group, NumDecls)); +} + + +/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() +/// to introduce parameters into function prototype scope. +Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { + const DeclSpec &DS = D.getDeclSpec(); + + // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. + VarDecl::StorageClass StorageClass = SC_None; + VarDecl::StorageClass StorageClassAsWritten = SC_None; + if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { + StorageClass = SC_Register; + StorageClassAsWritten = SC_Register; + } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { + Diag(DS.getStorageClassSpecLoc(), + diag::err_invalid_storage_class_in_func_decl); + D.getMutableDeclSpec().ClearStorageClassSpecs(); + } + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + + DiagnoseFunctionSpecifiers(D); + + TagDecl *OwnedDecl = 0; + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl); + QualType parmDeclType = TInfo->getType(); + + if (getLangOptions().CPlusPlus) { + // Check that there are no default arguments inside the type of this + // parameter. + CheckExtraCXXDefaultArguments(D); + + if (OwnedDecl && OwnedDecl->isDefinition()) { + // C++ [dcl.fct]p6: + // Types shall not be defined in return or parameter types. + Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type) + << Context.getTypeDeclType(OwnedDecl); + } + + // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). + if (D.getCXXScopeSpec().isSet()) { + Diag(D.getIdentifierLoc(), diag::err_qualified_param_declarator) + << D.getCXXScopeSpec().getRange(); + D.getCXXScopeSpec().clear(); + } + } + + // Ensure we have a valid name + IdentifierInfo *II = 0; + if (D.hasName()) { + II = D.getIdentifier(); + if (!II) { + Diag(D.getIdentifierLoc(), diag::err_bad_parameter_name) + << GetNameForDeclarator(D).getName().getAsString(); + D.setInvalidType(true); + } + } + + // Check for redeclaration of parameters, e.g. int foo(int x, int x); + if (II) { + LookupResult R(*this, II, D.getIdentifierLoc(), LookupOrdinaryName, + ForRedeclaration); + LookupName(R, S); + if (R.isSingleResult()) { + NamedDecl *PrevDecl = R.getFoundDecl(); + if (PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } else if (S->isDeclScope(PrevDecl)) { + Diag(D.getIdentifierLoc(), diag::err_param_redefinition) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + + // Recover by removing the name + II = 0; + D.SetIdentifier(0, D.getIdentifierLoc()); + D.setInvalidType(true); + } + } + } + + // Temporarily put parameter variables in the translation unit, not + // the enclosing context. This prevents them from accidentally + // looking like class members in C++. + ParmVarDecl *New = CheckParameter(Context.getTranslationUnitDecl(), + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), II, + parmDeclType, TInfo, + StorageClass, StorageClassAsWritten); + + if (D.isInvalidType()) + New->setInvalidDecl(); + + assert(S->isFunctionPrototypeScope()); + assert(S->getFunctionPrototypeDepth() >= 1); + New->setScopeInfo(S->getFunctionPrototypeDepth() - 1, + S->getNextFunctionPrototypeIndex()); + + // Add the parameter declaration into this scope. + S->AddDecl(New); + if (II) + IdResolver.AddDecl(New); + + ProcessDeclAttributes(S, New, D); + + if (New->hasAttr<BlocksAttr>()) { + Diag(New->getLocation(), diag::err_block_on_nonlocal); + } + return New; +} + +/// \brief Synthesizes a variable for a parameter arising from a +/// typedef. +ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, + SourceLocation Loc, + QualType T) { + /* FIXME: setting StartLoc == Loc. + Would it be worth to modify callers so as to provide proper source + location for the unnamed parameters, embedding the parameter's type? */ + ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, Loc, 0, + T, Context.getTrivialTypeSourceInfo(T, Loc), + SC_None, SC_None, 0); + Param->setImplicit(); + return Param; +} + +void Sema::DiagnoseUnusedParameters(ParmVarDecl * const *Param, + ParmVarDecl * const *ParamEnd) { + // Don't diagnose unused-parameter errors in template instantiations; we + // will already have done so in the template itself. + if (!ActiveTemplateInstantiations.empty()) + return; + + for (; Param != ParamEnd; ++Param) { + if (!(*Param)->isUsed() && (*Param)->getDeclName() && + !(*Param)->hasAttr<UnusedAttr>()) { + Diag((*Param)->getLocation(), diag::warn_unused_parameter) + << (*Param)->getDeclName(); + } + } +} + +void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, + ParmVarDecl * const *ParamEnd, + QualType ReturnTy, + NamedDecl *D) { + if (LangOpts.NumLargeByValueCopy == 0) // No check. + return; + + // Warn if the return value is pass-by-value and larger than the specified + // threshold. + if (ReturnTy->isPODType()) { + unsigned Size = Context.getTypeSizeInChars(ReturnTy).getQuantity(); + if (Size > LangOpts.NumLargeByValueCopy) + Diag(D->getLocation(), diag::warn_return_value_size) + << D->getDeclName() << Size; + } + + // Warn if any parameter is pass-by-value and larger than the specified + // threshold. + for (; Param != ParamEnd; ++Param) { + QualType T = (*Param)->getType(); + if (!T->isPODType()) + continue; + unsigned Size = Context.getTypeSizeInChars(T).getQuantity(); + if (Size > LangOpts.NumLargeByValueCopy) + Diag((*Param)->getLocation(), diag::warn_parameter_size) + << (*Param)->getDeclName() << Size; + } +} + +ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, + SourceLocation NameLoc, IdentifierInfo *Name, + QualType T, TypeSourceInfo *TSInfo, + VarDecl::StorageClass StorageClass, + VarDecl::StorageClass StorageClassAsWritten) { + ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, + adjustParameterType(T), TSInfo, + StorageClass, StorageClassAsWritten, + 0); + + // Parameters can not be abstract class types. + // For record types, this is done by the AbstractClassUsageDiagnoser once + // the class has been completely parsed. + if (!CurContext->isRecord() && + RequireNonAbstractType(NameLoc, T, diag::err_abstract_type_in_decl, + AbstractParamType)) + New->setInvalidDecl(); + + // Parameter declarators cannot be interface types. All ObjC objects are + // passed by reference. + if (T->isObjCObjectType()) { + Diag(NameLoc, + diag::err_object_cannot_be_passed_returned_by_value) << 1 << T; + New->setInvalidDecl(); + } + + // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage + // duration shall not be qualified by an address-space qualifier." + // Since all parameters have automatic store duration, they can not have + // an address space. + if (T.getAddressSpace() != 0) { + Diag(NameLoc, diag::err_arg_with_address_space); + New->setInvalidDecl(); + } + + return New; +} + +void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, + SourceLocation LocAfterDecls) { + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + + // Verify 6.9.1p6: 'every identifier in the identifier list shall be declared' + // for a K&R function. + if (!FTI.hasPrototype) { + for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) { + --i; + if (FTI.ArgInfo[i].Param == 0) { + llvm::SmallString<256> Code; + llvm::raw_svector_ostream(Code) << " int " + << FTI.ArgInfo[i].Ident->getName() + << ";\n"; + Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared) + << FTI.ArgInfo[i].Ident + << FixItHint::CreateInsertion(LocAfterDecls, Code.str()); + + // Implicitly declare the argument as type 'int' for lack of a better + // type. + AttributeFactory attrs; + DeclSpec DS(attrs); + const char* PrevSpec; // unused + unsigned DiagID; // unused + DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, + PrevSpec, DiagID); + Declarator ParamD(DS, Declarator::KNRTypeListContext); + ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc); + FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD); + } + } + } +} + +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, + Declarator &D) { + assert(getCurFunctionDecl() == 0 && "Function parsing confused"); + assert(D.isFunctionDeclarator() && "Not a function declarator!"); + Scope *ParentScope = FnBodyScope->getParent(); + + Decl *DP = HandleDeclarator(ParentScope, D, + MultiTemplateParamsArg(*this), + /*IsFunctionDefinition=*/true); + return ActOnStartOfFunctionDef(FnBodyScope, DP); +} + +static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { + // Don't warn about invalid declarations. + if (FD->isInvalidDecl()) + return false; + + // Or declarations that aren't global. + if (!FD->isGlobal()) + return false; + + // Don't warn about C++ member functions. + if (isa<CXXMethodDecl>(FD)) + return false; + + // Don't warn about 'main'. + if (FD->isMain()) + return false; + + // Don't warn about inline functions. + if (FD->isInlined()) + return false; + + // Don't warn about function templates. + if (FD->getDescribedFunctionTemplate()) + return false; + + // Don't warn about function template specializations. + if (FD->isFunctionTemplateSpecialization()) + return false; + + bool MissingPrototype = true; + for (const FunctionDecl *Prev = FD->getPreviousDeclaration(); + Prev; Prev = Prev->getPreviousDeclaration()) { + // Ignore any declarations that occur in function or method + // scope, because they aren't visible from the header. + if (Prev->getDeclContext()->isFunctionOrMethod()) + continue; + + MissingPrototype = !Prev->getType()->isFunctionProtoType(); + break; + } + + return MissingPrototype; +} + +void Sema::CheckForFunctionRedefinition(FunctionDecl *FD) { + // Don't complain if we're in GNU89 mode and the previous definition + // was an extern inline function. + const FunctionDecl *Definition; + if (FD->isDefined(Definition) && + !canRedefineFunction(Definition, getLangOptions())) { + if (getLangOptions().GNUMode && Definition->isInlineSpecified() && + Definition->getStorageClass() == SC_Extern) + Diag(FD->getLocation(), diag::err_redefinition_extern_inline) + << FD->getDeclName() << getLangOptions().CPlusPlus; + else + Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); + Diag(Definition->getLocation(), diag::note_previous_definition); + } +} + +Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { + // Clear the last template instantiation error context. + LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); + + if (!D) + return D; + FunctionDecl *FD = 0; + + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) + FD = FunTmpl->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(D); + + // Enter a new function scope + PushFunctionScope(); + + // See if this is a redefinition. + if (!FD->isLateTemplateParsed()) + CheckForFunctionRedefinition(FD); + + // Builtin functions cannot be defined. + if (unsigned BuiltinID = FD->getBuiltinID()) { + if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) { + Diag(FD->getLocation(), diag::err_builtin_definition) << FD; + FD->setInvalidDecl(); + } + } + + // The return type of a function definition must be complete + // (C99 6.9.1p3, C++ [dcl.fct]p6). + QualType ResultType = FD->getResultType(); + if (!ResultType->isDependentType() && !ResultType->isVoidType() && + !FD->isInvalidDecl() && + RequireCompleteType(FD->getLocation(), ResultType, + diag::err_func_def_incomplete_result)) + FD->setInvalidDecl(); + + // GNU warning -Wmissing-prototypes: + // Warn if a global function is defined without a previous + // prototype declaration. This warning is issued even if the + // definition itself provides a prototype. The aim is to detect + // global functions that fail to be declared in header files. + if (ShouldWarnAboutMissingPrototype(FD)) + Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; + + if (FnBodyScope) + PushDeclContext(FnBodyScope, FD); + + // Check the validity of our function parameters + CheckParmsForFunctionDef(FD->param_begin(), FD->param_end(), + /*CheckParameterNames=*/true); + + // Introduce our parameters into the function scope + for (unsigned p = 0, NumParams = FD->getNumParams(); p < NumParams; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + Param->setOwningFunction(FD); + + // If this has an identifier, add it to the scope stack. + if (Param->getIdentifier() && FnBodyScope) { + CheckShadow(FnBodyScope, Param); + + PushOnScopeChains(Param, FnBodyScope); + } + } + + // Checking attributes of current function definition + // dllimport attribute. + DLLImportAttr *DA = FD->getAttr<DLLImportAttr>(); + if (DA && (!FD->getAttr<DLLExportAttr>())) { + // dllimport attribute cannot be directly applied to definition. + // Microsoft accepts dllimport for functions defined within class scope. + if (!DA->isInherited() && + !(LangOpts.Microsoft && FD->getLexicalDeclContext()->isRecord())) { + Diag(FD->getLocation(), + diag::err_attribute_can_be_applied_only_to_symbol_declaration) + << "dllimport"; + FD->setInvalidDecl(); + return FD; + } + + // Visual C++ appears to not think this is an issue, so only issue + // a warning when Microsoft extensions are disabled. + if (!LangOpts.Microsoft) { + // If a symbol previously declared dllimport is later defined, the + // attribute is ignored in subsequent references, and a warning is + // emitted. + Diag(FD->getLocation(), + diag::warn_redeclaration_without_attribute_prev_attribute_ignored) + << FD->getName() << "dllimport"; + } + } + return FD; +} + +/// \brief Given the set of return statements within a function body, +/// compute the variables that are subject to the named return value +/// optimization. +/// +/// Each of the variables that is subject to the named return value +/// optimization will be marked as NRVO variables in the AST, and any +/// return statement that has a marked NRVO variable as its NRVO candidate can +/// use the named return value optimization. +/// +/// This function applies a very simplistic algorithm for NRVO: if every return +/// statement in the function has the same NRVO candidate, that candidate is +/// the NRVO variable. +/// +/// 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, FunctionScopeInfo *Scope) { + ReturnStmt **Returns = Scope->Returns.data(); + + const VarDecl *NRVOCandidate = 0; + for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { + if (!Returns[I]->getNRVOCandidate()) + return; + + if (!NRVOCandidate) + NRVOCandidate = Returns[I]->getNRVOCandidate(); + else if (NRVOCandidate != Returns[I]->getNRVOCandidate()) + return; + } + + if (NRVOCandidate) + const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true); +} + +Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { + return ActOnFinishFunctionBody(D, move(BodyArg), false); +} + +Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, + bool IsInstantiation) { + FunctionDecl *FD = 0; + FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl); + if (FunTmpl) + FD = FunTmpl->getTemplatedDecl(); + else + FD = dyn_cast_or_null<FunctionDecl>(dcl); + + sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); + sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0; + + if (FD) { + FD->setBody(Body); + if (FD->isMain()) { + // C and C++ allow for main to automagically return 0. + // Implements C++ [basic.start.main]p5 and C99 5.1.2.2.3. + FD->setHasImplicitReturnZero(true); + WP.disableCheckFallThrough(); + } + + // MSVC permits the use of pure specifier (=0) on function definition, + // defined at class scope, warn about this non standard construct. + if (getLangOptions().Microsoft && FD->isPure()) + Diag(FD->getLocation(), diag::warn_pure_function_definition); + + if (!FD->isInvalidDecl()) { + DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); + DiagnoseSizeOfParametersAndReturnValue(FD->param_begin(), FD->param_end(), + FD->getResultType(), FD); + + // If this is a constructor, we need a vtable. + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(FD)) + MarkVTableUsed(FD->getLocation(), Constructor->getParent()); + + ComputeNRVO(Body, getCurFunction()); + } + + assert(FD == getCurFunctionDecl() && "Function parsing confused"); + } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { + assert(MD == getCurMethodDecl() && "Method parsing confused"); + MD->setBody(Body); + if (Body) + MD->setEndLoc(Body->getLocEnd()); + if (!MD->isInvalidDecl()) { + DiagnoseUnusedParameters(MD->param_begin(), MD->param_end()); + DiagnoseSizeOfParametersAndReturnValue(MD->param_begin(), MD->param_end(), + MD->getResultType(), MD); + } + } else { + return 0; + } + + // Verify and clean out per-function state. + if (Body) { + // C++ constructors that have function-try-blocks can't have return + // statements in the handlers of that block. (C++ [except.handle]p14) + // Verify this. + if (FD && isa<CXXConstructorDecl>(FD) && isa<CXXTryStmt>(Body)) + DiagnoseReturnInConstructorExceptionHandler(cast<CXXTryStmt>(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 (getCurFunction()->NeedsScopeChecking() && + !dcl->isInvalidDecl() && + !hasAnyErrorsInThisFunction()) + DiagnoseInvalidJumps(Body); + + if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(dcl)) { + if (!Destructor->getParent()->isDependentType()) + CheckDestructor(Destructor); + + MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), + Destructor->getParent()); + } + + // If any errors have occurred, clear out any temporaries that may have + // been leftover. This ensures that these temporaries won't be picked up for + // deletion in some later function. + if (PP.getDiagnostics().hasErrorOccurred() || + PP.getDiagnostics().getSuppressAllDiagnostics()) + ExprTemporaries.clear(); + else if (!isa<FunctionTemplateDecl>(dcl)) { + // Since the body is valid, issue any analysis-based warnings that are + // enabled. + ActivePolicy = &WP; + } + + assert(ExprTemporaries.empty() && "Leftover temporaries in function"); + } + + if (!IsInstantiation) + PopDeclContext(); + + PopFunctionOrBlockScope(ActivePolicy, dcl); + + // If any errors have occurred, clear out any temporaries that may have + // been leftover. This ensures that these temporaries won't be picked up for + // deletion in some later function. + if (getDiagnostics().hasErrorOccurred()) + ExprTemporaries.clear(); + + return dcl; +} + +/// ImplicitlyDefineFunction - An undeclared identifier was used in a function +/// call, forming a call to an implicitly defined function (per C99 6.5.1p2). +NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, + IdentifierInfo &II, Scope *S) { + // Before we produce a declaration for an implicitly defined + // function, see whether there was a locally-scoped declaration of + // this name as a function or variable. If so, use that + // (non-visible) declaration, and complain about it. + llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos + = LocallyScopedExternalDecls.find(&II); + if (Pos != LocallyScopedExternalDecls.end()) { + Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second; + Diag(Pos->second->getLocation(), diag::note_previous_declaration); + return Pos->second; + } + + // Extension in C99. Legal in C90, but warn about it. + if (II.getName().startswith("__builtin_")) + Diag(Loc, diag::warn_builtin_unknown) << &II; + else if (getLangOptions().C99) + Diag(Loc, diag::ext_implicit_function_decl) << &II; + else + Diag(Loc, diag::warn_implicit_function_decl) << &II; + + // Set a Declarator for the implicit definition: int foo(); + const char *Dummy; + AttributeFactory attrFactory; + DeclSpec DS(attrFactory); + unsigned DiagID; + bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID); + (void)Error; // Silence warning. + assert(!Error && "Error setting up implicit decl!"); + Declarator D(DS, Declarator::BlockContext); + D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, SourceLocation(), 0, + 0, 0, true, SourceLocation(), + EST_None, SourceLocation(), + 0, 0, 0, 0, Loc, Loc, D), + DS.getAttributes(), + SourceLocation()); + D.SetIdentifier(&II, Loc); + + // Insert this function into translation-unit scope. + + DeclContext *PrevDC = CurContext; + CurContext = Context.getTranslationUnitDecl(); + + FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D)); + FD->setImplicit(); + + CurContext = PrevDC; + + AddKnownFunctionAttributes(FD); + + return FD; +} + +/// \brief Adds any function attributes that we know a priori based on +/// the declaration of this function. +/// +/// These attributes can apply both to implicitly-declared builtins +/// (like __builtin___printf_chk) or to library-declared functions +/// like NSLog or printf. +void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { + if (FD->isInvalidDecl()) + return; + + // If this is a built-in function, map its builtin attributes to + // actual attributes. + if (unsigned BuiltinID = FD->getBuiltinID()) { + // Handle printf-formatting attributes. + unsigned FormatIdx; + bool HasVAListArg; + if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { + if (!FD->getAttr<FormatAttr>()) + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "printf", FormatIdx+1, + HasVAListArg ? 0 : FormatIdx+2)); + } + if (Context.BuiltinInfo.isScanfLike(BuiltinID, FormatIdx, + HasVAListArg)) { + if (!FD->getAttr<FormatAttr>()) + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "scanf", FormatIdx+1, + HasVAListArg ? 0 : FormatIdx+2)); + } + + // Mark const if we don't care about errno and that is the only + // thing preventing the function from being const. This allows + // IRgen to use LLVM intrinsics for such functions. + if (!getLangOptions().MathErrno && + Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { + if (!FD->getAttr<ConstAttr>()) + FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); + } + + if (Context.BuiltinInfo.isNoThrow(BuiltinID)) + FD->addAttr(::new (Context) NoThrowAttr(FD->getLocation(), Context)); + if (Context.BuiltinInfo.isConst(BuiltinID)) + FD->addAttr(::new (Context) ConstAttr(FD->getLocation(), Context)); + } + + IdentifierInfo *Name = FD->getIdentifier(); + if (!Name) + return; + if ((!getLangOptions().CPlusPlus && + FD->getDeclContext()->isTranslationUnit()) || + (isa<LinkageSpecDecl>(FD->getDeclContext()) && + cast<LinkageSpecDecl>(FD->getDeclContext())->getLanguage() == + LinkageSpecDecl::lang_c)) { + // Okay: this could be a libc/libm/Objective-C function we know + // about. + } else + return; + + if (Name->isStr("NSLog") || Name->isStr("NSLogv")) { + // FIXME: NSLog and NSLogv should be target specific + if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { + // FIXME: We known better than our headers. + const_cast<FormatAttr *>(Format)->setType(Context, "printf"); + } else + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "printf", 1, + Name->isStr("NSLogv") ? 0 : 2)); + } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { + // FIXME: asprintf and vasprintf aren't C99 functions. Should they be + // target-specific builtins, perhaps? + if (!FD->getAttr<FormatAttr>()) + FD->addAttr(::new (Context) FormatAttr(FD->getLocation(), Context, + "printf", 2, + Name->isStr("vasprintf") ? 0 : 3)); + } +} + +TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, + TypeSourceInfo *TInfo) { + assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); + assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); + + if (!TInfo) { + assert(D.isInvalidType() && "no declarator info for valid type"); + TInfo = Context.getTrivialTypeSourceInfo(T); + } + + // Scope manipulation handled by caller. + TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier(), + TInfo); + + // Bail out immediately if we have an invalid declaration. + if (D.isInvalidType()) { + NewTD->setInvalidDecl(); + return NewTD; + } + + // C++ [dcl.typedef]p8: + // If the typedef declaration defines an unnamed class (or + // enum), the first typedef-name declared by the declaration + // to be that class type (or enum type) is used to denote the + // class type (or enum type) for linkage purposes only. + // We need to check whether the type was declared in the declaration. + switch (D.getDeclSpec().getTypeSpecType()) { + case TST_enum: + case TST_struct: + case TST_union: + case TST_class: { + TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); + + // Do nothing if the tag is not anonymous or already has an + // associated typedef (from an earlier typedef in this decl group). + if (tagFromDeclSpec->getIdentifier()) break; + if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; + + // A well-formed anonymous tag must always be a TUK_Definition. + assert(tagFromDeclSpec->isThisDeclarationADefinition()); + + // The type must match the tag exactly; no qualifiers allowed. + if (!Context.hasSameType(T, Context.getTagDeclType(tagFromDeclSpec))) + break; + + // Otherwise, set this is the anon-decl typedef for the tag. + tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); + break; + } + + default: + break; + } + + return NewTD; +} + + +/// \brief Determine whether a tag with a given kind is acceptable +/// as a redeclaration of the given tag declaration. +/// +/// \returns true if the new tag kind is acceptable, false otherwise. +bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, + TagTypeKind NewTag, bool isDefinition, + SourceLocation NewTagLoc, + const IdentifierInfo &Name) { + // C++ [dcl.type.elab]p3: + // The class-key or enum keyword present in the + // elaborated-type-specifier shall agree in kind with the + // declaration to which the name in the elaborated-type-specifier + // refers. This rule also applies to the form of + // elaborated-type-specifier that declares a class-name or + // friend class since it can be construed as referring to the + // definition of the class. Thus, in any + // elaborated-type-specifier, the enum keyword shall be used to + // refer to an enumeration (7.2), the union class-key shall be + // used to refer to a union (clause 9), and either the class or + // struct class-key shall be used to refer to a class (clause 9) + // declared using the class or struct class-key. + TagTypeKind OldTag = Previous->getTagKind(); + if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct)) + if (OldTag == NewTag) + return true; + + if ((OldTag == TTK_Struct || OldTag == TTK_Class) && + (NewTag == TTK_Struct || NewTag == TTK_Class)) { + // Warn about the struct/class tag mismatch. + bool isTemplate = false; + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous)) + isTemplate = Record->getDescribedClassTemplate(); + + if (!ActiveTemplateInstantiations.empty()) { + // In a template instantiation, do not offer fix-its for tag mismatches + // since they usually mess up the template instead of fixing the problem. + Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) + << (NewTag == TTK_Class) << isTemplate << &Name; + return true; + } + + if (isDefinition) { + // On definitions, check previous tags and issue a fix-it for each + // one that doesn't match the current tag. + if (Previous->getDefinition()) { + // Don't suggest fix-its for redefinitions. + return true; + } + + bool previousMismatch = false; + for (TagDecl::redecl_iterator I(Previous->redecls_begin()), + E(Previous->redecls_end()); I != E; ++I) { + if (I->getTagKind() != NewTag) { + if (!previousMismatch) { + previousMismatch = true; + Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) + << (NewTag == TTK_Class) << isTemplate << &Name; + } + Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) + << (NewTag == TTK_Class) + << FixItHint::CreateReplacement(I->getInnerLocStart(), + NewTag == TTK_Class? + "class" : "struct"); + } + } + return true; + } + + // Check for a previous definition. If current tag and definition + // are same type, do nothing. If no definition, but disagree with + // with previous tag type, give a warning, but no fix-it. + const TagDecl *Redecl = Previous->getDefinition() ? + Previous->getDefinition() : Previous; + if (Redecl->getTagKind() == NewTag) { + return true; + } + + Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) + << (NewTag == TTK_Class) + << isTemplate << &Name; + Diag(Redecl->getLocation(), diag::note_previous_use); + + // If there is a previous defintion, suggest a fix-it. + if (Previous->getDefinition()) { + Diag(NewTagLoc, diag::note_struct_class_suggestion) + << (Redecl->getTagKind() == TTK_Class) + << FixItHint::CreateReplacement(SourceRange(NewTagLoc), + Redecl->getTagKind() == TTK_Class? "class" : "struct"); + } + + return true; + } + return false; +} + +/// ActOnTag - This is invoked when we see 'struct foo' or 'struct {'. In the +/// former case, Name will be non-null. In the later case, Name will be null. +/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a +/// reference/declaration/definition of a tag. +Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, AccessSpecifier AS, + MultiTemplateParamsArg TemplateParameterLists, + bool &OwnedDecl, bool &IsDependent, + bool ScopedEnum, bool ScopedEnumUsesClassTag, + TypeResult UnderlyingType) { + // If this is not a definition, it must have a name. + assert((Name != 0 || TUK == TUK_Definition) && + "Nameless record must be a definition!"); + assert(TemplateParameterLists.size() == 0 || TUK != TUK_Reference); + + OwnedDecl = false; + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + + // FIXME: Check explicit specializations more carefully. + bool isExplicitSpecialization = false; + bool Invalid = false; + + // We only need to do this matching if we have template parameters + // or a scope specifier, which also conveniently avoids this work + // for non-C++ cases. + if (TemplateParameterLists.size() > 0 || + (SS.isNotEmpty() && TUK != TUK_Reference)) { + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(KWLoc, NameLoc, SS, + TemplateParameterLists.get(), + TemplateParameterLists.size(), + TUK == TUK_Friend, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // This is a declaration or definition of a class template (which may + // be a member of another template). + + if (Invalid) + return 0; + + OwnedDecl = false; + DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, + SS, Name, NameLoc, Attr, + TemplateParams, AS, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); + return Result.get(); + } else { + // The "template<>" header is extraneous. + Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) + << TypeWithKeyword::getTagTypeKindName(Kind) << Name; + isExplicitSpecialization = true; + } + } + } + + // Figure out the underlying type if this a enum declaration. We need to do + // this early, because it's needed to detect if this is an incompatible + // redeclaration. + llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying; + + if (Kind == TTK_Enum) { + if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) + // No underlying type explicitly specified, or we failed to parse the + // type, default to int. + EnumUnderlying = Context.IntTy.getTypePtr(); + else if (UnderlyingType.get()) { + // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an + // integral type; any cv-qualification is ignored. + TypeSourceInfo *TI = 0; + QualType T = GetTypeFromParser(UnderlyingType.get(), &TI); + EnumUnderlying = TI; + + SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); + + if (!T->isDependentType() && !T->isIntegralType(Context)) { + Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) + << T; + // Recover by falling back to int. + EnumUnderlying = Context.IntTy.getTypePtr(); + } + + if (DiagnoseUnexpandedParameterPack(UnderlyingLoc, TI, + UPPC_FixedUnderlyingType)) + EnumUnderlying = Context.IntTy.getTypePtr(); + + } else if (getLangOptions().Microsoft) + // Microsoft enums are always of int type. + EnumUnderlying = Context.IntTy.getTypePtr(); + } + + DeclContext *SearchDC = CurContext; + DeclContext *DC = CurContext; + bool isStdBadAlloc = false; + + RedeclarationKind Redecl = ForRedeclaration; + if (TUK == TUK_Friend || TUK == TUK_Reference) + Redecl = NotForRedeclaration; + + LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl); + + if (Name && SS.isNotEmpty()) { + // We have a nested-name tag ('struct foo::bar'). + + // Check for invalid 'foo::'. + if (SS.isInvalid()) { + Name = 0; + goto CreateNewDecl; + } + + // If this is a friend or a reference to a class in a dependent + // context, don't try to make a decl for it. + if (TUK == TUK_Friend || TUK == TUK_Reference) { + DC = computeDeclContext(SS, false); + if (!DC) { + IsDependent = true; + return 0; + } + } else { + DC = computeDeclContext(SS, true); + if (!DC) { + Diag(SS.getRange().getBegin(), diag::err_dependent_nested_name_spec) + << SS.getRange(); + return 0; + } + } + + if (RequireCompleteDeclContext(SS, DC)) + return 0; + + SearchDC = DC; + // Look-up name inside 'foo::'. + LookupQualifiedName(Previous, DC); + + if (Previous.isAmbiguous()) + return 0; + + if (Previous.empty()) { + // Name lookup did not find anything. However, if the + // nested-name-specifier refers to the current instantiation, + // and that current instantiation has any dependent base + // classes, we might find something at instantiation time: treat + // this as a dependent elaborated-type-specifier. + // But this only makes any sense for reference-like lookups. + if (Previous.wasNotFoundInCurrentInstantiation() && + (TUK == TUK_Reference || TUK == TUK_Friend)) { + IsDependent = true; + return 0; + } + + // A tag 'foo::bar' must already exist. + Diag(NameLoc, diag::err_not_tag_in_scope) + << Kind << Name << DC << SS.getRange(); + Name = 0; + Invalid = true; + goto CreateNewDecl; + } + } else if (Name) { + // If this is a named struct, check to see if there was a previous forward + // declaration or definition. + // FIXME: We're looking into outer scopes here, even when we + // shouldn't be. Doing so can result in ambiguities that we + // shouldn't be diagnosing. + LookupName(Previous, S); + + if (Previous.isAmbiguous() && + (TUK == TUK_Definition || TUK == TUK_Declaration)) { + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *ND = F.next(); + if (ND->getDeclContext()->getRedeclContext() != SearchDC) + F.erase(); + } + F.done(); + } + + // Note: there used to be some attempt at recovery here. + if (Previous.isAmbiguous()) + return 0; + + if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) { + // FIXME: This makes sure that we ignore the contexts associated + // with C structs, unions, and enums when looking for a matching + // tag declaration or definition. See the similar lookup tweak + // in Sema::LookupName; is there a better way to deal with this? + while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC)) + SearchDC = SearchDC->getParent(); + } + } else if (S->isFunctionPrototypeScope()) { + // If this is an enum declaration in function prototype scope, set its + // initial context to the translation unit. + SearchDC = Context.getTranslationUnitDecl(); + } + + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl()); + // Just pretend that we didn't see the previous declaration. + Previous.clear(); + } + + if (getLangOptions().CPlusPlus && Name && DC && StdNamespace && + DC->Equals(getStdNamespace()) && Name->isStr("bad_alloc")) { + // This is a declaration of or a reference to "std::bad_alloc". + isStdBadAlloc = true; + + if (Previous.empty() && StdBadAlloc) { + // std::bad_alloc has been implicitly declared (but made invisible to + // name lookup). Fill in this implicit declaration as the previous + // declaration, so that the declarations get chained appropriately. + Previous.addDecl(getStdBadAlloc()); + } + } + + // If we didn't find a previous declaration, and this is a reference + // (or friend reference), move to the correct scope. In C++, we + // also need to do a redeclaration lookup there, just in case + // there's a shadow friend decl. + if (Name && Previous.empty() && + (TUK == TUK_Reference || TUK == TUK_Friend)) { + if (Invalid) goto CreateNewDecl; + assert(SS.isEmpty()); + + if (TUK == TUK_Reference) { + // C++ [basic.scope.pdecl]p5: + // -- for an elaborated-type-specifier of the form + // + // class-key identifier + // + // if the elaborated-type-specifier is used in the + // decl-specifier-seq or parameter-declaration-clause of a + // function defined in namespace scope, the identifier is + // declared as a class-name in the namespace that contains + // the declaration; otherwise, except as a friend + // declaration, the identifier is declared in the smallest + // non-class, non-function-prototype scope that contains the + // declaration. + // + // C99 6.7.2.3p8 has a similar (but not identical!) provision for + // C structs and unions. + // + // It is an error in C++ to declare (rather than define) an enum + // type, including via an elaborated type specifier. We'll + // diagnose that later; for now, declare the enum in the same + // scope as we would have picked for any other tag type. + // + // GNU C also supports this behavior as part of its incomplete + // enum types extension, while GNU C++ does not. + // + // Find the context where we'll be declaring the tag. + // FIXME: We would like to maintain the current DeclContext as the + // lexical context, + while (SearchDC->isRecord() || SearchDC->isTransparentContext()) + SearchDC = SearchDC->getParent(); + + // Find the scope where we'll be declaring the tag. + while (S->isClassScope() || + (getLangOptions().CPlusPlus && + S->isFunctionPrototypeScope()) || + ((S->getFlags() & Scope::DeclScope) == 0) || + (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext())) + S = S->getParent(); + } else { + assert(TUK == TUK_Friend); + // C++ [namespace.memdef]p3: + // If a friend declaration in a non-local class first declares a + // class or function, the friend class or function is a member of + // the innermost enclosing namespace. + SearchDC = SearchDC->getEnclosingNamespaceContext(); + } + + // In C++, we need to do a redeclaration lookup to properly + // diagnose some problems. + if (getLangOptions().CPlusPlus) { + Previous.setRedeclarationKind(ForRedeclaration); + LookupQualifiedName(Previous, SearchDC); + } + } + + if (!Previous.empty()) { + NamedDecl *PrevDecl = (*Previous.begin())->getUnderlyingDecl(); + + // It's okay to have a tag decl in the same scope as a typedef + // which hides a tag decl in the same scope. Finding this + // insanity with a redeclaration lookup can only actually happen + // in C++. + // + // This is also okay for elaborated-type-specifiers, which is + // technically forbidden by the current standard but which is + // okay according to the likely resolution of an open issue; + // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 + if (getLangOptions().CPlusPlus) { + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) { + if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) { + TagDecl *Tag = TT->getDecl(); + if (Tag->getDeclName() == Name && + Tag->getDeclContext()->getRedeclContext() + ->Equals(TD->getDeclContext()->getRedeclContext())) { + PrevDecl = Tag; + Previous.clear(); + Previous.addDecl(Tag); + Previous.resolveKind(); + } + } + } + } + + if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { + // If this is a use of a previous tag, or if the tag is already declared + // in the same scope (so that the definition/declaration completes or + // rementions the tag), reuse the decl. + if (TUK == TUK_Reference || TUK == TUK_Friend || + isDeclInScope(PrevDecl, SearchDC, S, isExplicitSpecialization)) { + // Make sure that this wasn't declared as an enum and now used as a + // struct or something similar. + if (!isAcceptableTagRedeclaration(PrevTagDecl, Kind, + TUK == TUK_Definition, KWLoc, + *Name)) { + bool SafeToContinue + = (PrevTagDecl->getTagKind() != TTK_Enum && + Kind != TTK_Enum); + if (SafeToContinue) + Diag(KWLoc, diag::err_use_with_wrong_tag) + << Name + << FixItHint::CreateReplacement(SourceRange(KWLoc), + PrevTagDecl->getKindName()); + else + Diag(KWLoc, diag::err_use_with_wrong_tag) << Name; + Diag(PrevTagDecl->getLocation(), diag::note_previous_use); + + if (SafeToContinue) + Kind = PrevTagDecl->getTagKind(); + else { + // Recover by making this an anonymous redefinition. + Name = 0; + Previous.clear(); + Invalid = true; + } + } + + if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) { + const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl); + + // All conflicts with previous declarations are recovered by + // returning the previous declaration. + if (ScopedEnum != PrevEnum->isScoped()) { + Diag(KWLoc, diag::err_enum_redeclare_scoped_mismatch) + << PrevEnum->isScoped(); + Diag(PrevTagDecl->getLocation(), diag::note_previous_use); + return PrevTagDecl; + } + else if (EnumUnderlying && PrevEnum->isFixed()) { + QualType T; + if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>()) + T = TI->getType(); + else + T = QualType(EnumUnderlying.get<const Type*>(), 0); + + if (!Context.hasSameUnqualifiedType(T, PrevEnum->getIntegerType())) { + Diag(NameLoc.isValid() ? NameLoc : KWLoc, + diag::err_enum_redeclare_type_mismatch) + << T + << PrevEnum->getIntegerType(); + Diag(PrevTagDecl->getLocation(), diag::note_previous_use); + return PrevTagDecl; + } + } + else if (!EnumUnderlying.isNull() != PrevEnum->isFixed()) { + Diag(KWLoc, diag::err_enum_redeclare_fixed_mismatch) + << PrevEnum->isFixed(); + Diag(PrevTagDecl->getLocation(), diag::note_previous_use); + return PrevTagDecl; + } + } + + if (!Invalid) { + // If this is a use, just return the declaration we found. + + // FIXME: In the future, return a variant or some other clue + // for the consumer of this Decl to know it doesn't own it. + // For our current ASTs this shouldn't be a problem, but will + // need to be changed with DeclGroups. + if ((TUK == TUK_Reference && (!PrevTagDecl->getFriendObjectKind() || + getLangOptions().Microsoft)) || TUK == TUK_Friend) + return PrevTagDecl; + + // Diagnose attempts to redefine a tag. + if (TUK == TUK_Definition) { + if (TagDecl *Def = PrevTagDecl->getDefinition()) { + // If we're defining a specialization and the previous definition + // is from an implicit instantiation, don't emit an error + // here; we'll catch this in the general case below. + if (!isExplicitSpecialization || + !isa<CXXRecordDecl>(Def) || + cast<CXXRecordDecl>(Def)->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) { + Diag(NameLoc, diag::err_redefinition) << Name; + Diag(Def->getLocation(), diag::note_previous_definition); + // If this is a redefinition, recover by making this + // struct be anonymous, which will make any later + // references get the previous definition. + Name = 0; + Previous.clear(); + Invalid = true; + } + } else { + // If the type is currently being defined, complain + // about a nested redefinition. + const TagType *Tag + = cast<TagType>(Context.getTagDeclType(PrevTagDecl)); + if (Tag->isBeingDefined()) { + Diag(NameLoc, diag::err_nested_redefinition) << Name; + Diag(PrevTagDecl->getLocation(), + diag::note_previous_definition); + Name = 0; + Previous.clear(); + Invalid = true; + } + } + + // Okay, this is definition of a previously declared or referenced + // tag PrevDecl. We're going to create a new Decl for it. + } + } + // If we get here we have (another) forward declaration or we + // have a definition. Just create a new decl. + + } else { + // If we get here, this is a definition of a new tag type in a nested + // scope, e.g. "struct foo; void bar() { struct foo; }", just create a + // new decl/type. We set PrevDecl to NULL so that the entities + // have distinct types. + Previous.clear(); + } + // If we get here, we're going to create a new Decl. If PrevDecl + // is non-NULL, it's a definition of the tag declared by + // PrevDecl. If it's NULL, we have a new definition. + + + // Otherwise, PrevDecl is not a tag, but was found with tag + // lookup. This is only actually possible in C++, where a few + // things like templates still live in the tag namespace. + } else { + assert(getLangOptions().CPlusPlus); + + // Use a better diagnostic if an elaborated-type-specifier + // found the wrong kind of type on the first + // (non-redeclaration) lookup. + if ((TUK == TUK_Reference || TUK == TUK_Friend) && + !Previous.isForRedeclaration()) { + unsigned Kind = 0; + if (isa<TypedefDecl>(PrevDecl)) Kind = 1; + else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3; + Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind; + Diag(PrevDecl->getLocation(), diag::note_declared_at); + Invalid = true; + + // Otherwise, only diagnose if the declaration is in scope. + } else if (!isDeclInScope(PrevDecl, SearchDC, S, + isExplicitSpecialization)) { + // do nothing + + // Diagnose implicit declarations introduced by elaborated types. + } else if (TUK == TUK_Reference || TUK == TUK_Friend) { + unsigned Kind = 0; + if (isa<TypedefDecl>(PrevDecl)) Kind = 1; + else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 3; + Diag(NameLoc, diag::err_tag_reference_conflict) << Kind; + Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; + Invalid = true; + + // Otherwise it's a declaration. Call out a particularly common + // case here. + } else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) { + unsigned Kind = 0; + if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1; + Diag(NameLoc, diag::err_tag_definition_of_typedef) + << Name << Kind << TND->getUnderlyingType(); + Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; + Invalid = true; + + // Otherwise, diagnose. + } else { + // The tag name clashes with something else in the target scope, + // issue an error and recover by making this tag be anonymous. + Diag(NameLoc, diag::err_redefinition_different_kind) << Name; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + Name = 0; + Invalid = true; + } + + // The existing declaration isn't relevant to us; we're in a + // new scope, so clear out the previous declaration. + Previous.clear(); + } + } + +CreateNewDecl: + + TagDecl *PrevDecl = 0; + if (Previous.isSingleResult()) + PrevDecl = cast<TagDecl>(Previous.getFoundDecl()); + + // If there is an identifier, use the location of the identifier as the + // location of the decl, otherwise use the location of the struct/union + // keyword. + SourceLocation Loc = NameLoc.isValid() ? NameLoc : KWLoc; + + // Otherwise, create a new declaration. If there is a previous + // declaration of the same entity, the two will be linked via + // PrevDecl. + TagDecl *New; + + bool IsForwardReference = false; + if (Kind == TTK_Enum) { + // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: + // enum X { A, B, C } D; D should chain to X. + New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, + cast_or_null<EnumDecl>(PrevDecl), ScopedEnum, + ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); + // If this is an undefined enum, warn. + if (TUK != TUK_Definition && !Invalid) { + TagDecl *Def; + if (getLangOptions().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) { + // C++0x: 7.2p2: opaque-enum-declaration. + // Conflicts are diagnosed above. Do nothing. + } + else if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) { + Diag(Loc, diag::ext_forward_ref_enum_def) + << New; + Diag(Def->getLocation(), diag::note_previous_definition); + } else { + unsigned DiagID = diag::ext_forward_ref_enum; + if (getLangOptions().Microsoft) + DiagID = diag::ext_ms_forward_ref_enum; + else if (getLangOptions().CPlusPlus) + DiagID = diag::err_forward_ref_enum; + Diag(Loc, DiagID); + + // If this is a forward-declared reference to an enumeration, make a + // note of it; we won't actually be introducing the declaration into + // the declaration context. + if (TUK == TUK_Reference) + IsForwardReference = true; + } + } + + if (EnumUnderlying) { + EnumDecl *ED = cast<EnumDecl>(New); + if (TypeSourceInfo *TI = EnumUnderlying.dyn_cast<TypeSourceInfo*>()) + ED->setIntegerTypeSourceInfo(TI); + else + ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0)); + ED->setPromotionType(ED->getIntegerType()); + } + + } else { + // struct/union/class + + // FIXME: Tag decls should be chained to any simultaneous vardecls, e.g.: + // struct X { int A; } D; D should chain to X. + if (getLangOptions().CPlusPlus) { + // FIXME: Look for a way to use RecordDecl for simple structs. + New = CXXRecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null<CXXRecordDecl>(PrevDecl)); + + if (isStdBadAlloc && (!StdBadAlloc || getStdBadAlloc()->isImplicit())) + StdBadAlloc = cast<CXXRecordDecl>(New); + } else + New = RecordDecl::Create(Context, Kind, SearchDC, KWLoc, Loc, Name, + cast_or_null<RecordDecl>(PrevDecl)); + } + + // Maybe add qualifier info. + if (SS.isNotEmpty()) { + if (SS.isSet()) { + New->setQualifierInfo(SS.getWithLocInContext(Context)); + if (TemplateParameterLists.size() > 0) { + New->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size(), + (TemplateParameterList**) TemplateParameterLists.release()); + } + } + else + Invalid = true; + } + + if (RecordDecl *RD = dyn_cast<RecordDecl>(New)) { + // Add alignment attributes if necessary; these attributes are checked when + // the ASTContext lays out the structure. + // + // It is important for implementing the correct semantics that this + // happen here (in act on tag decl). The #pragma pack stack is + // maintained as a result of parser callbacks which can occur at + // many points during the parsing of a struct declaration (because + // the #pragma tokens are effectively skipped over during the + // parsing of the struct). + AddAlignmentAttributesForRecord(RD); + + AddMsStructLayoutForRecord(RD); + } + + // If this is a specialization of a member class (of a class template), + // check the specialization. + if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous)) + Invalid = true; + + if (Invalid) + New->setInvalidDecl(); + + if (Attr) + ProcessDeclAttributeList(S, New, Attr); + + // If we're declaring or defining a tag in function prototype scope + // in C, note that this type can only be used within the function. + if (Name && S->isFunctionPrototypeScope() && !getLangOptions().CPlusPlus) + Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New); + + // Set the lexical context. If the tag has a C++ scope specifier, the + // lexical context will be different from the semantic context. + New->setLexicalDeclContext(CurContext); + + // Mark this as a friend decl if applicable. + // In Microsoft mode, a friend declaration also acts as a forward + // declaration so we always pass true to setObjectOfFriendDecl to make + // the tag name visible. + if (TUK == TUK_Friend) + New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() || + getLangOptions().Microsoft); + + // Set the access specifier. + if (!Invalid && SearchDC->isRecord()) + SetMemberAccessSpecifier(New, PrevDecl, AS); + + if (TUK == TUK_Definition) + New->startDefinition(); + + // If this has an identifier, add it to the scope stack. + if (TUK == TUK_Friend) { + // We might be replacing an existing declaration in the lookup tables; + // if so, borrow its access specifier. + if (PrevDecl) + New->setAccess(PrevDecl->getAccess()); + + DeclContext *DC = New->getDeclContext()->getRedeclContext(); + DC->makeDeclVisibleInContext(New, /* Recoverable = */ false); + if (Name) // can be null along some error paths + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false); + } else if (Name) { + S = getNonFieldDeclScope(S); + PushOnScopeChains(New, S, !IsForwardReference); + if (IsForwardReference) + SearchDC->makeDeclVisibleInContext(New, /* Recoverable = */ false); + + } else { + CurContext->addDecl(New); + } + + // If this is the C FILE type, notify the AST context. + if (IdentifierInfo *II = New->getIdentifier()) + if (!New->isInvalidDecl() && + New->getDeclContext()->getRedeclContext()->isTranslationUnit() && + II->isStr("FILE")) + Context.setFILEDecl(New); + + OwnedDecl = true; + return New; +} + +void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { + AdjustDeclIfTemplate(TagD); + TagDecl *Tag = cast<TagDecl>(TagD); + + // Enter the tag context. + PushDeclContext(S, Tag); +} + +void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD, + SourceLocation FinalLoc, + SourceLocation LBraceLoc) { + AdjustDeclIfTemplate(TagD); + CXXRecordDecl *Record = cast<CXXRecordDecl>(TagD); + + FieldCollector->StartClass(); + + if (!Record->getIdentifier()) + return; + + if (FinalLoc.isValid()) + Record->addAttr(new (Context) FinalAttr(FinalLoc, Context)); + + // C++ [class]p2: + // [...] The class-name is also inserted into the scope of the + // class itself; this is known as the injected-class-name. For + // purposes of access checking, the injected-class-name is treated + // as if it were a public member name. + CXXRecordDecl *InjectedClassName + = CXXRecordDecl::Create(Context, Record->getTagKind(), CurContext, + Record->getLocStart(), Record->getLocation(), + Record->getIdentifier(), + /*PrevDecl=*/0, + /*DelayTypeCreation=*/true); + Context.getTypeDeclType(InjectedClassName, Record); + InjectedClassName->setImplicit(); + InjectedClassName->setAccess(AS_public); + if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) + InjectedClassName->setDescribedClassTemplate(Template); + PushOnScopeChains(InjectedClassName, S); + assert(InjectedClassName->isInjectedClassName() && + "Broken injected-class-name"); +} + +void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, + SourceLocation RBraceLoc) { + AdjustDeclIfTemplate(TagD); + TagDecl *Tag = cast<TagDecl>(TagD); + Tag->setRBraceLoc(RBraceLoc); + + if (isa<CXXRecordDecl>(Tag)) + FieldCollector->FinishClass(); + + // Exit this scope of this tag's definition. + PopDeclContext(); + + // Notify the consumer that we've defined a tag. + Consumer.HandleTagDeclDefinition(Tag); +} + +void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) { + AdjustDeclIfTemplate(TagD); + TagDecl *Tag = cast<TagDecl>(TagD); + Tag->setInvalidDecl(); + + // We're undoing ActOnTagStartDefinition here, not + // ActOnStartCXXMemberDeclarations, so we don't have to mess with + // the FieldCollector. + + PopDeclContext(); +} + +// Note that FieldName may be null for anonymous bitfields. +bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, + QualType FieldTy, const Expr *BitWidth, + bool *ZeroWidth) { + // Default to true; that shouldn't confuse checks for emptiness + if (ZeroWidth) + *ZeroWidth = true; + + // C99 6.7.2.1p4 - verify the field type. + // C++ 9.6p3: A bit-field shall have integral or enumeration type. + if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { + // Handle incomplete types with specific error. + if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) + return true; + if (FieldName) + return Diag(FieldLoc, diag::err_not_integral_type_bitfield) + << FieldName << FieldTy << BitWidth->getSourceRange(); + return Diag(FieldLoc, diag::err_not_integral_type_anon_bitfield) + << FieldTy << BitWidth->getSourceRange(); + } else if (DiagnoseUnexpandedParameterPack(const_cast<Expr *>(BitWidth), + UPPC_BitFieldWidth)) + return true; + + // If the bit-width is type- or value-dependent, don't try to check + // it now. + if (BitWidth->isValueDependent() || BitWidth->isTypeDependent()) + return false; + + llvm::APSInt Value; + if (VerifyIntegerConstantExpression(BitWidth, &Value)) + return true; + + if (Value != 0 && ZeroWidth) + *ZeroWidth = false; + + // Zero-width bitfield is ok for anonymous field. + if (Value == 0 && FieldName) + return Diag(FieldLoc, diag::err_bitfield_has_zero_width) << FieldName; + + if (Value.isSigned() && Value.isNegative()) { + if (FieldName) + return Diag(FieldLoc, diag::err_bitfield_has_negative_width) + << FieldName << Value.toString(10); + return Diag(FieldLoc, diag::err_anon_bitfield_has_negative_width) + << Value.toString(10); + } + + if (!FieldTy->isDependentType()) { + uint64_t TypeSize = Context.getTypeSize(FieldTy); + if (Value.getZExtValue() > TypeSize) { + if (!getLangOptions().CPlusPlus) { + if (FieldName) + return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_size) + << FieldName << (unsigned)Value.getZExtValue() + << (unsigned)TypeSize; + + return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_size) + << (unsigned)Value.getZExtValue() << (unsigned)TypeSize; + } + + if (FieldName) + Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_size) + << FieldName << (unsigned)Value.getZExtValue() + << (unsigned)TypeSize; + else + Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_size) + << (unsigned)Value.getZExtValue() << (unsigned)TypeSize; + } + } + + return false; +} + +/// ActOnField - Each field of a C struct/union is passed into this in order +/// to create a FieldDecl object for it. +Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, + Declarator &D, ExprTy *BitfieldWidth) { + FieldDecl *Res = HandleField(S, cast_or_null<RecordDecl>(TagD), + DeclStart, D, static_cast<Expr*>(BitfieldWidth), + /*HasInit=*/false, AS_public); + return Res; +} + +/// HandleField - Analyze a field of a C struct or a C++ data member. +/// +FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, + SourceLocation DeclStart, + Declarator &D, Expr *BitWidth, bool HasInit, + AccessSpecifier AS) { + IdentifierInfo *II = D.getIdentifier(); + SourceLocation Loc = DeclStart; + if (II) Loc = D.getIdentifierLoc(); + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + if (getLangOptions().CPlusPlus) { + CheckExtraCXXDefaultArguments(D); + + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_DataMemberType)) { + D.setInvalidType(); + T = Context.IntTy; + TInfo = Context.getTrivialTypeSourceInfo(T, Loc); + } + } + + DiagnoseFunctionSpecifiers(D); + + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + + // Check to see if this name was declared as a member previously + LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); + LookupName(Previous, S); + assert((Previous.empty() || Previous.isOverloadedResult() || + Previous.isSingleResult()) + && "Lookup of member name should be either overloaded, single or null"); + + // If the name is overloaded then get any declaration else get the single result + NamedDecl *PrevDecl = Previous.isOverloadedResult() ? + Previous.getRepresentativeDecl() : Previous.getAsSingle<NamedDecl>(); + + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + + if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) + PrevDecl = 0; + + bool Mutable + = (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_mutable); + SourceLocation TSSL = D.getSourceRange().getBegin(); + FieldDecl *NewFD + = CheckFieldDecl(II, T, TInfo, Record, Loc, Mutable, BitWidth, HasInit, + TSSL, AS, PrevDecl, &D); + + if (NewFD->isInvalidDecl()) + Record->setInvalidDecl(); + + if (NewFD->isInvalidDecl() && PrevDecl) { + // Don't introduce NewFD into scope; there's already something + // with the same name in the same scope. + } else if (II) { + PushOnScopeChains(NewFD, S); + } else + Record->addDecl(NewFD); + + return NewFD; +} + +/// \brief Build a new FieldDecl and check its well-formedness. +/// +/// This routine builds a new FieldDecl given the fields name, type, +/// record, etc. \p PrevDecl should refer to any previous declaration +/// with the same name and in the same scope as the field to be +/// created. +/// +/// \returns a new FieldDecl. +/// +/// \todo The Declarator argument is a hack. It will be removed once +FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, + TypeSourceInfo *TInfo, + RecordDecl *Record, SourceLocation Loc, + bool Mutable, Expr *BitWidth, bool HasInit, + SourceLocation TSSL, + AccessSpecifier AS, NamedDecl *PrevDecl, + Declarator *D) { + IdentifierInfo *II = Name.getAsIdentifierInfo(); + bool InvalidDecl = false; + if (D) InvalidDecl = D->isInvalidType(); + + // If we receive a broken type, recover by assuming 'int' and + // marking this declaration as invalid. + if (T.isNull()) { + InvalidDecl = true; + T = Context.IntTy; + } + + QualType EltTy = Context.getBaseElementType(T); + if (!EltTy->isDependentType() && + RequireCompleteType(Loc, EltTy, diag::err_field_incomplete)) { + // Fields of incomplete type force their record to be invalid. + Record->setInvalidDecl(); + InvalidDecl = true; + } + + // C99 6.7.2.1p8: A member of a structure or union may have any type other + // than a variably modified type. + if (!InvalidDecl && T->isVariablyModifiedType()) { + bool SizeIsNegative; + llvm::APSInt Oversized; + QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context, + SizeIsNegative, + Oversized); + if (!FixedTy.isNull()) { + Diag(Loc, diag::warn_illegal_constant_array_size); + T = FixedTy; + } else { + if (SizeIsNegative) + Diag(Loc, diag::err_typecheck_negative_array_size); + else if (Oversized.getBoolValue()) + Diag(Loc, diag::err_array_too_large) + << Oversized.toString(10); + else + Diag(Loc, diag::err_typecheck_field_variable_size); + InvalidDecl = true; + } + } + + // Fields can not have abstract class types + if (!InvalidDecl && RequireNonAbstractType(Loc, T, + diag::err_abstract_type_in_decl, + AbstractFieldType)) + InvalidDecl = true; + + bool ZeroWidth = false; + // If this is declared as a bit-field, check the bit-field. + if (!InvalidDecl && BitWidth && + VerifyBitField(Loc, II, T, BitWidth, &ZeroWidth)) { + InvalidDecl = true; + BitWidth = 0; + ZeroWidth = false; + } + + // Check that 'mutable' is consistent with the type of the declaration. + if (!InvalidDecl && Mutable) { + unsigned DiagID = 0; + if (T->isReferenceType()) + DiagID = diag::err_mutable_reference; + else if (T.isConstQualified()) + DiagID = diag::err_mutable_const; + + if (DiagID) { + SourceLocation ErrLoc = Loc; + if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid()) + ErrLoc = D->getDeclSpec().getStorageClassSpecLoc(); + Diag(ErrLoc, DiagID); + Mutable = false; + InvalidDecl = true; + } + } + + FieldDecl *NewFD = FieldDecl::Create(Context, Record, TSSL, Loc, II, T, TInfo, + BitWidth, Mutable, HasInit); + if (InvalidDecl) + NewFD->setInvalidDecl(); + + if (PrevDecl && !isa<TagDecl>(PrevDecl)) { + Diag(Loc, diag::err_duplicate_member) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + NewFD->setInvalidDecl(); + } + + if (!InvalidDecl && getLangOptions().CPlusPlus) { + if (Record->isUnion()) { + if (const RecordType *RT = EltTy->getAs<RecordType>()) { + CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (RDecl->getDefinition()) { + // C++ [class.union]p1: An object of a class with a non-trivial + // constructor, a non-trivial copy constructor, a non-trivial + // destructor, or a non-trivial copy assignment operator + // cannot be a member of a union, nor can an array of such + // objects. + if (!getLangOptions().CPlusPlus0x && CheckNontrivialField(NewFD)) + NewFD->setInvalidDecl(); + } + } + + // C++ [class.union]p1: If a union contains a member of reference type, + // the program is ill-formed. + if (EltTy->isReferenceType()) { + Diag(NewFD->getLocation(), diag::err_union_member_of_reference_type) + << NewFD->getDeclName() << EltTy; + NewFD->setInvalidDecl(); + } + } + } + + // FIXME: We need to pass in the attributes given an AST + // representation, not a parser representation. + if (D) + // FIXME: What to pass instead of TUScope? + ProcessDeclAttributes(TUScope, NewFD, *D); + + if (T.isObjCGCWeak()) + Diag(Loc, diag::warn_attribute_weak_on_field); + + NewFD->setAccess(AS); + return NewFD; +} + +bool Sema::CheckNontrivialField(FieldDecl *FD) { + assert(FD); + assert(getLangOptions().CPlusPlus && "valid check only for C++"); + + if (FD->isInvalidDecl()) + return true; + + QualType EltTy = Context.getBaseElementType(FD->getType()); + if (const RecordType *RT = EltTy->getAs<RecordType>()) { + CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (RDecl->getDefinition()) { + // We check for copy constructors before constructors + // because otherwise we'll never get complaints about + // copy constructors. + + CXXSpecialMember member = CXXInvalid; + if (!RDecl->hasTrivialCopyConstructor()) + member = CXXCopyConstructor; + else if (!RDecl->hasTrivialDefaultConstructor()) + member = CXXDefaultConstructor; + else if (!RDecl->hasTrivialCopyAssignment()) + member = CXXCopyAssignment; + else if (!RDecl->hasTrivialDestructor()) + member = CXXDestructor; + + if (member != CXXInvalid) { + Diag(FD->getLocation(), diag::err_illegal_union_or_anon_struct_member) + << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; + DiagnoseNontrivial(RT, member); + return true; + } + } + } + + return false; +} + +/// DiagnoseNontrivial - Given that a class has a non-trivial +/// special member, figure out why. +void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { + QualType QT(T, 0U); + CXXRecordDecl* RD = cast<CXXRecordDecl>(T->getDecl()); + + // Check whether the member was user-declared. + switch (member) { + case CXXInvalid: + break; + + case CXXDefaultConstructor: + if (RD->hasUserDeclaredConstructor()) { + typedef CXXRecordDecl::ctor_iterator ctor_iter; + for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){ + const FunctionDecl *body = 0; + ci->hasBody(body); + if (!body || !cast<CXXConstructorDecl>(body)->isImplicitlyDefined()) { + SourceLocation CtorLoc = ci->getLocation(); + Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + } + + assert(0 && "found no user-declared constructors"); + return; + } + break; + + case CXXCopyConstructor: + if (RD->hasUserDeclaredCopyConstructor()) { + SourceLocation CtorLoc = + RD->getCopyConstructor(0)->getLocation(); + Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXMoveConstructor: + if (RD->hasUserDeclaredMoveConstructor()) { + SourceLocation CtorLoc = RD->getMoveConstructor()->getLocation(); + Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXCopyAssignment: + if (RD->hasUserDeclaredCopyAssignment()) { + // FIXME: this should use the location of the copy + // assignment, not the type. + SourceLocation TyLoc = RD->getSourceRange().getBegin(); + Diag(TyLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXMoveAssignment: + if (RD->hasUserDeclaredMoveAssignment()) { + SourceLocation AssignLoc = RD->getMoveAssignmentOperator()->getLocation(); + Diag(AssignLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + + case CXXDestructor: + if (RD->hasUserDeclaredDestructor()) { + SourceLocation DtorLoc = LookupDestructor(RD)->getLocation(); + Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member; + return; + } + break; + } + + typedef CXXRecordDecl::base_class_iterator base_iter; + + // Virtual bases and members inhibit trivial copying/construction, + // but not trivial destruction. + if (member != CXXDestructor) { + // Check for virtual bases. vbases includes indirect virtual bases, + // so we just iterate through the direct bases. + for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) + if (bi->isVirtual()) { + SourceLocation BaseLoc = bi->getSourceRange().getBegin(); + Diag(BaseLoc, diag::note_nontrivial_has_virtual) << QT << 1; + return; + } + + // Check for virtual methods. + typedef CXXRecordDecl::method_iterator meth_iter; + for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; + ++mi) { + if (mi->isVirtual()) { + SourceLocation MLoc = mi->getSourceRange().getBegin(); + Diag(MLoc, diag::note_nontrivial_has_virtual) << QT << 0; + return; + } + } + } + + bool (CXXRecordDecl::*hasTrivial)() const; + switch (member) { + case CXXDefaultConstructor: + hasTrivial = &CXXRecordDecl::hasTrivialDefaultConstructor; break; + case CXXCopyConstructor: + hasTrivial = &CXXRecordDecl::hasTrivialCopyConstructor; break; + case CXXCopyAssignment: + hasTrivial = &CXXRecordDecl::hasTrivialCopyAssignment; break; + case CXXDestructor: + hasTrivial = &CXXRecordDecl::hasTrivialDestructor; break; + default: + assert(0 && "unexpected special member"); return; + } + + // Check for nontrivial bases (and recurse). + for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) { + const RecordType *BaseRT = bi->getType()->getAs<RecordType>(); + assert(BaseRT && "Don't know how to handle dependent bases"); + CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl()); + if (!(BaseRecTy->*hasTrivial)()) { + SourceLocation BaseLoc = bi->getSourceRange().getBegin(); + Diag(BaseLoc, diag::note_nontrivial_has_nontrivial) << QT << 1 << member; + DiagnoseNontrivial(BaseRT, member); + return; + } + } + + // Check for nontrivial members (and recurse). + typedef RecordDecl::field_iterator field_iter; + for (field_iter fi = RD->field_begin(), fe = RD->field_end(); fi != fe; + ++fi) { + QualType EltTy = Context.getBaseElementType((*fi)->getType()); + if (const RecordType *EltRT = EltTy->getAs<RecordType>()) { + CXXRecordDecl* EltRD = cast<CXXRecordDecl>(EltRT->getDecl()); + + if (!(EltRD->*hasTrivial)()) { + SourceLocation FLoc = (*fi)->getLocation(); + Diag(FLoc, diag::note_nontrivial_has_nontrivial) << QT << 0 << member; + DiagnoseNontrivial(EltRT, member); + return; + } + } + } + + assert(0 && "found no explanation for non-trivial member"); +} + +/// TranslateIvarVisibility - Translate visibility from a token ID to an +/// AST enum value. +static ObjCIvarDecl::AccessControl +TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { + switch (ivarVisibility) { + default: assert(0 && "Unknown visitibility kind"); + case tok::objc_private: return ObjCIvarDecl::Private; + case tok::objc_public: return ObjCIvarDecl::Public; + case tok::objc_protected: return ObjCIvarDecl::Protected; + case tok::objc_package: return ObjCIvarDecl::Package; + } +} + +/// ActOnIvar - Each ivar field of an objective-c class is passed into this +/// in order to create an IvarDecl object for it. +Decl *Sema::ActOnIvar(Scope *S, + SourceLocation DeclStart, + Decl *IntfDecl, + Declarator &D, ExprTy *BitfieldWidth, + tok::ObjCKeywordKind Visibility) { + + IdentifierInfo *II = D.getIdentifier(); + Expr *BitWidth = (Expr*)BitfieldWidth; + SourceLocation Loc = DeclStart; + if (II) Loc = D.getIdentifierLoc(); + + // FIXME: Unnamed fields can be handled in various different ways, for + // example, unnamed unions inject all members into the struct namespace! + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + + if (BitWidth) { + // 6.7.2.1p3, 6.7.2.1p4 + if (VerifyBitField(Loc, II, T, BitWidth)) { + D.setInvalidType(); + BitWidth = 0; + } + } else { + // Not a bitfield. + + // validate II. + + } + if (T->isReferenceType()) { + Diag(Loc, diag::err_ivar_reference_type); + D.setInvalidType(); + } + // C99 6.7.2.1p8: A member of a structure or union may have any type other + // than a variably modified type. + else if (T->isVariablyModifiedType()) { + Diag(Loc, diag::err_typecheck_ivar_variable_size); + D.setInvalidType(); + } + + // Get the visibility (access control) for this ivar. + ObjCIvarDecl::AccessControl ac = + Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) + : ObjCIvarDecl::None; + // Must set ivar's DeclContext to its enclosing interface. + ObjCContainerDecl *EnclosingDecl = cast<ObjCContainerDecl>(IntfDecl); + ObjCContainerDecl *EnclosingContext; + if (ObjCImplementationDecl *IMPDecl = + dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { + if (!LangOpts.ObjCNonFragileABI2) { + // Case of ivar declared in an implementation. Context is that of its class. + EnclosingContext = IMPDecl->getClassInterface(); + assert(EnclosingContext && "Implementation has no class interface!"); + } + else + EnclosingContext = EnclosingDecl; + } else { + if (ObjCCategoryDecl *CDecl = + dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { + if (!LangOpts.ObjCNonFragileABI2 || !CDecl->IsClassExtension()) { + Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension(); + return 0; + } + } + EnclosingContext = EnclosingDecl; + } + + // Construct the decl. + ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, EnclosingContext, + DeclStart, Loc, II, T, + TInfo, ac, (Expr *)BitfieldWidth); + + if (II) { + NamedDecl *PrevDecl = LookupSingleName(S, II, Loc, LookupMemberName, + ForRedeclaration); + if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) + && !isa<TagDecl>(PrevDecl)) { + Diag(Loc, diag::err_duplicate_member) << II; + Diag(PrevDecl->getLocation(), diag::note_previous_declaration); + NewID->setInvalidDecl(); + } + } + + // Process attributes attached to the ivar. + ProcessDeclAttributes(S, NewID, D); + + if (D.isInvalidType()) + NewID->setInvalidDecl(); + + if (II) { + // FIXME: When interfaces are DeclContexts, we'll need to add + // these to the interface. + S->AddDecl(NewID); + IdResolver.AddDecl(NewID); + } + + return NewID; +} + +/// ActOnLastBitfield - This routine handles synthesized bitfields rules for +/// class and class extensions. For every class @interface and class +/// extension @interface, if the last ivar is a bitfield of any type, +/// then add an implicit `char :0` ivar to the end of that interface. +void Sema::ActOnLastBitfield(SourceLocation DeclLoc, Decl *EnclosingDecl, + llvm::SmallVectorImpl<Decl *> &AllIvarDecls) { + if (!LangOpts.ObjCNonFragileABI2 || AllIvarDecls.empty()) + return; + + Decl *ivarDecl = AllIvarDecls[AllIvarDecls.size()-1]; + ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(ivarDecl); + + if (!Ivar->isBitField()) + return; + uint64_t BitFieldSize = + Ivar->getBitWidth()->EvaluateAsInt(Context).getZExtValue(); + if (BitFieldSize == 0) + return; + ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl); + if (!ID) { + if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { + if (!CD->IsClassExtension()) + return; + } + // No need to add this to end of @implementation. + else + return; + } + // All conditions are met. Add a new bitfield to the tail end of ivars. + llvm::APInt Zero(Context.getTypeSize(Context.CharTy), 0); + Expr * BW = IntegerLiteral::Create(Context, Zero, Context.CharTy, DeclLoc); + + Ivar = ObjCIvarDecl::Create(Context, cast<ObjCContainerDecl>(EnclosingDecl), + DeclLoc, DeclLoc, 0, + Context.CharTy, + Context.CreateTypeSourceInfo(Context.CharTy), + ObjCIvarDecl::Private, BW, + true); + AllIvarDecls.push_back(Ivar); +} + +void Sema::ActOnFields(Scope* S, + SourceLocation RecLoc, Decl *EnclosingDecl, + Decl **Fields, unsigned NumFields, + SourceLocation LBrac, SourceLocation RBrac, + AttributeList *Attr) { + assert(EnclosingDecl && "missing record or interface decl"); + + // If the decl this is being inserted into is invalid, then it may be a + // redeclaration or some other bogus case. Don't try to add fields to it. + if (EnclosingDecl->isInvalidDecl()) { + // FIXME: Deallocate fields? + return; + } + + + // Verify that all the fields are okay. + unsigned NumNamedMembers = 0; + llvm::SmallVector<FieldDecl*, 32> RecFields; + + RecordDecl *Record = dyn_cast<RecordDecl>(EnclosingDecl); + for (unsigned i = 0; i != NumFields; ++i) { + FieldDecl *FD = cast<FieldDecl>(Fields[i]); + + // Get the type for the field. + const Type *FDTy = FD->getType().getTypePtr(); + + if (!FD->isAnonymousStructOrUnion()) { + // Remember all fields written by the user. + RecFields.push_back(FD); + } + + // If the field is already invalid for some reason, don't emit more + // diagnostics about it. + if (FD->isInvalidDecl()) { + EnclosingDecl->setInvalidDecl(); + continue; + } + + // C99 6.7.2.1p2: + // A structure or union shall not contain a member with + // incomplete or function type (hence, a structure shall not + // contain an instance of itself, but may contain a pointer to + // an instance of itself), except that the last member of a + // structure with more than one named member may have incomplete + // array type; such a structure (and any union containing, + // possibly recursively, a member that is such a structure) + // shall not be a member of a structure or an element of an + // array. + if (FDTy->isFunctionType()) { + // Field declared as a function. + Diag(FD->getLocation(), diag::err_field_declared_as_function) + << FD->getDeclName(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } else if (FDTy->isIncompleteArrayType() && Record && + ((i == NumFields - 1 && !Record->isUnion()) || + ((getLangOptions().Microsoft || getLangOptions().CPlusPlus) && + (i == NumFields - 1 || Record->isUnion())))) { + // Flexible array member. + // Microsoft and g++ is more permissive regarding flexible array. + // It will accept flexible array in union and also + // as the sole element of a struct/class. + if (getLangOptions().Microsoft) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_ms) + << FD->getDeclName(); + else if (NumFields == 1) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_ms) + << FD->getDeclName() << Record->getTagKind(); + } else if (getLangOptions().CPlusPlus) { + if (Record->isUnion()) + Diag(FD->getLocation(), diag::ext_flexible_array_union_gnu) + << FD->getDeclName(); + else if (NumFields == 1) + Diag(FD->getLocation(), diag::ext_flexible_array_empty_aggregate_gnu) + << FD->getDeclName() << Record->getTagKind(); + } else if (NumNamedMembers < 1) { + Diag(FD->getLocation(), diag::err_flexible_array_empty_struct) + << FD->getDeclName(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + if (!FD->getType()->isDependentType() && + !Context.getBaseElementType(FD->getType())->isPODType()) { + Diag(FD->getLocation(), diag::err_flexible_array_has_nonpod_type) + << FD->getDeclName() << FD->getType(); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } + // Okay, we have a legal flexible array member at the end of the struct. + if (Record) + Record->setHasFlexibleArrayMember(true); + } else if (!FDTy->isDependentType() && + RequireCompleteType(FD->getLocation(), FD->getType(), + diag::err_field_incomplete)) { + // Incomplete type + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } else if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) { + if (FDTTy->getDecl()->hasFlexibleArrayMember()) { + // If this is a member of a union, then entire union becomes "flexible". + if (Record && Record->isUnion()) { + Record->setHasFlexibleArrayMember(true); + } else { + // If this is a struct/class and this is not the last element, reject + // it. Note that GCC supports variable sized arrays in the middle of + // structures. + if (i != NumFields-1) + Diag(FD->getLocation(), diag::ext_variable_sized_type_in_struct) + << FD->getDeclName() << FD->getType(); + else { + // We support flexible arrays at the end of structs in + // other structs as an extension. + Diag(FD->getLocation(), diag::ext_flexible_array_in_struct) + << FD->getDeclName(); + if (Record) + Record->setHasFlexibleArrayMember(true); + } + } + } + if (Record && FDTTy->getDecl()->hasObjectMember()) + Record->setHasObjectMember(true); + } else if (FDTy->isObjCObjectType()) { + /// A field cannot be an Objective-c object + Diag(FD->getLocation(), diag::err_statically_allocated_object); + FD->setInvalidDecl(); + EnclosingDecl->setInvalidDecl(); + continue; + } else if (getLangOptions().ObjC1 && + getLangOptions().getGCMode() != LangOptions::NonGC && + Record && + (FD->getType()->isObjCObjectPointerType() || + FD->getType().isObjCGCStrong())) + Record->setHasObjectMember(true); + else if (Context.getAsArrayType(FD->getType())) { + QualType BaseType = Context.getBaseElementType(FD->getType()); + if (Record && BaseType->isRecordType() && + BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()) + Record->setHasObjectMember(true); + } + // Keep track of the number of named members. + if (FD->getIdentifier()) + ++NumNamedMembers; + } + + // Okay, we successfully defined 'Record'. + if (Record) { + bool Completed = false; + if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Record)) { + if (!CXXRecord->isInvalidDecl()) { + // Set access bits correctly on the directly-declared conversions. + UnresolvedSetImpl *Convs = CXXRecord->getConversionFunctions(); + for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end(); + I != E; ++I) + Convs->setAccess(I, (*I)->getAccess()); + + if (!CXXRecord->isDependentType()) { + // Adjust user-defined destructor exception spec. + if (getLangOptions().CPlusPlus0x && + CXXRecord->hasUserDeclaredDestructor()) + AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor()); + + // Add any implicitly-declared members to this class. + AddImplicitlyDeclaredMembersToClass(CXXRecord); + + // If we have virtual base classes, we may end up finding multiple + // final overriders for a given virtual function. Check for this + // problem now. + if (CXXRecord->getNumVBases()) { + CXXFinalOverriderMap FinalOverriders; + CXXRecord->getFinalOverriders(FinalOverriders); + + for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), + MEnd = FinalOverriders.end(); + M != MEnd; ++M) { + for (OverridingMethods::iterator SO = M->second.begin(), + SOEnd = M->second.end(); + SO != SOEnd; ++SO) { + assert(SO->second.size() > 0 && + "Virtual function without overridding functions?"); + if (SO->second.size() == 1) + continue; + + // C++ [class.virtual]p2: + // In a derived class, if a virtual member function of a base + // class subobject has more than one final overrider the + // program is ill-formed. + Diag(Record->getLocation(), diag::err_multiple_final_overriders) + << (NamedDecl *)M->first << Record; + Diag(M->first->getLocation(), + diag::note_overridden_virtual_function); + for (OverridingMethods::overriding_iterator + OM = SO->second.begin(), + OMEnd = SO->second.end(); + OM != OMEnd; ++OM) + Diag(OM->Method->getLocation(), diag::note_final_overrider) + << (NamedDecl *)M->first << OM->Method->getParent(); + + Record->setInvalidDecl(); + } + } + CXXRecord->completeDefinition(&FinalOverriders); + Completed = true; + } + } + } + } + + if (!Completed) + Record->completeDefinition(); + + // Now that the record is complete, do any delayed exception spec checks + // we were missing. + while (!DelayedDestructorExceptionSpecChecks.empty()) { + const CXXDestructorDecl *Dtor = + DelayedDestructorExceptionSpecChecks.back().first; + if (Dtor->getParent() != Record) + break; + + assert(!Dtor->getParent()->isDependentType() && + "Should not ever add destructors of templates into the list."); + CheckOverridingFunctionExceptionSpec(Dtor, + DelayedDestructorExceptionSpecChecks.back().second); + DelayedDestructorExceptionSpecChecks.pop_back(); + } + + } else { + ObjCIvarDecl **ClsFields = + reinterpret_cast<ObjCIvarDecl**>(RecFields.data()); + if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(EnclosingDecl)) { + ID->setLocEnd(RBrac); + // Add ivar's to class's DeclContext. + for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + ClsFields[i]->setLexicalDeclContext(ID); + ID->addDecl(ClsFields[i]); + } + // Must enforce the rule that ivars in the base classes may not be + // duplicates. + if (ID->getSuperClass()) + DiagnoseDuplicateIvars(ID, ID->getSuperClass()); + } else if (ObjCImplementationDecl *IMPDecl = + dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { + assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); + for (unsigned I = 0, N = RecFields.size(); I != N; ++I) + // Ivar declared in @implementation never belongs to the implementation. + // Only it is in implementation's lexical context. + ClsFields[I]->setLexicalDeclContext(IMPDecl); + CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); + } else if (ObjCCategoryDecl *CDecl = + dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { + // case of ivars in class extension; all other cases have been + // reported as errors elsewhere. + // FIXME. Class extension does not have a LocEnd field. + // CDecl->setLocEnd(RBrac); + // Add ivar's to class extension's DeclContext. + for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + ClsFields[i]->setLexicalDeclContext(CDecl); + CDecl->addDecl(ClsFields[i]); + } + } + } + + if (Attr) + ProcessDeclAttributeList(S, Record, Attr); + + // If there's a #pragma GCC visibility in scope, and this isn't a subclass, + // set the visibility of this record. + if (Record && !Record->getDeclContext()->isRecord()) + AddPushedVisibilityAttribute(Record); +} + +/// \brief Determine whether the given integral value is representable within +/// the given type T. +static bool isRepresentableIntegerValue(ASTContext &Context, + llvm::APSInt &Value, + QualType T) { + assert(T->isIntegralType(Context) && "Integral type required!"); + unsigned BitWidth = Context.getIntWidth(T); + + if (Value.isUnsigned() || Value.isNonNegative()) { + if (T->isSignedIntegerOrEnumerationType()) + --BitWidth; + return Value.getActiveBits() <= BitWidth; + } + return Value.getMinSignedBits() <= BitWidth; +} + +// \brief Given an integral type, return the next larger integral type +// (or a NULL type of no such type exists). +static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { + // FIXME: Int128/UInt128 support, which also needs to be introduced into + // enum checking below. + assert(T->isIntegralType(Context) && "Integral type required!"); + const unsigned NumTypes = 4; + QualType SignedIntegralTypes[NumTypes] = { + Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy + }; + QualType UnsignedIntegralTypes[NumTypes] = { + Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy, + Context.UnsignedLongLongTy + }; + + unsigned BitWidth = Context.getTypeSize(T); + QualType *Types = T->isSignedIntegerOrEnumerationType()? SignedIntegralTypes + : UnsignedIntegralTypes; + for (unsigned I = 0; I != NumTypes; ++I) + if (Context.getTypeSize(Types[I]) > BitWidth) + return Types[I]; + + return QualType(); +} + +EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, + EnumConstantDecl *LastEnumConst, + SourceLocation IdLoc, + IdentifierInfo *Id, + Expr *Val) { + unsigned IntWidth = Context.Target.getIntWidth(); + llvm::APSInt EnumVal(IntWidth); + QualType EltTy; + + if (Val && DiagnoseUnexpandedParameterPack(Val, UPPC_EnumeratorValue)) + Val = 0; + + if (Val) { + if (Enum->isDependentType() || Val->isTypeDependent()) + EltTy = Context.DependentTy; + else { + // C99 6.7.2.2p2: Make sure we have an integer constant expression. + SourceLocation ExpLoc; + if (!Val->isValueDependent() && + VerifyIntegerConstantExpression(Val, &EnumVal)) { + Val = 0; + } else { + if (!getLangOptions().CPlusPlus) { + // C99 6.7.2.2p2: + // The expression that defines the value of an enumeration constant + // shall be an integer constant expression that has a value + // representable as an int. + + // Complain if the value is not representable in an int. + if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << Val->getSourceRange() + << (EnumVal.isUnsigned() || EnumVal.isNonNegative()); + else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { + // Force the type of the expression to 'int'. + Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).take(); + } + } + + if (Enum->isFixed()) { + EltTy = Enum->getIntegerType(); + + // C++0x [dcl.enum]p5: + // ... if the initializing value of an enumerator cannot be + // represented by the underlying type, the program is ill-formed. + if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + if (getLangOptions().Microsoft) { + Diag(IdLoc, diag::ext_enumerator_too_large) << EltTy; + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); + } else + Diag(IdLoc, diag::err_enumerator_too_large) + << EltTy; + } else + Val = ImpCastExprToType(Val, EltTy, CK_IntegralCast).take(); + } + else { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If an initializer is specified for an enumerator, the + // initializing value has the same type as the expression. + EltTy = Val->getType(); + } + } + } + } + + if (!Val) { + if (Enum->isDependentType()) + EltTy = Context.DependentTy; + else if (!LastEnumConst) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If no initializer is specified for the first enumerator, the + // initializing value has an unspecified integral type. + // + // GCC uses 'int' for its unspecified integral type, as does + // C99 6.7.2.2p3. + if (Enum->isFixed()) { + EltTy = Enum->getIntegerType(); + } + else { + EltTy = Context.IntTy; + } + } else { + // Assign the last value + 1. + EnumVal = LastEnumConst->getInitVal(); + ++EnumVal; + EltTy = LastEnumConst->getType(); + + // Check for overflow on increment. + if (EnumVal < LastEnumConst->getInitVal()) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // + // - Otherwise the type of the initializing value is the same as + // the type of the initializing value of the preceding enumerator + // unless the incremented value is not representable in that type, + // in which case the type is an unspecified integral type + // sufficient to contain the incremented value. If no such type + // exists, the program is ill-formed. + QualType T = getNextLargerIntegralType(Context, EltTy); + if (T.isNull() || Enum->isFixed()) { + // There is no integral type larger enough to represent this + // value. Complain, then allow the value to wrap around. + EnumVal = LastEnumConst->getInitVal(); + EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2); + ++EnumVal; + if (Enum->isFixed()) + // When the underlying type is fixed, this is ill-formed. + Diag(IdLoc, diag::err_enumerator_wrapped) + << EnumVal.toString(10) + << EltTy; + else + Diag(IdLoc, diag::warn_enumerator_too_large) + << EnumVal.toString(10); + } else { + EltTy = T; + } + + // Retrieve the last enumerator's value, extent that type to the + // type that is supposed to be large enough to represent the incremented + // value, then increment. + EnumVal = LastEnumConst->getInitVal(); + EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); + EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); + ++EnumVal; + + // If we're not in C++, diagnose the overflow of enumerator values, + // which in C99 means that the enumerator value is not representable in + // an int (C99 6.7.2.2p2). However, we support GCC's extension that + // permits enumerator values that are representable in some larger + // integral type. + if (!getLangOptions().CPlusPlus && !T.isNull()) + Diag(IdLoc, diag::warn_enum_value_overflow); + } else if (!getLangOptions().CPlusPlus && + !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + // Enforce C99 6.7.2.2p2 even when we compute the next value. + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << 1; + } + } + } + + if (!EltTy->isDependentType()) { + // Make the enumerator value match the signedness and size of the + // enumerator's type. + EnumVal = EnumVal.zextOrTrunc(Context.getIntWidth(EltTy)); + EnumVal.setIsSigned(EltTy->isSignedIntegerOrEnumerationType()); + } + + return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, + Val, EnumVal); +} + + +Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, + SourceLocation IdLoc, IdentifierInfo *Id, + AttributeList *Attr, + SourceLocation EqualLoc, ExprTy *val) { + EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl); + EnumConstantDecl *LastEnumConst = + cast_or_null<EnumConstantDecl>(lastEnumConst); + Expr *Val = static_cast<Expr*>(val); + + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + S = getNonFieldDeclScope(S); + + // Verify that there isn't already something declared with this name in this + // scope. + NamedDecl *PrevDecl = LookupSingleName(S, Id, IdLoc, LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(IdLoc, PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + + if (PrevDecl) { + // When in C++, we may get a TagDecl with the same name; in this case the + // enum constant will 'hide' the tag. + assert((getLangOptions().CPlusPlus || !isa<TagDecl>(PrevDecl)) && + "Received TagDecl when not in C++!"); + if (!isa<TagDecl>(PrevDecl) && isDeclInScope(PrevDecl, CurContext, S)) { + if (isa<EnumConstantDecl>(PrevDecl)) + Diag(IdLoc, diag::err_redefinition_of_enumerator) << Id; + else + Diag(IdLoc, diag::err_redefinition) << Id; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + return 0; + } + } + + // C++ [class.mem]p13: + // If T is the name of a class, then each of the following shall have a + // name different from T: + // - every enumerator of every member of class T that is an enumerated + // type + if (CXXRecordDecl *Record + = dyn_cast<CXXRecordDecl>( + TheEnumDecl->getDeclContext()->getRedeclContext())) + if (Record->getIdentifier() && Record->getIdentifier() == Id) + Diag(IdLoc, diag::err_member_name_of_class) << Id; + + EnumConstantDecl *New = + CheckEnumConstant(TheEnumDecl, LastEnumConst, IdLoc, Id, Val); + + if (New) { + // Process attributes. + if (Attr) ProcessDeclAttributeList(S, New, Attr); + + // Register this decl in the current scope stack. + New->setAccess(TheEnumDecl->getAccess()); + PushOnScopeChains(New, S); + } + + return New; +} + +void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, + SourceLocation RBraceLoc, Decl *EnumDeclX, + Decl **Elements, unsigned NumElements, + Scope *S, AttributeList *Attr) { + EnumDecl *Enum = cast<EnumDecl>(EnumDeclX); + QualType EnumType = Context.getTypeDeclType(Enum); + + if (Attr) + ProcessDeclAttributeList(S, Enum, Attr); + + if (Enum->isDependentType()) { + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = + cast_or_null<EnumConstantDecl>(Elements[i]); + if (!ECD) continue; + + ECD->setType(EnumType); + } + + Enum->completeDefinition(Context.DependentTy, Context.DependentTy, 0, 0); + return; + } + + // TODO: If the result value doesn't fit in an int, it must be a long or long + // long value. ISO C does not support this, but GCC does as an extension, + // emit a warning. + unsigned IntWidth = Context.Target.getIntWidth(); + unsigned CharWidth = Context.Target.getCharWidth(); + unsigned ShortWidth = Context.Target.getShortWidth(); + + // Verify that all the values are okay, compute the size of the values, and + // reverse the list. + unsigned NumNegativeBits = 0; + unsigned NumPositiveBits = 0; + + // Keep track of whether all elements have type int. + bool AllElementsInt = true; + + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = + cast_or_null<EnumConstantDecl>(Elements[i]); + if (!ECD) continue; // Already issued a diagnostic. + + const llvm::APSInt &InitVal = ECD->getInitVal(); + + // Keep track of the size of positive and negative values. + if (InitVal.isUnsigned() || InitVal.isNonNegative()) + NumPositiveBits = std::max(NumPositiveBits, + (unsigned)InitVal.getActiveBits()); + else + NumNegativeBits = std::max(NumNegativeBits, + (unsigned)InitVal.getMinSignedBits()); + + // Keep track of whether every enum element has type int (very commmon). + if (AllElementsInt) + AllElementsInt = ECD->getType() == Context.IntTy; + } + + // Figure out the type that should be used for this enum. + QualType BestType; + unsigned BestWidth; + + // C++0x N3000 [conv.prom]p3: + // An rvalue of an unscoped enumeration type whose underlying + // type is not fixed can be converted to an rvalue of the first + // of the following types that can represent all the values of + // the enumeration: int, unsigned int, long int, unsigned long + // int, long long int, or unsigned long long int. + // C99 6.4.4.3p2: + // An identifier declared as an enumeration constant has type int. + // The C99 rule is modified by a gcc extension + QualType BestPromotionType; + + bool Packed = Enum->getAttr<PackedAttr>() ? true : false; + // -fshort-enums is the equivalent to specifying the packed attribute on all + // enum definitions. + if (LangOpts.ShortEnums) + Packed = true; + + if (Enum->isFixed()) { + BestType = BestPromotionType = Enum->getIntegerType(); + // We don't need to set BestWidth, because BestType is going to be the type + // of the enumerators, but we do anyway because otherwise some compilers + // warn that it might be used uninitialized. + BestWidth = CharWidth; + } + else if (NumNegativeBits) { + // If there is a negative value, figure out the smallest integer type (of + // int/long/longlong) that fits. + // If it's packed, check also if it fits a char or a short. + if (Packed && NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) { + BestType = Context.SignedCharTy; + BestWidth = CharWidth; + } else if (Packed && NumNegativeBits <= ShortWidth && + NumPositiveBits < ShortWidth) { + BestType = Context.ShortTy; + BestWidth = ShortWidth; + } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) { + BestType = Context.IntTy; + BestWidth = IntWidth; + } else { + BestWidth = Context.Target.getLongWidth(); + + if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) { + BestType = Context.LongTy; + } else { + BestWidth = Context.Target.getLongLongWidth(); + + if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth) + Diag(Enum->getLocation(), diag::warn_enum_too_large); + BestType = Context.LongLongTy; + } + } + BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType); + } else { + // If there is no negative value, figure out the smallest type that fits + // all of the enumerator values. + // If it's packed, check also if it fits a char or a short. + if (Packed && NumPositiveBits <= CharWidth) { + BestType = Context.UnsignedCharTy; + BestPromotionType = Context.IntTy; + BestWidth = CharWidth; + } else if (Packed && NumPositiveBits <= ShortWidth) { + BestType = Context.UnsignedShortTy; + BestPromotionType = Context.IntTy; + BestWidth = ShortWidth; + } else if (NumPositiveBits <= IntWidth) { + BestType = Context.UnsignedIntTy; + BestWidth = IntWidth; + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? Context.UnsignedIntTy : Context.IntTy; + } else if (NumPositiveBits <= + (BestWidth = Context.Target.getLongWidth())) { + BestType = Context.UnsignedLongTy; + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? Context.UnsignedLongTy : Context.LongTy; + } else { + BestWidth = Context.Target.getLongLongWidth(); + assert(NumPositiveBits <= BestWidth && + "How could an initializer get larger than ULL?"); + BestType = Context.UnsignedLongLongTy; + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? Context.UnsignedLongLongTy : Context.LongLongTy; + } + } + + // Loop over all of the enumerator constants, changing their types to match + // the type of the enum if needed. + for (unsigned i = 0; i != NumElements; ++i) { + EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]); + if (!ECD) continue; // Already issued a diagnostic. + + // Standard C says the enumerators have int type, but we allow, as an + // extension, the enumerators to be larger than int size. If each + // enumerator value fits in an int, type it as an int, otherwise type it the + // same as the enumerator decl itself. This means that in "enum { X = 1U }" + // that X has type 'int', not 'unsigned'. + + // Determine whether the value fits into an int. + llvm::APSInt InitVal = ECD->getInitVal(); + + // If it fits into an integer type, force it. Otherwise force it to match + // the enum decl type. + QualType NewTy; + unsigned NewWidth; + bool NewSign; + if (!getLangOptions().CPlusPlus && + isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { + NewTy = Context.IntTy; + NewWidth = IntWidth; + NewSign = true; + } else if (ECD->getType() == BestType) { + // Already the right type! + if (getLangOptions().CPlusPlus) + // C++ [dcl.enum]p4: Following the closing brace of an + // enum-specifier, each enumerator has the type of its + // enumeration. + ECD->setType(EnumType); + continue; + } else { + NewTy = BestType; + NewWidth = BestWidth; + NewSign = BestType->isSignedIntegerOrEnumerationType(); + } + + // Adjust the APSInt value. + InitVal = InitVal.extOrTrunc(NewWidth); + InitVal.setIsSigned(NewSign); + ECD->setInitVal(InitVal); + + // Adjust the Expr initializer and type. + if (ECD->getInitExpr() && + !Context.hasSameType(NewTy, ECD->getInitExpr()->getType())) + ECD->setInitExpr(ImplicitCastExpr::Create(Context, NewTy, + CK_IntegralCast, + ECD->getInitExpr(), + /*base paths*/ 0, + VK_RValue)); + if (getLangOptions().CPlusPlus) + // C++ [dcl.enum]p4: Following the closing brace of an + // enum-specifier, each enumerator has the type of its + // enumeration. + ECD->setType(EnumType); + else + ECD->setType(NewTy); + } + + Enum->completeDefinition(BestType, BestPromotionType, + NumPositiveBits, NumNegativeBits); +} + +Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, + SourceLocation StartLoc, + SourceLocation EndLoc) { + StringLiteral *AsmString = cast<StringLiteral>(expr); + + FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, + AsmString, StartLoc, + EndLoc); + CurContext->addDecl(New); + return New; +} + +void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, + SourceLocation PragmaLoc, + SourceLocation NameLoc) { + Decl *PrevDecl = LookupSingleName(TUScope, Name, NameLoc, LookupOrdinaryName); + + if (PrevDecl) { + PrevDecl->addAttr(::new (Context) WeakAttr(PragmaLoc, Context)); + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair<IdentifierInfo*,WeakInfo> + (Name, WeakInfo((IdentifierInfo*)0, NameLoc))); + } +} + +void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation NameLoc, + SourceLocation AliasNameLoc) { + Decl *PrevDecl = LookupSingleName(TUScope, AliasName, AliasNameLoc, + LookupOrdinaryName); + WeakInfo W = WeakInfo(Name, NameLoc); + + if (PrevDecl) { + if (!PrevDecl->hasAttr<AliasAttr>()) + if (NamedDecl *ND = dyn_cast<NamedDecl>(PrevDecl)) + DeclApplyPragmaWeak(TUScope, ND, W); + } else { + (void)WeakUndeclaredIdentifiers.insert( + std::pair<IdentifierInfo*,WeakInfo>(AliasName, W)); + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp new file mode 100644 index 0000000..7f93ab7 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -0,0 +1,3207 @@ +//===--- SemaDeclAttr.cpp - Declaration Attribute Handling ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements decl-related attribute processing. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "TargetAttributesSema.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "llvm/ADT/StringExtras.h" +using namespace clang; +using namespace sema; + +/// These constants match the enumerated choices of +/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type. +enum { + ExpectedFunction, + ExpectedUnion, + ExpectedVariableOrFunction, + ExpectedFunctionOrMethod, + ExpectedParameter, + ExpectedParameterOrMethod, + ExpectedFunctionMethodOrBlock, + ExpectedClassOrVirtualMethod, + ExpectedFunctionMethodOrParameter, + ExpectedClass, + ExpectedVirtualMethod, + ExpectedClassMember, + ExpectedVariable, + ExpectedMethod, + ExpectedVariableFunctionOrLabel +}; + +//===----------------------------------------------------------------------===// +// Helper functions +//===----------------------------------------------------------------------===// + +static const FunctionType *getFunctionType(const Decl *d, + bool blocksToo = true) { + QualType Ty; + if (const ValueDecl *decl = dyn_cast<ValueDecl>(d)) + Ty = decl->getType(); + else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d)) + Ty = decl->getType(); + else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(d)) + Ty = decl->getUnderlyingType(); + else + return 0; + + if (Ty->isFunctionPointerType()) + Ty = Ty->getAs<PointerType>()->getPointeeType(); + else if (blocksToo && Ty->isBlockPointerType()) + Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); + + return Ty->getAs<FunctionType>(); +} + +// FIXME: We should provide an abstraction around a method or function +// to provide the following bits of information. + +/// isFunction - Return true if the given decl has function +/// type (function or function-typed variable). +static bool isFunction(const Decl *d) { + return getFunctionType(d, false) != NULL; +} + +/// isFunctionOrMethod - Return true if the given decl has function +/// type (function or function-typed variable) or an Objective-C +/// method. +static bool isFunctionOrMethod(const Decl *d) { + return isFunction(d)|| isa<ObjCMethodDecl>(d); +} + +/// isFunctionOrMethodOrBlock - Return true if the given decl has function +/// type (function or function-typed variable) or an Objective-C +/// method or a block. +static bool isFunctionOrMethodOrBlock(const Decl *d) { + if (isFunctionOrMethod(d)) + return true; + // check for block is more involved. + if (const VarDecl *V = dyn_cast<VarDecl>(d)) { + QualType Ty = V->getType(); + return Ty->isBlockPointerType(); + } + return isa<BlockDecl>(d); +} + +/// Return true if the given decl has a declarator that should have +/// been processed by Sema::GetTypeForDeclarator. +static bool hasDeclarator(const Decl *d) { + // In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl. + return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefNameDecl>(d); +} + +/// hasFunctionProto - Return true if the given decl has a argument +/// information. This decl should have already passed +/// isFunctionOrMethod or isFunctionOrMethodOrBlock. +static bool hasFunctionProto(const Decl *d) { + if (const FunctionType *FnTy = getFunctionType(d)) + return isa<FunctionProtoType>(FnTy); + else { + assert(isa<ObjCMethodDecl>(d) || isa<BlockDecl>(d)); + return true; + } +} + +/// getFunctionOrMethodNumArgs - Return number of function or method +/// arguments. It is an error to call this on a K&R function (use +/// hasFunctionProto first). +static unsigned getFunctionOrMethodNumArgs(const Decl *d) { + if (const FunctionType *FnTy = getFunctionType(d)) + return cast<FunctionProtoType>(FnTy)->getNumArgs(); + if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) + return BD->getNumParams(); + return cast<ObjCMethodDecl>(d)->param_size(); +} + +static QualType getFunctionOrMethodArgType(const Decl *d, unsigned Idx) { + if (const FunctionType *FnTy = getFunctionType(d)) + return cast<FunctionProtoType>(FnTy)->getArgType(Idx); + if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) + return BD->getParamDecl(Idx)->getType(); + + return cast<ObjCMethodDecl>(d)->param_begin()[Idx]->getType(); +} + +static QualType getFunctionOrMethodResultType(const Decl *d) { + if (const FunctionType *FnTy = getFunctionType(d)) + return cast<FunctionProtoType>(FnTy)->getResultType(); + return cast<ObjCMethodDecl>(d)->getResultType(); +} + +static bool isFunctionOrMethodVariadic(const Decl *d) { + if (const FunctionType *FnTy = getFunctionType(d)) { + const FunctionProtoType *proto = cast<FunctionProtoType>(FnTy); + return proto->isVariadic(); + } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(d)) + return BD->isVariadic(); + else { + return cast<ObjCMethodDecl>(d)->isVariadic(); + } +} + +static bool isInstanceMethod(const Decl *d) { + if (const CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(d)) + return MethodDecl->isInstance(); + return false; +} + +static inline bool isNSStringType(QualType T, ASTContext &Ctx) { + const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>(); + if (!PT) + return false; + + ObjCInterfaceDecl *Cls = PT->getObjectType()->getInterface(); + if (!Cls) + return false; + + IdentifierInfo* ClsName = Cls->getIdentifier(); + + // FIXME: Should we walk the chain of classes? + return ClsName == &Ctx.Idents.get("NSString") || + ClsName == &Ctx.Idents.get("NSMutableString"); +} + +static inline bool isCFStringType(QualType T, ASTContext &Ctx) { + const PointerType *PT = T->getAs<PointerType>(); + if (!PT) + return false; + + const RecordType *RT = PT->getPointeeType()->getAs<RecordType>(); + if (!RT) + return false; + + const RecordDecl *RD = RT->getDecl(); + if (RD->getTagKind() != TTK_Struct) + return false; + + return RD->getIdentifier() == &Ctx.Idents.get("__CFString"); +} + +//===----------------------------------------------------------------------===// +// Attribute Implementations +//===----------------------------------------------------------------------===// + +// FIXME: All this manual attribute parsing code is gross. At the +// least add some helper functions to check most argument patterns (# +// and types of args). + +static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, + const AttributeList &Attr, Sema &S) { + TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(d); + if (tDecl == 0) { + S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); + return; + } + + QualType curType = tDecl->getUnderlyingType(); + + Expr *sizeExpr; + + // Special case where the argument is a template id. + if (Attr.getParameterName()) { + CXXScopeSpec SS; + UnqualifiedId id; + id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); + sizeExpr = S.ActOnIdExpression(scope, SS, id, false, false).takeAs<Expr>(); + } else { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + sizeExpr = Attr.getArg(0); + } + + // Instantiate/Install the vector type, and let Sema build the type for us. + // This will run the reguired checks. + QualType T = S.BuildExtVectorType(curType, sizeExpr, Attr.getLoc()); + if (!T.isNull()) { + // FIXME: preserve the old source info. + tDecl->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(T)); + + // Remember this typedef decl, we will need it later for diagnostics. + S.ExtVectorDecls.push_back(tDecl); + } +} + +static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (TagDecl *TD = dyn_cast<TagDecl>(d)) + TD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context)); + else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { + // If the alignment is less than or equal to 8 bits, the packed attribute + // has no effect. + if (!FD->getType()->isIncompleteType() && + S.Context.getTypeAlign(FD->getType()) <= 8) + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) + << Attr.getName() << FD->getType(); + else + FD->addAttr(::new (S.Context) PackedAttr(Attr.getLoc(), S.Context)); + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + +static void HandleMsStructAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (TagDecl *TD = dyn_cast<TagDecl>(d)) + TD->addAttr(::new (S.Context) MsStructAttr(Attr.getLoc(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); +} + +static void HandleIBAction(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // The IBAction attributes only apply to instance methods. + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) + if (MD->isInstanceMethod()) { + d->addAttr(::new (S.Context) IBActionAttr(Attr.getLoc(), S.Context)); + return; + } + + S.Diag(Attr.getLoc(), diag::warn_attribute_ibaction) << Attr.getName(); +} + +static void HandleIBOutlet(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // The IBOutlet attributes only apply to instance variables of + // Objective-C classes. + if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) { + d->addAttr(::new (S.Context) IBOutletAttr(Attr.getLoc(), S.Context)); + return; + } + + S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); +} + +static void HandleIBOutletCollection(Decl *d, const AttributeList &Attr, + Sema &S) { + + // The iboutletcollection attribute can have zero or one arguments. + if (Attr.getParameterName() && Attr.getNumArgs() > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // The IBOutletCollection attributes only apply to instance variables of + // Objective-C classes. + if (!(isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d))) { + S.Diag(Attr.getLoc(), diag::warn_attribute_iboutlet) << Attr.getName(); + return; + } + if (const ValueDecl *VD = dyn_cast<ValueDecl>(d)) + if (!VD->getType()->getAs<ObjCObjectPointerType>()) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) + << VD->getType() << 0; + return; + } + if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(d)) + if (!PD->getType()->getAs<ObjCObjectPointerType>()) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_object_type) + << PD->getType() << 1; + return; + } + + IdentifierInfo *II = Attr.getParameterName(); + if (!II) + II = &S.Context.Idents.get("id"); + + ParsedType TypeRep = S.getTypeName(*II, Attr.getLoc(), + S.getScopeForContext(d->getDeclContext()->getParent())); + if (!TypeRep) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; + return; + } + QualType QT = TypeRep.get(); + // Diagnose use of non-object type in iboutletcollection attribute. + // FIXME. Gnu attribute extension ignores use of builtin types in + // attributes. So, __attribute__((iboutletcollection(char))) will be + // treated as __attribute__((iboutletcollection())). + if (!QT->isObjCIdType() && !QT->isObjCClassType() && + !QT->isObjCObjectType()) { + S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; + return; + } + d->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getLoc(), S.Context, + QT)); +} + +static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // GCC ignores the nonnull attribute on K&R style function prototypes, so we + // ignore it as well + if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(d); + unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + + // The nonnull attribute only applies to pointers. + llvm::SmallVector<unsigned, 10> NonNullArgs; + + for (AttributeList::arg_iterator I=Attr.arg_begin(), + E=Attr.arg_end(); I!=E; ++I) { + + + // The argument must be an integer constant expression. + Expr *Ex = *I; + llvm::APSInt ArgNum(32); + if (Ex->isTypeDependent() || Ex->isValueDependent() || + !Ex->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "nonnull" << Ex->getSourceRange(); + return; + } + + unsigned x = (unsigned) ArgNum.getZExtValue(); + + if (x < 1 || x > NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "nonnull" << I.getArgNum() << Ex->getSourceRange(); + return; + } + + --x; + if (HasImplicitThisParam) { + if (x == 0) { + S.Diag(Attr.getLoc(), + diag::err_attribute_invalid_implicit_this_argument) + << "nonnull" << Ex->getSourceRange(); + return; + } + --x; + } + + // Is the function argument a pointer type? + QualType T = getFunctionOrMethodArgType(d, x).getNonReferenceType(); + if (!T->isAnyPointerType() && !T->isBlockPointerType()) { + // FIXME: Should also highlight argument in decl. + S.Diag(Attr.getLoc(), diag::warn_nonnull_pointers_only) + << "nonnull" << Ex->getSourceRange(); + continue; + } + + NonNullArgs.push_back(x); + } + + // If no arguments were specified to __attribute__((nonnull)) then all pointer + // arguments have a nonnull attribute. + if (NonNullArgs.empty()) { + for (unsigned I = 0, E = getFunctionOrMethodNumArgs(d); I != E; ++I) { + QualType T = getFunctionOrMethodArgType(d, I).getNonReferenceType(); + if (T->isAnyPointerType() || T->isBlockPointerType()) + NonNullArgs.push_back(I); + else if (const RecordType *UT = T->getAsUnionType()) { + if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { + RecordDecl *UD = UT->getDecl(); + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); it != itend; ++it) { + T = it->getType(); + if (T->isAnyPointerType() || T->isBlockPointerType()) { + NonNullArgs.push_back(I); + break; + } + } + } + } + } + + // No pointer arguments? + if (NonNullArgs.empty()) { + // Warn the trivial case only if attribute is not coming from a + // macro instantiation. + if (Attr.getLoc().isFileID()) + S.Diag(Attr.getLoc(), diag::warn_attribute_nonnull_no_pointers); + return; + } + } + + unsigned* start = &NonNullArgs[0]; + unsigned size = NonNullArgs.size(); + llvm::array_pod_sort(start, start + size); + d->addAttr(::new (S.Context) NonNullAttr(Attr.getLoc(), S.Context, start, + size)); +} + +static void HandleOwnershipAttr(Decl *d, const AttributeList &AL, Sema &S) { + // This attribute must be applied to a function declaration. + // The first argument to the attribute must be a string, + // the name of the resource, for example "malloc". + // The following arguments must be argument indexes, the arguments must be + // of integer type for Returns, otherwise of pointer type. + // The difference between Holds and Takes is that a pointer may still be used + // after being held. free() should be __attribute((ownership_takes)), whereas + // a list append function may well be __attribute((ownership_holds)). + + if (!AL.getParameterName()) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_n_not_string) + << AL.getName()->getName() << 1; + return; + } + // Figure out our Kind, and check arguments while we're at it. + OwnershipAttr::OwnershipKind K; + switch (AL.getKind()) { + case AttributeList::AT_ownership_takes: + K = OwnershipAttr::Takes; + if (AL.getNumArgs() < 1) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + return; + } + break; + case AttributeList::AT_ownership_holds: + K = OwnershipAttr::Holds; + if (AL.getNumArgs() < 1) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + return; + } + break; + case AttributeList::AT_ownership_returns: + K = OwnershipAttr::Returns; + if (AL.getNumArgs() > 1) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) + << AL.getNumArgs() + 1; + return; + } + break; + default: + // This should never happen given how we are called. + llvm_unreachable("Unknown ownership attribute"); + } + + if (!isFunction(d) || !hasFunctionProto(d)) { + S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) + << AL.getName() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(d); + unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + + llvm::StringRef Module = AL.getParameterName()->getName(); + + // Normalize the argument, __foo__ becomes foo. + if (Module.startswith("__") && Module.endswith("__")) + Module = Module.substr(2, Module.size() - 4); + + llvm::SmallVector<unsigned, 10> OwnershipArgs; + + for (AttributeList::arg_iterator I = AL.arg_begin(), E = AL.arg_end(); I != E; + ++I) { + + Expr *IdxExpr = *I; + llvm::APSInt ArgNum(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() + || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_not_int) + << AL.getName()->getName() << IdxExpr->getSourceRange(); + continue; + } + + unsigned x = (unsigned) ArgNum.getZExtValue(); + + if (x > NumArgs || x < 1) { + S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) + << AL.getName()->getName() << x << IdxExpr->getSourceRange(); + continue; + } + --x; + if (HasImplicitThisParam) { + if (x == 0) { + S.Diag(AL.getLoc(), diag::err_attribute_invalid_implicit_this_argument) + << "ownership" << IdxExpr->getSourceRange(); + return; + } + --x; + } + + switch (K) { + case OwnershipAttr::Takes: + case OwnershipAttr::Holds: { + // Is the function argument a pointer type? + QualType T = getFunctionOrMethodArgType(d, x); + if (!T->isAnyPointerType() && !T->isBlockPointerType()) { + // FIXME: Should also highlight argument in decl. + S.Diag(AL.getLoc(), diag::err_ownership_type) + << ((K==OwnershipAttr::Takes)?"ownership_takes":"ownership_holds") + << "pointer" + << IdxExpr->getSourceRange(); + continue; + } + break; + } + case OwnershipAttr::Returns: { + if (AL.getNumArgs() > 1) { + // Is the function argument an integer type? + Expr *IdxExpr = AL.getArg(0); + llvm::APSInt ArgNum(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() + || !IdxExpr->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(AL.getLoc(), diag::err_ownership_type) + << "ownership_returns" << "integer" + << IdxExpr->getSourceRange(); + return; + } + } + break; + } + default: + llvm_unreachable("Unknown ownership attribute"); + } // switch + + // Check we don't have a conflict with another ownership attribute. + for (specific_attr_iterator<OwnershipAttr> + i = d->specific_attr_begin<OwnershipAttr>(), + e = d->specific_attr_end<OwnershipAttr>(); + i != e; ++i) { + if ((*i)->getOwnKind() != K) { + for (const unsigned *I = (*i)->args_begin(), *E = (*i)->args_end(); + I!=E; ++I) { + if (x == *I) { + S.Diag(AL.getLoc(), diag::err_attributes_are_not_compatible) + << AL.getName()->getName() << "ownership_*"; + } + } + } + } + OwnershipArgs.push_back(x); + } + + unsigned* start = OwnershipArgs.data(); + unsigned size = OwnershipArgs.size(); + llvm::array_pod_sort(start, start + size); + + if (K != OwnershipAttr::Returns && OwnershipArgs.empty()) { + S.Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << 2; + return; + } + + d->addAttr(::new (S.Context) OwnershipAttr(AL.getLoc(), S.Context, K, Module, + start, size)); +} + +/// Whether this declaration has internal linkage for the purposes of +/// things that want to complain about things not have internal linkage. +static bool hasEffectivelyInternalLinkage(NamedDecl *D) { + switch (D->getLinkage()) { + case NoLinkage: + case InternalLinkage: + return true; + + // Template instantiations that go from external to unique-external + // shouldn't get diagnosed. + case UniqueExternalLinkage: + return true; + + case ExternalLinkage: + return false; + } + llvm_unreachable("unknown linkage kind!"); + return false; +} + +static void HandleWeakRefAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + return; + } + + NamedDecl *nd = cast<NamedDecl>(d); + + // gcc rejects + // class c { + // static int a __attribute__((weakref ("v2"))); + // static int b() __attribute__((weakref ("f3"))); + // }; + // and ignores the attributes of + // void f(void) { + // static int a __attribute__((weakref ("v2"))); + // } + // we reject them + const DeclContext *Ctx = d->getDeclContext()->getRedeclContext(); + if (!Ctx->isFileContext()) { + S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_global_context) << + nd->getNameAsString(); + return; + } + + // The GCC manual says + // + // At present, a declaration to which `weakref' is attached can only + // be `static'. + // + // It also says + // + // Without a TARGET, + // given as an argument to `weakref' or to `alias', `weakref' is + // equivalent to `weak'. + // + // gcc 4.4.1 will accept + // int a7 __attribute__((weakref)); + // as + // int a7 __attribute__((weak)); + // This looks like a bug in gcc. We reject that for now. We should revisit + // it if this behaviour is actually used. + + if (!hasEffectivelyInternalLinkage(nd)) { + S.Diag(Attr.getLoc(), diag::err_attribute_weakref_not_static); + return; + } + + // GCC rejects + // static ((alias ("y"), weakref)). + // Should we? How to check that weakref is before or after alias? + + if (Attr.getNumArgs() == 1) { + Expr *Arg = Attr.getArg(0); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + + if (Str == 0 || Str->isWide()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "weakref" << 1; + return; + } + // GCC will accept anything as the argument of weakref. Should we + // check for an existing decl? + d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, + Str->getString())); + } + + d->addAttr(::new (S.Context) WeakRefAttr(Attr.getLoc(), S.Context)); +} + +static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + Expr *Arg = Attr.getArg(0); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + + if (Str == 0 || Str->isWide()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "alias" << 1; + return; + } + + if (S.Context.Target.getTriple().isOSDarwin()) { + S.Diag(Attr.getLoc(), diag::err_alias_not_supported_on_darwin); + return; + } + + // FIXME: check if target symbol exists in current file + + d->addAttr(::new (S.Context) AliasAttr(Attr.getLoc(), S.Context, + Str->getString())); +} + +static void HandleNakedAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) NakedAttr(Attr.getLoc(), S.Context)); +} + +static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getLoc(), S.Context)); +} + +static void HandleMallocAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // Check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { + QualType RetTy = FD->getResultType(); + if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { + d->addAttr(::new (S.Context) MallocAttr(Attr.getLoc(), S.Context)); + return; + } + } + + S.Diag(Attr.getLoc(), diag::warn_attribute_malloc_pointer_only); +} + +static void HandleMayAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + d->addAttr(::new (S.Context) MayAliasAttr(Attr.getLoc(), S.Context)); +} + +static void HandleNoCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { + assert(Attr.isInvalid() == false); + if (isa<VarDecl>(d)) + d->addAttr(::new (S.Context) NoCommonAttr(Attr.getLoc(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; +} + +static void HandleCommonAttr(Decl *d, const AttributeList &Attr, Sema &S) { + assert(Attr.isInvalid() == false); + if (isa<VarDecl>(d)) + d->addAttr(::new (S.Context) CommonAttr(Attr.getLoc(), S.Context)); + else + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; +} + +static void HandleNoReturnAttr(Decl *d, const AttributeList &attr, Sema &S) { + if (hasDeclarator(d)) return; + + if (S.CheckNoReturnAttr(attr)) return; + + if (!isa<ObjCMethodDecl>(d)) { + S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << attr.getName() << ExpectedFunctionOrMethod; + return; + } + + d->addAttr(::new (S.Context) NoReturnAttr(attr.getLoc(), S.Context)); +} + +bool Sema::CheckNoReturnAttr(const AttributeList &attr) { + if (attr.hasParameterOrArguments()) { + Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + attr.setInvalid(); + return true; + } + + return false; +} + +static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + + // The checking path for 'noreturn' and 'analyzer_noreturn' are different + // because 'analyzer_noreturn' does not impact the type. + + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isFunctionOrMethod(d) && !isa<BlockDecl>(d)) { + ValueDecl *VD = dyn_cast<ValueDecl>(d); + if (VD == 0 || (!VD->getType()->isBlockPointerType() + && !VD->getType()->isFunctionPointerType())) { + S.Diag(Attr.getLoc(), + Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + : diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionMethodOrBlock; + return; + } + } + + d->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getLoc(), S.Context)); +} + +// PS3 PPU-specific. +static void HandleVecReturnAttr(Decl *d, const AttributeList &Attr, + Sema &S) { +/* + Returning a Vector Class in Registers + + According to the PPU ABI specifications, a class with a single member of + vector type is returned in memory when used as the return value of a function. + This results in inefficient code when implementing vector classes. To return + the value in a single vector register, add the vecreturn attribute to the + class definition. This attribute is also applicable to struct types. + + Example: + + struct Vector + { + __vector float xyzw; + } __attribute__((vecreturn)); + + Vector Add(Vector lhs, Vector rhs) + { + Vector result; + result.xyzw = vec_add(lhs.xyzw, rhs.xyzw); + return result; // This will be returned in a register + } +*/ + if (!isa<RecordDecl>(d)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedClass; + return; + } + + if (d->getAttr<VecReturnAttr>()) { + S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn"; + return; + } + + RecordDecl *record = cast<RecordDecl>(d); + int count = 0; + + if (!isa<CXXRecordDecl>(record)) { + S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); + return; + } + + if (!cast<CXXRecordDecl>(record)->isPOD()) { + S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_pod_record); + return; + } + + for (RecordDecl::field_iterator iter = record->field_begin(); + iter != record->field_end(); iter++) { + if ((count == 1) || !iter->getType()->isVectorType()) { + S.Diag(Attr.getLoc(), diag::err_attribute_vecreturn_only_vector_member); + return; + } + count++; + } + + d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context)); +} + +static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionMethodOrParameter; + return; + } + // FIXME: Actually store the attribute on the declaration +} + +static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<VarDecl>(d) && !isa<ObjCIvarDecl>(d) && !isFunctionOrMethod(d) && + !isa<TypeDecl>(d) && !isa<LabelDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableFunctionOrLabel; + return; + } + + d->addAttr(::new (S.Context) UnusedAttr(Attr.getLoc(), S.Context)); +} + +static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (const VarDecl *VD = dyn_cast<VarDecl>(d)) { + if (VD->hasLocalStorage() || VD->hasExternalStorage()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "used"; + return; + } + } else if (!isFunctionOrMethod(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + return; + } + + d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); +} + +static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + int priority = 65535; // FIXME: Do not hardcode such constants. + if (Attr.getNumArgs() > 0) { + Expr *E = Attr.getArg(0); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "constructor" << 1 << E->getSourceRange(); + return; + } + priority = Idx.getZExtValue(); + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) ConstructorAttr(Attr.getLoc(), S.Context, + priority)); +} + +static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + int priority = 65535; // FIXME: Do not hardcode such constants. + if (Attr.getNumArgs() > 0) { + Expr *E = Attr.getArg(0); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "destructor" << 1 << E->getSourceRange(); + return; + } + priority = Idx.getZExtValue(); + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) DestructorAttr(Attr.getLoc(), S.Context, + priority)); +} + +static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + // Handle the case where deprecated attribute has a text message. + llvm::StringRef Str; + if (NumArgs == 1) { + StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0)); + if (!SE) { + S.Diag(Attr.getArg(0)->getLocStart(), diag::err_attribute_not_string) + << "deprecated"; + return; + } + Str = SE->getString(); + } + + d->addAttr(::new (S.Context) DeprecatedAttr(Attr.getLoc(), S.Context, Str)); +} + +static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { + unsigned NumArgs = Attr.getNumArgs(); + if (NumArgs > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 1; + return; + } + + // Handle the case where unavailable attribute has a text message. + llvm::StringRef Str; + if (NumArgs == 1) { + StringLiteral *SE = dyn_cast<StringLiteral>(Attr.getArg(0)); + if (!SE) { + S.Diag(Attr.getArg(0)->getLocStart(), + diag::err_attribute_not_string) << "unavailable"; + return; + } + Str = SE->getString(); + } + d->addAttr(::new (S.Context) UnavailableAttr(Attr.getLoc(), S.Context, Str)); +} + +static void HandleAvailabilityAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + IdentifierInfo *Platform = Attr.getParameterName(); + SourceLocation PlatformLoc = Attr.getParameterLoc(); + + llvm::StringRef PlatformName + = AvailabilityAttr::getPrettyPlatformName(Platform->getName()); + if (PlatformName.empty()) { + S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) + << Platform; + + PlatformName = Platform->getName(); + } + + AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); + AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); + AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); + bool IsUnavailable = Attr.getUnavailableLoc().isValid(); + + // Ensure that Introduced < Deprecated < Obsoleted (although not all + // of these steps are needed). + if (Introduced.isValid() && Deprecated.isValid() && + !(Introduced.Version < Deprecated.Version)) { + S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering) + << 1 << PlatformName << Deprecated.Version.getAsString() + << 0 << Introduced.Version.getAsString(); + return; + } + + if (Introduced.isValid() && Obsoleted.isValid() && + !(Introduced.Version < Obsoleted.Version)) { + S.Diag(Introduced.KeywordLoc, diag::warn_availability_version_ordering) + << 2 << PlatformName << Obsoleted.Version.getAsString() + << 0 << Introduced.Version.getAsString(); + return; + } + + if (Deprecated.isValid() && Obsoleted.isValid() && + !(Deprecated.Version < Obsoleted.Version)) { + S.Diag(Deprecated.KeywordLoc, diag::warn_availability_version_ordering) + << 2 << PlatformName << Obsoleted.Version.getAsString() + << 1 << Deprecated.Version.getAsString(); + return; + } + + d->addAttr(::new (S.Context) AvailabilityAttr(Attr.getLoc(), S.Context, + Platform, + Introduced.Version, + Deprecated.Version, + Obsoleted.Version, + IsUnavailable)); +} + +static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + Expr *Arg = Attr.getArg(0); + Arg = Arg->IgnoreParenCasts(); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + + if (Str == 0 || Str->isWide()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "visibility" << 1; + return; + } + + llvm::StringRef TypeStr = Str->getString(); + VisibilityAttr::VisibilityType type; + + if (TypeStr == "default") + type = VisibilityAttr::Default; + else if (TypeStr == "hidden") + type = VisibilityAttr::Hidden; + else if (TypeStr == "internal") + type = VisibilityAttr::Hidden; // FIXME + else if (TypeStr == "protected") + type = VisibilityAttr::Protected; + else { + S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; + return; + } + + d->addAttr(::new (S.Context) VisibilityAttr(Attr.getLoc(), S.Context, type)); +} + +static void HandleObjCMethodFamilyAttr(Decl *decl, const AttributeList &attr, + Sema &S) { + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl); + if (!method) { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_decl_type) + << ExpectedMethod; + return; + } + + if (attr.getNumArgs() != 0 || !attr.getParameterName()) { + if (!attr.getParameterName() && attr.getNumArgs() == 1) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "objc_method_family" << 1; + } else { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + } + attr.setInvalid(); + return; + } + + llvm::StringRef param = attr.getParameterName()->getName(); + ObjCMethodFamilyAttr::FamilyKind family; + if (param == "none") + family = ObjCMethodFamilyAttr::OMF_None; + else if (param == "alloc") + family = ObjCMethodFamilyAttr::OMF_alloc; + else if (param == "copy") + family = ObjCMethodFamilyAttr::OMF_copy; + else if (param == "init") + family = ObjCMethodFamilyAttr::OMF_init; + else if (param == "mutableCopy") + family = ObjCMethodFamilyAttr::OMF_mutableCopy; + else if (param == "new") + family = ObjCMethodFamilyAttr::OMF_new; + else { + // Just warn and ignore it. This is future-proof against new + // families being used in system headers. + S.Diag(attr.getParameterLoc(), diag::warn_unknown_method_family); + return; + } + + decl->addAttr(new (S.Context) ObjCMethodFamilyAttr(attr.getLoc(), + S.Context, family)); +} + +static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, + Sema &S) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D); + if (OCI == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_requires_objc_interface); + return; + } + + D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getLoc(), S.Context)); +} + +static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + QualType T = TD->getUnderlyingType(); + if (!T->isPointerType() || + !T->getAs<PointerType>()->getPointeeType()->isRecordType()) { + S.Diag(TD->getLocation(), diag::err_nsobject_attribute); + return; + } + } + D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getLoc(), S.Context)); +} + +static void +HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + if (!isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_overloadable_not_function); + return; + } + + D->addAttr(::new (S.Context) OverloadableAttr(Attr.getLoc(), S.Context)); +} + +static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (!Attr.getParameterName()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "blocks" << 1; + return; + } + + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + BlocksAttr::BlockType type; + if (Attr.getParameterName()->isStr("byref")) + type = BlocksAttr::ByRef; + else { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << "blocks" << Attr.getParameterName(); + return; + } + + d->addAttr(::new (S.Context) BlocksAttr(Attr.getLoc(), S.Context, type)); +} + +static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 2) { + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; + return; + } + + int sentinel = 0; + if (Attr.getNumArgs() > 0) { + Expr *E = Attr.getArg(0); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "sentinel" << 1 << E->getSourceRange(); + return; + } + sentinel = Idx.getZExtValue(); + + if (sentinel < 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_less_than_zero) + << E->getSourceRange(); + return; + } + } + + int nullPos = 0; + if (Attr.getNumArgs() > 1) { + Expr *E = Attr.getArg(1); + llvm::APSInt Idx(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "sentinel" << 2 << E->getSourceRange(); + return; + } + nullPos = Idx.getZExtValue(); + + if (nullPos > 1 || nullPos < 0) { + // FIXME: This error message could be improved, it would be nice + // to say what the bounds actually are. + S.Diag(Attr.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) + << E->getSourceRange(); + return; + } + } + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) { + const FunctionType *FT = FD->getType()->getAs<FunctionType>(); + assert(FT && "FunctionDecl has non-function type?"); + + if (isa<FunctionNoProtoType>(FT)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_named_arguments); + return; + } + + if (!cast<FunctionProtoType>(FT)->isVariadic()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; + return; + } + } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) { + if (!MD->isVariadic()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << 0; + return; + } + } else if (isa<BlockDecl>(d)) { + // Note! BlockDecl is typeless. Variadic diagnostics will be issued by the + // caller. + ; + } else if (const VarDecl *V = dyn_cast<VarDecl>(d)) { + QualType Ty = V->getType(); + if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { + const FunctionType *FT = Ty->isFunctionPointerType() ? getFunctionType(d) + : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); + if (!cast<FunctionProtoType>(FT)->isVariadic()) { + int m = Ty->isFunctionPointerType() ? 0 : 1; + S.Diag(Attr.getLoc(), diag::warn_attribute_sentinel_not_variadic) << m; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionMethodOrBlock; + return; + } + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionMethodOrBlock; + return; + } + d->addAttr(::new (S.Context) SentinelAttr(Attr.getLoc(), S.Context, sentinel, + nullPos)); +} + +static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + if (isFunction(D) && getFunctionType(D)->getResultType()->isVoidType()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) + << Attr.getName() << 0; + return; + } + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) + if (MD->getResultType()->isVoidType()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_void_function_method) + << Attr.getName() << 1; + return; + } + + D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getLoc(), S.Context)); +} + +static void HandleWeakAttr(Decl *d, const AttributeList &attr, Sema &S) { + // check the attribute arguments. + if (attr.hasParameterOrArguments()) { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<VarDecl>(d) && !isa<FunctionDecl>(d)) { + S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << attr.getName() << ExpectedVariableOrFunction; + return; + } + + NamedDecl *nd = cast<NamedDecl>(d); + + // 'weak' only applies to declarations with external linkage. + if (hasEffectivelyInternalLinkage(nd)) { + S.Diag(attr.getLoc(), diag::err_attribute_weak_static); + return; + } + + nd->addAttr(::new (S.Context) WeakAttr(attr.getLoc(), S.Context)); +} + +static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // weak_import only applies to variable & function declarations. + bool isDef = false; + if (!D->canBeWeakImported(isDef)) { + if (isDef) + S.Diag(Attr.getLoc(), + diag::warn_attribute_weak_import_invalid_on_definition) + << "weak_import" << 2 /*variable and function*/; + else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D) || + (S.Context.Target.getTriple().isOSDarwin() && + isa<ObjCInterfaceDecl>(D))) { + // Nothing to warn about here. + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + + return; + } + + D->addAttr(::new (S.Context) WeakImportAttr(Attr.getLoc(), S.Context)); +} + +static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, + Sema &S) { + // Attribute has 3 arguments. + if (Attr.getNumArgs() != 3) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + unsigned WGSize[3]; + for (unsigned i = 0; i < 3; ++i) { + Expr *E = Attr.getArg(i); + llvm::APSInt ArgNum(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "reqd_work_group_size" << E->getSourceRange(); + return; + } + WGSize[i] = (unsigned) ArgNum.getZExtValue(); + } + D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getLoc(), S.Context, + WGSize[0], WGSize[1], + WGSize[2])); +} + +static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { + // Attribute has no arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // Make sure that there is a string literal as the sections's single + // argument. + Expr *ArgExpr = Attr.getArg(0); + StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); + if (!SE) { + S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) << "section"; + return; + } + + // If the target wants to validate the section specifier, make it happen. + std::string Error = S.Context.Target.isValidSectionSpecifier(SE->getString()); + if (!Error.empty()) { + S.Diag(SE->getLocStart(), diag::err_attribute_section_invalid_for_target) + << Error; + return; + } + + // This attribute cannot be applied to local variables. + if (isa<VarDecl>(D) && cast<VarDecl>(D)->hasLocalStorage()) { + S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable); + return; + } + + D->addAttr(::new (S.Context) SectionAttr(Attr.getLoc(), S.Context, + SE->getString())); +} + + +static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + d->addAttr(::new (S.Context) NoThrowAttr(Attr.getLoc(), S.Context)); +} + +static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + d->addAttr(::new (S.Context) ConstAttr(Attr.getLoc(), S.Context)); +} + +static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + d->addAttr(::new (S.Context) PureAttr(Attr.getLoc(), S.Context)); +} + +static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (!Attr.getParameterName()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + VarDecl *VD = dyn_cast<VarDecl>(d); + + if (!VD || !VD->hasLocalStorage()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "cleanup"; + return; + } + + // Look up the function + // FIXME: Lookup probably isn't looking in the right place + NamedDecl *CleanupDecl + = S.LookupSingleName(S.TUScope, Attr.getParameterName(), + Attr.getParameterLoc(), Sema::LookupOrdinaryName); + if (!CleanupDecl) { + S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_arg_not_found) << + Attr.getParameterName(); + return; + } + + FunctionDecl *FD = dyn_cast<FunctionDecl>(CleanupDecl); + if (!FD) { + S.Diag(Attr.getParameterLoc(), + diag::err_attribute_cleanup_arg_not_function) + << Attr.getParameterName(); + return; + } + + if (FD->getNumParams() != 1) { + S.Diag(Attr.getParameterLoc(), + diag::err_attribute_cleanup_func_must_take_one_arg) + << Attr.getParameterName(); + return; + } + + // We're currently more strict than GCC about what function types we accept. + // If this ever proves to be a problem it should be easy to fix. + QualType Ty = S.Context.getPointerType(VD->getType()); + QualType ParamTy = FD->getParamDecl(0)->getType(); + if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), + ParamTy, Ty) != Sema::Compatible) { + S.Diag(Attr.getParameterLoc(), + diag::err_attribute_cleanup_func_arg_incompatible_type) << + Attr.getParameterName() << ParamTy << Ty; + return; + } + + d->addAttr(::new (S.Context) CleanupAttr(Attr.getLoc(), S.Context, FD)); + S.MarkDeclarationReferenced(Attr.getParameterLoc(), FD); +} + +/// Handle __attribute__((format_arg((idx)))) attribute based on +/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(d); + unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + unsigned FirstIdx = 1; + + // checks for the 2nd argument + Expr *IdxExpr = Attr.getArg(0); + llvm::APSInt Idx(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || + !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + unsigned ArgIdx = Idx.getZExtValue() - 1; + + if (HasImplicitThisParam) { + if (ArgIdx == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_implicit_this_argument) + << "format_arg" << IdxExpr->getSourceRange(); + return; + } + ArgIdx--; + } + + // make sure the format string is really a string + QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); + + bool not_nsstring_type = !isNSStringType(Ty, S.Context); + if (not_nsstring_type && + !isCFStringType(Ty, S.Context) && + (!Ty->isPointerType() || + !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << (not_nsstring_type ? "a string type" : "an NSString") + << IdxExpr->getSourceRange(); + return; + } + Ty = getFunctionOrMethodResultType(d); + if (!isNSStringType(Ty, S.Context) && + !isCFStringType(Ty, S.Context) && + (!Ty->isPointerType() || + !Ty->getAs<PointerType>()->getPointeeType()->isCharType())) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_result_not) + << (not_nsstring_type ? "string type" : "NSString") + << IdxExpr->getSourceRange(); + return; + } + + d->addAttr(::new (S.Context) FormatArgAttr(Attr.getLoc(), S.Context, + Idx.getZExtValue())); +} + +enum FormatAttrKind { + CFStringFormat, + NSStringFormat, + StrftimeFormat, + SupportedFormat, + IgnoredFormat, + InvalidFormat +}; + +/// getFormatAttrKind - Map from format attribute names to supported format +/// types. +static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) { + // Check for formats that get handled specially. + if (Format == "NSString") + return NSStringFormat; + if (Format == "CFString") + return CFStringFormat; + if (Format == "strftime") + return StrftimeFormat; + + // Otherwise, check for supported formats. + if (Format == "scanf" || Format == "printf" || Format == "printf0" || + Format == "strfmon" || Format == "cmn_err" || Format == "strftime" || + Format == "NSString" || Format == "CFString" || Format == "vcmn_err" || + Format == "zcmn_err" || + Format == "kprintf") // OpenBSD. + return SupportedFormat; + + if (Format == "gcc_diag" || Format == "gcc_cdiag" || + Format == "gcc_cxxdiag" || Format == "gcc_tdiag") + return IgnoredFormat; + + return InvalidFormat; +} + +/// Handle __attribute__((init_priority(priority))) attributes based on +/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html +static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + if (!S.getLangOptions().CPlusPlus) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + + if (!isa<VarDecl>(d) || S.getCurFunctionOrMethodDecl()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + QualType T = dyn_cast<VarDecl>(d)->getType(); + if (S.Context.getAsArrayType(T)) + T = S.Context.getBaseElementType(T); + if (!T->getAs<RecordType>()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *priorityExpr = Attr.getArg(0); + + llvm::APSInt priority(32); + if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || + !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "init_priority" << priorityExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + unsigned prioritynum = priority.getZExtValue(); + if (prioritynum < 101 || prioritynum > 65535) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range) + << priorityExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + d->addAttr(::new (S.Context) InitPriorityAttr(Attr.getLoc(), S.Context, + prioritynum)); +} + +/// Handle __attribute__((format(type,idx,firstarg))) attributes based on +/// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { + + if (!Attr.getParameterName()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "format" << 1; + return; + } + + if (Attr.getNumArgs() != 2) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 3; + return; + } + + if (!isFunctionOrMethodOrBlock(d) || !hasFunctionProto(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + // In C++ the implicit 'this' function parameter also counts, and they are + // counted from one. + bool HasImplicitThisParam = isInstanceMethod(d); + unsigned NumArgs = getFunctionOrMethodNumArgs(d) + HasImplicitThisParam; + unsigned FirstIdx = 1; + + llvm::StringRef Format = Attr.getParameterName()->getName(); + + // Normalize the argument, __foo__ becomes foo. + if (Format.startswith("__") && Format.endswith("__")) + Format = Format.substr(2, Format.size() - 4); + + // Check for supported formats. + FormatAttrKind Kind = getFormatAttrKind(Format); + + if (Kind == IgnoredFormat) + return; + + if (Kind == InvalidFormat) { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << "format" << Attr.getParameterName()->getName(); + return; + } + + // checks for the 2nd argument + Expr *IdxExpr = Attr.getArg(0); + llvm::APSInt Idx(32); + if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || + !IdxExpr->isIntegerConstantExpr(Idx, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + if (Idx.getZExtValue() < FirstIdx || Idx.getZExtValue() > NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "format" << 2 << IdxExpr->getSourceRange(); + return; + } + + // FIXME: Do we need to bounds check? + unsigned ArgIdx = Idx.getZExtValue() - 1; + + if (HasImplicitThisParam) { + if (ArgIdx == 0) { + S.Diag(Attr.getLoc(), + diag::err_format_attribute_implicit_this_format_string) + << IdxExpr->getSourceRange(); + return; + } + ArgIdx--; + } + + // make sure the format string is really a string + QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); + + if (Kind == CFStringFormat) { + if (!isCFStringType(Ty, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << "a CFString" << IdxExpr->getSourceRange(); + return; + } + } else if (Kind == NSStringFormat) { + // FIXME: do we need to check if the type is NSString*? What are the + // semantics? + if (!isNSStringType(Ty, S.Context)) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << "an NSString" << IdxExpr->getSourceRange(); + return; + } + } else if (!Ty->isPointerType() || + !Ty->getAs<PointerType>()->getPointeeType()->isCharType()) { + // FIXME: Should highlight the actual expression that has the wrong type. + S.Diag(Attr.getLoc(), diag::err_format_attribute_not) + << "a string type" << IdxExpr->getSourceRange(); + return; + } + + // check the 3rd argument + Expr *FirstArgExpr = Attr.getArg(1); + llvm::APSInt FirstArg(32); + if (FirstArgExpr->isTypeDependent() || FirstArgExpr->isValueDependent() || + !FirstArgExpr->isIntegerConstantExpr(FirstArg, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "format" << 3 << FirstArgExpr->getSourceRange(); + return; + } + + // check if the function is variadic if the 3rd argument non-zero + if (FirstArg != 0) { + if (isFunctionOrMethodVariadic(d)) { + ++NumArgs; // +1 for ... + } else { + S.Diag(d->getLocation(), diag::err_format_attribute_requires_variadic); + return; + } + } + + // strftime requires FirstArg to be 0 because it doesn't read from any + // variable the input is just the current time + the format string. + if (Kind == StrftimeFormat) { + if (FirstArg != 0) { + S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter) + << FirstArgExpr->getSourceRange(); + return; + } + // if 0 it disables parameter checking (to use with e.g. va_list) + } else if (FirstArg != 0 && FirstArg != NumArgs) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "format" << 3 << FirstArgExpr->getSourceRange(); + return; + } + + d->addAttr(::new (S.Context) FormatAttr(Attr.getLoc(), S.Context, Format, + Idx.getZExtValue(), + FirstArg.getZExtValue())); +} + +static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // Try to find the underlying union declaration. + RecordDecl *RD = 0; + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(d); + if (TD && TD->getUnderlyingType()->isUnionType()) + RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); + else + RD = dyn_cast<RecordDecl>(d); + + if (!RD || !RD->isUnion()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedUnion; + return; + } + + if (!RD->isDefinition()) { + S.Diag(Attr.getLoc(), + diag::warn_transparent_union_attribute_not_definition); + return; + } + + RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); + if (Field == FieldEnd) { + S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); + return; + } + + FieldDecl *FirstField = *Field; + QualType FirstType = FirstField->getType(); + if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { + S.Diag(FirstField->getLocation(), + diag::warn_transparent_union_attribute_floating) + << FirstType->isVectorType() << FirstType; + return; + } + + uint64_t FirstSize = S.Context.getTypeSize(FirstType); + uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); + for (; Field != FieldEnd; ++Field) { + QualType FieldType = Field->getType(); + if (S.Context.getTypeSize(FieldType) != FirstSize || + S.Context.getTypeAlign(FieldType) != FirstAlign) { + // Warn if we drop the attribute. + bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; + unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) + : S.Context.getTypeAlign(FieldType); + S.Diag(Field->getLocation(), + diag::warn_transparent_union_attribute_field_size_align) + << isSize << Field->getDeclName() << FieldBits; + unsigned FirstBits = isSize? FirstSize : FirstAlign; + S.Diag(FirstField->getLocation(), + diag::note_transparent_union_first_field_size_align) + << isSize << FirstBits; + return; + } + } + + RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getLoc(), S.Context)); +} + +static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + Expr *ArgExpr = Attr.getArg(0); + StringLiteral *SE = dyn_cast<StringLiteral>(ArgExpr); + + // Make sure that there is a string literal as the annotation's single + // argument. + if (!SE) { + S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; + return; + } + d->addAttr(::new (S.Context) AnnotateAttr(Attr.getLoc(), S.Context, + SE->getString())); +} + +static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + //FIXME: The C++0x version of this attribute has more limited applicabilty + // than GNU's, and should error out when it is used to specify a + // weaker alignment, rather than being silently ignored. + + if (Attr.getNumArgs() == 0) { + D->addAttr(::new (S.Context) AlignedAttr(Attr.getLoc(), S.Context, true, 0)); + return; + } + + S.AddAlignedAttr(Attr.getLoc(), D, Attr.getArg(0)); +} + +void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) { + if (E->isTypeDependent() || E->isValueDependent()) { + // Save dependent expressions in the AST to be instantiated. + D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E)); + return; + } + + // FIXME: Cache the number on the Attr object? + llvm::APSInt Alignment(32); + if (!E->isIntegerConstantExpr(Alignment, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_not_int) + << "aligned" << E->getSourceRange(); + return; + } + if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { + Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) + << E->getSourceRange(); + return; + } + + D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, true, E)); +} + +void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, TypeSourceInfo *TS) { + // FIXME: Cache the number on the Attr object if non-dependent? + // FIXME: Perform checking of type validity + D->addAttr(::new (Context) AlignedAttr(AttrLoc, Context, false, TS)); + return; +} + +/// HandleModeAttr - This attribute modifies the width of a decl with primitive +/// type. +/// +/// Despite what would be logical, the mode attribute is a decl attribute, not a +/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be +/// HImode, not an intermediate pointer. +static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { + // This attribute isn't documented, but glibc uses it. It changes + // the width of an int or unsigned int to the specified size. + + // Check that there aren't any arguments + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + IdentifierInfo *Name = Attr.getParameterName(); + if (!Name) { + S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name); + return; + } + + llvm::StringRef Str = Attr.getParameterName()->getName(); + + // Normalize the attribute name, __foo__ becomes foo. + if (Str.startswith("__") && Str.endswith("__")) + Str = Str.substr(2, Str.size() - 4); + + unsigned DestWidth = 0; + bool IntegerMode = true; + bool ComplexMode = false; + switch (Str.size()) { + case 2: + switch (Str[0]) { + case 'Q': DestWidth = 8; break; + case 'H': DestWidth = 16; break; + case 'S': DestWidth = 32; break; + case 'D': DestWidth = 64; break; + case 'X': DestWidth = 96; break; + case 'T': DestWidth = 128; break; + } + if (Str[1] == 'F') { + IntegerMode = false; + } else if (Str[1] == 'C') { + IntegerMode = false; + ComplexMode = true; + } else if (Str[1] != 'I') { + DestWidth = 0; + } + break; + case 4: + // FIXME: glibc uses 'word' to define register_t; this is narrower than a + // pointer on PIC16 and other embedded platforms. + if (Str == "word") + DestWidth = S.Context.Target.getPointerWidth(0); + else if (Str == "byte") + DestWidth = S.Context.Target.getCharWidth(); + break; + case 7: + if (Str == "pointer") + DestWidth = S.Context.Target.getPointerWidth(0); + break; + } + + QualType OldTy; + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) + OldTy = TD->getUnderlyingType(); + else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) + OldTy = VD->getType(); + else { + S.Diag(D->getLocation(), diag::err_attr_wrong_decl) + << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc()); + return; + } + + if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType()) + S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); + else if (IntegerMode) { + if (!OldTy->isIntegralOrEnumerationType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } else if (ComplexMode) { + if (!OldTy->isComplexType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } else { + if (!OldTy->isFloatingType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } + + // FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t + // and friends, at least with glibc. + // FIXME: Make sure 32/64-bit integers don't get defined to types of the wrong + // width on unusual platforms. + // FIXME: Make sure floating-point mappings are accurate + // FIXME: Support XF and TF types + QualType NewTy; + switch (DestWidth) { + case 0: + S.Diag(Attr.getLoc(), diag::err_unknown_machine_mode) << Name; + return; + default: + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + case 8: + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } + if (OldTy->isSignedIntegerType()) + NewTy = S.Context.SignedCharTy; + else + NewTy = S.Context.UnsignedCharTy; + break; + case 16: + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } + if (OldTy->isSignedIntegerType()) + NewTy = S.Context.ShortTy; + else + NewTy = S.Context.UnsignedShortTy; + break; + case 32: + if (!IntegerMode) + NewTy = S.Context.FloatTy; + else if (OldTy->isSignedIntegerType()) + NewTy = S.Context.IntTy; + else + NewTy = S.Context.UnsignedIntTy; + break; + case 64: + if (!IntegerMode) + NewTy = S.Context.DoubleTy; + else if (OldTy->isSignedIntegerType()) + if (S.Context.Target.getLongWidth() == 64) + NewTy = S.Context.LongTy; + else + NewTy = S.Context.LongLongTy; + else + if (S.Context.Target.getLongWidth() == 64) + NewTy = S.Context.UnsignedLongTy; + else + NewTy = S.Context.UnsignedLongLongTy; + break; + case 96: + NewTy = S.Context.LongDoubleTy; + break; + case 128: + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } + if (OldTy->isSignedIntegerType()) + NewTy = S.Context.Int128Ty; + else + NewTy = S.Context.UnsignedInt128Ty; + break; + } + + if (ComplexMode) { + NewTy = S.Context.getComplexType(NewTy); + } + + // Install the new type. + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + // FIXME: preserve existing source info. + TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy)); + } else + cast<ValueDecl>(D)->setType(NewTy); +} + +static void HandleNoDebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() > 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isFunctionOrMethod(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) NoDebugAttr(Attr.getLoc(), S.Context)); +} + +static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) NoInlineAttr(Attr.getLoc(), S.Context)); +} + +static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getLoc(), + S.Context)); +} + +static void HandleConstantAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.hasParameterOrArguments()) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<VarDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; + return; + } + + d->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getLoc(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; + } +} + +static void HandleDeviceAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d) && !isa<VarDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariableOrFunction; + return; + } + + d->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getLoc(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; + } +} + +static void HandleGlobalAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + FunctionDecl *FD = cast<FunctionDecl>(d); + if (!FD->getResultType()->isVoidType()) { + TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); + if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) { + S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) + << FD->getType() + << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(), + "void"); + } else { + S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) + << FD->getType(); + } + return; + } + + d->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getLoc(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; + } +} + +static void HandleHostAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + d->addAttr(::new (S.Context) CUDAHostAttr(Attr.getLoc(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; + } +} + +static void HandleSharedAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<VarDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedVariable; + return; + } + + d->addAttr(::new (S.Context) CUDASharedAttr(Attr.getLoc(), S.Context)); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; + } +} + +static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + FunctionDecl *Fn = dyn_cast<FunctionDecl>(d); + if (Fn == 0) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunction; + return; + } + + if (!Fn->isInlineSpecified()) { + S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); + return; + } + + d->addAttr(::new (S.Context) GNUInlineAttr(Attr.getLoc(), S.Context)); +} + +static void HandleCallConvAttr(Decl *d, const AttributeList &attr, Sema &S) { + if (hasDeclarator(d)) return; + + // Diagnostic is emitted elsewhere: here we store the (valid) attr + // in the Decl node for syntactic reasoning, e.g., pretty-printing. + CallingConv CC; + if (S.CheckCallingConvAttr(attr, CC)) + return; + + if (!isa<ObjCMethodDecl>(d)) { + S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << attr.getName() << ExpectedFunctionOrMethod; + return; + } + + switch (attr.getKind()) { + case AttributeList::AT_fastcall: + d->addAttr(::new (S.Context) FastCallAttr(attr.getLoc(), S.Context)); + return; + case AttributeList::AT_stdcall: + d->addAttr(::new (S.Context) StdCallAttr(attr.getLoc(), S.Context)); + return; + case AttributeList::AT_thiscall: + d->addAttr(::new (S.Context) ThisCallAttr(attr.getLoc(), S.Context)); + return; + case AttributeList::AT_cdecl: + d->addAttr(::new (S.Context) CDeclAttr(attr.getLoc(), S.Context)); + return; + case AttributeList::AT_pascal: + d->addAttr(::new (S.Context) PascalAttr(attr.getLoc(), S.Context)); + return; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return; + } + + llvm::StringRef StrRef = Str->getString(); + PcsAttr::PCSType PCS; + if (StrRef == "aapcs") + PCS = PcsAttr::AAPCS; + else if (StrRef == "aapcs-vfp") + PCS = PcsAttr::AAPCS_VFP; + else { + S.Diag(attr.getLoc(), diag::err_invalid_pcs); + attr.setInvalid(); + return; + } + + d->addAttr(::new (S.Context) PcsAttr(attr.getLoc(), S.Context, PCS)); + } + default: + llvm_unreachable("unexpected attribute kind"); + return; + } +} + +static void HandleOpenCLKernelAttr(Decl *d, const AttributeList &Attr, Sema &S){ + assert(Attr.isInvalid() == false); + d->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getLoc(), S.Context)); +} + +bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { + if (attr.isInvalid()) + return true; + + if ((attr.getNumArgs() != 0 && + !(attr.getKind() == AttributeList::AT_pcs && attr.getNumArgs() == 1)) || + attr.getParameterName()) { + Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + attr.setInvalid(); + return true; + } + + // TODO: diagnose uses of these conventions on the wrong target. Or, better + // move to TargetAttributesSema one day. + switch (attr.getKind()) { + case AttributeList::AT_cdecl: CC = CC_C; break; + case AttributeList::AT_fastcall: CC = CC_X86FastCall; break; + case AttributeList::AT_stdcall: CC = CC_X86StdCall; break; + case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break; + case AttributeList::AT_pascal: CC = CC_X86Pascal; break; + case AttributeList::AT_pcs: { + Expr *Arg = attr.getArg(0); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "pcs" << 1; + attr.setInvalid(); + return true; + } + + llvm::StringRef StrRef = Str->getString(); + if (StrRef == "aapcs") { + CC = CC_AAPCS; + break; + } else if (StrRef == "aapcs-vfp") { + CC = CC_AAPCS_VFP; + break; + } + // FALLS THROUGH + } + default: llvm_unreachable("unexpected attribute kind"); return true; + } + + return false; +} + +static void HandleRegparmAttr(Decl *d, const AttributeList &attr, Sema &S) { + if (hasDeclarator(d)) return; + + unsigned numParams; + if (S.CheckRegparmAttr(attr, numParams)) + return; + + if (!isa<ObjCMethodDecl>(d)) { + S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << attr.getName() << ExpectedFunctionOrMethod; + return; + } + + d->addAttr(::new (S.Context) RegparmAttr(attr.getLoc(), S.Context, numParams)); +} + +/// Checks a regparm attribute, returning true if it is ill-formed and +/// otherwise setting numParams to the appropriate value. +bool Sema::CheckRegparmAttr(const AttributeList &attr, unsigned &numParams) { + if (attr.isInvalid()) + return true; + + if (attr.getNumArgs() != 1) { + Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + attr.setInvalid(); + return true; + } + + Expr *NumParamsExpr = attr.getArg(0); + llvm::APSInt NumParams(32); + if (NumParamsExpr->isTypeDependent() || NumParamsExpr->isValueDependent() || + !NumParamsExpr->isIntegerConstantExpr(NumParams, Context)) { + Diag(attr.getLoc(), diag::err_attribute_argument_not_int) + << "regparm" << NumParamsExpr->getSourceRange(); + attr.setInvalid(); + return true; + } + + if (Context.Target.getRegParmMax() == 0) { + Diag(attr.getLoc(), diag::err_attribute_regparm_wrong_platform) + << NumParamsExpr->getSourceRange(); + attr.setInvalid(); + return true; + } + + numParams = NumParams.getZExtValue(); + if (numParams > Context.Target.getRegParmMax()) { + Diag(attr.getLoc(), diag::err_attribute_regparm_invalid_number) + << Context.Target.getRegParmMax() << NumParamsExpr->getSourceRange(); + attr.setInvalid(); + return true; + } + + return false; +} + +static void HandleLaunchBoundsAttr(Decl *d, const AttributeList &Attr, Sema &S){ + if (S.LangOpts.CUDA) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1 && Attr.getNumArgs() != 2) { + // FIXME: 0 is not okay. + S.Diag(Attr.getLoc(), diag::err_attribute_too_many_arguments) << 2; + return; + } + + if (!isFunctionOrMethod(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + Expr *MaxThreadsExpr = Attr.getArg(0); + llvm::APSInt MaxThreads(32); + if (MaxThreadsExpr->isTypeDependent() || + MaxThreadsExpr->isValueDependent() || + !MaxThreadsExpr->isIntegerConstantExpr(MaxThreads, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "launch_bounds" << 1 << MaxThreadsExpr->getSourceRange(); + return; + } + + llvm::APSInt MinBlocks(32); + if (Attr.getNumArgs() > 1) { + Expr *MinBlocksExpr = Attr.getArg(1); + if (MinBlocksExpr->isTypeDependent() || + MinBlocksExpr->isValueDependent() || + !MinBlocksExpr->isIntegerConstantExpr(MinBlocks, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_int) + << "launch_bounds" << 2 << MinBlocksExpr->getSourceRange(); + return; + } + } + + d->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getLoc(), S.Context, + MaxThreads.getZExtValue(), + MinBlocks.getZExtValue())); + } else { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds"; + } +} + +//===----------------------------------------------------------------------===// +// Checker-specific attribute handlers. +//===----------------------------------------------------------------------===// + +static bool isValidSubjectOfNSAttribute(Sema &S, QualType type) { + return type->isObjCObjectPointerType() || S.Context.isObjCNSObjectType(type); +} +static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) { + return type->isPointerType() || isValidSubjectOfNSAttribute(S, type); +} + +static void HandleNSConsumedAttr(Decl *d, const AttributeList &attr, Sema &S) { + ParmVarDecl *param = dyn_cast<ParmVarDecl>(d); + if (!param) { + S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) + << SourceRange(attr.getLoc()) << attr.getName() << ExpectedParameter; + return; + } + + bool typeOK, cf; + if (attr.getKind() == AttributeList::AT_ns_consumed) { + typeOK = isValidSubjectOfNSAttribute(S, param->getType()); + cf = false; + } else { + typeOK = isValidSubjectOfCFAttribute(S, param->getType()); + cf = true; + } + + if (!typeOK) { + S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_parameter_type) + << SourceRange(attr.getLoc()) << attr.getName() << cf; + return; + } + + if (cf) + param->addAttr(::new (S.Context) CFConsumedAttr(attr.getLoc(), S.Context)); + else + param->addAttr(::new (S.Context) NSConsumedAttr(attr.getLoc(), S.Context)); +} + +static void HandleNSConsumesSelfAttr(Decl *d, const AttributeList &attr, + Sema &S) { + if (!isa<ObjCMethodDecl>(d)) { + S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) + << SourceRange(attr.getLoc()) << attr.getName() << ExpectedMethod; + return; + } + + d->addAttr(::new (S.Context) NSConsumesSelfAttr(attr.getLoc(), S.Context)); +} + +static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr, + Sema &S) { + + QualType returnType; + + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d)) + returnType = MD->getResultType(); + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d)) + returnType = FD->getResultType(); + else { + S.Diag(d->getLocStart(), diag::warn_attribute_wrong_decl_type) + << SourceRange(attr.getLoc()) << attr.getName() + << ExpectedFunctionOrMethod; + return; + } + + bool typeOK; + bool cf; + switch (attr.getKind()) { + default: llvm_unreachable("invalid ownership attribute"); return; + case AttributeList::AT_ns_returns_autoreleased: + case AttributeList::AT_ns_returns_retained: + case AttributeList::AT_ns_returns_not_retained: + typeOK = isValidSubjectOfNSAttribute(S, returnType); + cf = false; + break; + + case AttributeList::AT_cf_returns_retained: + case AttributeList::AT_cf_returns_not_retained: + typeOK = isValidSubjectOfCFAttribute(S, returnType); + cf = true; + break; + } + + if (!typeOK) { + S.Diag(d->getLocStart(), diag::warn_ns_attribute_wrong_return_type) + << SourceRange(attr.getLoc()) + << attr.getName() << isa<ObjCMethodDecl>(d) << cf; + return; + } + + switch (attr.getKind()) { + default: + assert(0 && "invalid ownership attribute"); + return; + case AttributeList::AT_ns_returns_autoreleased: + d->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(attr.getLoc(), + S.Context)); + return; + case AttributeList::AT_cf_returns_not_retained: + d->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(attr.getLoc(), + S.Context)); + return; + case AttributeList::AT_ns_returns_not_retained: + d->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(attr.getLoc(), + S.Context)); + return; + case AttributeList::AT_cf_returns_retained: + d->addAttr(::new (S.Context) CFReturnsRetainedAttr(attr.getLoc(), + S.Context)); + return; + case AttributeList::AT_ns_returns_retained: + d->addAttr(::new (S.Context) NSReturnsRetainedAttr(attr.getLoc(), + S.Context)); + return; + }; +} + +static bool isKnownDeclSpecAttr(const AttributeList &Attr) { + return Attr.getKind() == AttributeList::AT_dllimport || + Attr.getKind() == AttributeList::AT_dllexport || + Attr.getKind() == AttributeList::AT_uuid; +} + +//===----------------------------------------------------------------------===// +// Microsoft specific attribute handlers. +//===----------------------------------------------------------------------===// + +static void HandleUuidAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (S.LangOpts.Microsoft || S.LangOpts.Borland) { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + Expr *Arg = Attr.getArg(0); + StringLiteral *Str = dyn_cast<StringLiteral>(Arg); + if (Str == 0 || Str->isWide()) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "uuid" << 1; + return; + } + + llvm::StringRef StrRef = Str->getString(); + + bool IsCurly = StrRef.size() > 1 && StrRef.front() == '{' && + StrRef.back() == '}'; + + // Validate GUID length. + if (IsCurly && StrRef.size() != 38) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + if (!IsCurly && StrRef.size() != 36) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + + // GUID format is "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" or + // "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" + llvm::StringRef::iterator I = StrRef.begin(); + if (IsCurly) // Skip the optional '{' + ++I; + + for (int i = 0; i < 36; ++i) { + if (i == 8 || i == 13 || i == 18 || i == 23) { + if (*I != '-') { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + } else if (!isxdigit(*I)) { + S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); + return; + } + I++; + } + + d->addAttr(::new (S.Context) UuidAttr(Attr.getLoc(), S.Context, + Str->getString())); + } else + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; +} + +//===----------------------------------------------------------------------===// +// Top Level Sema Entry Points +//===----------------------------------------------------------------------===// + +static void ProcessNonInheritableDeclAttr(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) { + switch (Attr.getKind()) { + case AttributeList::AT_device: HandleDeviceAttr (D, Attr, S); break; + case AttributeList::AT_host: HandleHostAttr (D, Attr, S); break; + case AttributeList::AT_overloadable:HandleOverloadableAttr(D, Attr, S); break; + default: + break; + } +} + +static void ProcessInheritableDeclAttr(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) { + switch (Attr.getKind()) { + case AttributeList::AT_IBAction: HandleIBAction(D, Attr, S); break; + case AttributeList::AT_IBOutlet: HandleIBOutlet(D, Attr, S); break; + case AttributeList::AT_IBOutletCollection: + HandleIBOutletCollection(D, Attr, S); break; + case AttributeList::AT_address_space: + case AttributeList::AT_opencl_image_access: + case AttributeList::AT_objc_gc: + case AttributeList::AT_vector_size: + case AttributeList::AT_neon_vector_type: + case AttributeList::AT_neon_polyvector_type: + // Ignore these, these are type attributes, handled by + // ProcessTypeAttributes. + break; + case AttributeList::AT_device: + case AttributeList::AT_host: + case AttributeList::AT_overloadable: + // Ignore, this is a non-inheritable attribute, handled + // by ProcessNonInheritableDeclAttr. + break; + case AttributeList::AT_alias: HandleAliasAttr (D, Attr, S); break; + case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; + case AttributeList::AT_always_inline: + HandleAlwaysInlineAttr (D, Attr, S); break; + case AttributeList::AT_analyzer_noreturn: + HandleAnalyzerNoReturnAttr (D, Attr, S); break; + case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; + case AttributeList::AT_availability:HandleAvailabilityAttr(D, Attr, S); break; + case AttributeList::AT_carries_dependency: + HandleDependencyAttr (D, Attr, S); break; + case AttributeList::AT_common: HandleCommonAttr (D, Attr, S); break; + case AttributeList::AT_constant: HandleConstantAttr (D, Attr, S); break; + case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break; + case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break; + case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break; + case AttributeList::AT_ext_vector_type: + HandleExtVectorTypeAttr(scope, D, Attr, S); + break; + case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; + case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; + case AttributeList::AT_global: HandleGlobalAttr (D, Attr, S); break; + case AttributeList::AT_gnu_inline: HandleGNUInlineAttr (D, Attr, S); break; + case AttributeList::AT_launch_bounds: + HandleLaunchBoundsAttr(D, Attr, S); + break; + case AttributeList::AT_mode: HandleModeAttr (D, Attr, S); break; + case AttributeList::AT_malloc: HandleMallocAttr (D, Attr, S); break; + case AttributeList::AT_may_alias: HandleMayAliasAttr (D, Attr, S); break; + case AttributeList::AT_nocommon: HandleNoCommonAttr (D, Attr, S); break; + case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; + case AttributeList::AT_ownership_returns: + case AttributeList::AT_ownership_takes: + case AttributeList::AT_ownership_holds: + HandleOwnershipAttr (D, Attr, S); break; + case AttributeList::AT_naked: HandleNakedAttr (D, Attr, S); break; + case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; + case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; + case AttributeList::AT_shared: HandleSharedAttr (D, Attr, S); break; + case AttributeList::AT_vecreturn: HandleVecReturnAttr (D, Attr, S); break; + + // Checker-specific. + case AttributeList::AT_cf_consumed: + case AttributeList::AT_ns_consumed: HandleNSConsumedAttr (D, Attr, S); break; + case AttributeList::AT_ns_consumes_self: + HandleNSConsumesSelfAttr(D, Attr, S); break; + + case AttributeList::AT_ns_returns_autoreleased: + case AttributeList::AT_ns_returns_not_retained: + case AttributeList::AT_cf_returns_not_retained: + case AttributeList::AT_ns_returns_retained: + case AttributeList::AT_cf_returns_retained: + HandleNSReturnsRetainedAttr(D, Attr, S); break; + + case AttributeList::AT_reqd_wg_size: + HandleReqdWorkGroupSize(D, Attr, S); break; + + case AttributeList::AT_init_priority: + HandleInitPriorityAttr(D, Attr, S); break; + + case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; + case AttributeList::AT_MsStruct: HandleMsStructAttr (D, Attr, S); break; + case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; + case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break; + case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; + case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; + case AttributeList::AT_visibility: HandleVisibilityAttr (D, Attr, S); break; + case AttributeList::AT_warn_unused_result: HandleWarnUnusedResult(D,Attr,S); + break; + case AttributeList::AT_weak: HandleWeakAttr (D, Attr, S); break; + case AttributeList::AT_weakref: HandleWeakRefAttr (D, Attr, S); break; + case AttributeList::AT_weak_import: HandleWeakImportAttr (D, Attr, S); break; + case AttributeList::AT_transparent_union: + HandleTransparentUnionAttr(D, Attr, S); + break; + case AttributeList::AT_objc_exception: + HandleObjCExceptionAttr(D, Attr, S); + break; + case AttributeList::AT_objc_method_family: + HandleObjCMethodFamilyAttr(D, Attr, S); + break; + case AttributeList::AT_nsobject: HandleObjCNSObject (D, Attr, S); break; + case AttributeList::AT_blocks: HandleBlocksAttr (D, Attr, S); break; + case AttributeList::AT_sentinel: HandleSentinelAttr (D, Attr, S); break; + case AttributeList::AT_const: HandleConstAttr (D, Attr, S); break; + case AttributeList::AT_pure: HandlePureAttr (D, Attr, S); break; + case AttributeList::AT_cleanup: HandleCleanupAttr (D, Attr, S); break; + case AttributeList::AT_nodebug: HandleNoDebugAttr (D, Attr, S); break; + case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break; + case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; + case AttributeList::IgnoredAttribute: + // Just ignore + break; + case AttributeList::AT_no_instrument_function: // Interacts with -pg. + HandleNoInstrumentFunctionAttr(D, Attr, S); + break; + case AttributeList::AT_stdcall: + case AttributeList::AT_cdecl: + case AttributeList::AT_fastcall: + case AttributeList::AT_thiscall: + case AttributeList::AT_pascal: + case AttributeList::AT_pcs: + HandleCallConvAttr(D, Attr, S); + break; + case AttributeList::AT_opencl_kernel_function: + HandleOpenCLKernelAttr(D, Attr, S); + break; + case AttributeList::AT_uuid: + HandleUuidAttr(D, Attr, S); + break; + default: + // Ask target about the attribute. + const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); + if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) + S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) + << Attr.getName(); + break; + } +} + +/// ProcessDeclAttribute - Apply the specific attribute to the specified decl if +/// the attribute applies to decls. If the attribute is a type attribute, just +/// silently ignore it if a GNU attribute. FIXME: Applying a C++0x attribute to +/// the wrong thing is illegal (C++0x [dcl.attr.grammar]/4). +static void ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S, + bool NonInheritable, bool Inheritable) { + if (Attr.isInvalid()) + return; + + if (Attr.isDeclspecAttribute() && !isKnownDeclSpecAttr(Attr)) + // FIXME: Try to deal with other __declspec attributes! + return; + + if (NonInheritable) + ProcessNonInheritableDeclAttr(scope, D, Attr, S); + + if (Inheritable) + ProcessInheritableDeclAttr(scope, D, Attr, S); +} + +/// ProcessDeclAttributeList - Apply all the decl attributes in the specified +/// attribute list to the specified decl, ignoring any type attributes. +void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, + const AttributeList *AttrList, + bool NonInheritable, bool Inheritable) { + for (const AttributeList* l = AttrList; l; l = l->getNext()) { + ProcessDeclAttribute(S, D, *l, *this, NonInheritable, Inheritable); + } + + // GCC accepts + // static int a9 __attribute__((weakref)); + // but that looks really pointless. We reject it. + if (Inheritable && D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { + Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) << + dyn_cast<NamedDecl>(D)->getNameAsString(); + return; + } +} + +/// DeclClonePragmaWeak - clone existing decl (maybe definition), +/// #pragma weak needs a non-definition decl and source may not have one +NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) { + assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND)); + NamedDecl *NewD = 0; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), + FD->getInnerLocStart(), + FD->getLocation(), DeclarationName(II), + FD->getType(), FD->getTypeSourceInfo()); + if (FD->getQualifier()) { + FunctionDecl *NewFD = cast<FunctionDecl>(NewD); + NewFD->setQualifierInfo(FD->getQualifierLoc()); + } + } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) { + NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), + VD->getInnerLocStart(), VD->getLocation(), II, + VD->getType(), VD->getTypeSourceInfo(), + VD->getStorageClass(), + VD->getStorageClassAsWritten()); + if (VD->getQualifier()) { + VarDecl *NewVD = cast<VarDecl>(NewD); + NewVD->setQualifierInfo(VD->getQualifierLoc()); + } + } + return NewD; +} + +/// DeclApplyPragmaWeak - A declaration (maybe definition) needs #pragma weak +/// applied to it, possibly with an alias. +void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { + if (W.getUsed()) return; // only do this once + W.setUsed(true); + if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) + IdentifierInfo *NDId = ND->getIdentifier(); + NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias()); + NewD->addAttr(::new (Context) AliasAttr(W.getLocation(), Context, + NDId->getName())); + NewD->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); + WeakTopLevelDecl.push_back(NewD); + // FIXME: "hideous" code from Sema::LazilyCreateBuiltin + // to insert Decl at TU scope, sorry. + DeclContext *SavedContext = CurContext; + CurContext = Context.getTranslationUnitDecl(); + PushOnScopeChains(NewD, S); + CurContext = SavedContext; + } else { // just add weak to existing + ND->addAttr(::new (Context) WeakAttr(W.getLocation(), Context)); + } +} + +/// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in +/// it, apply them to D. This is a bit tricky because PD can have attributes +/// specified in many different places, and we need to find and apply them all. +void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, + bool NonInheritable, bool Inheritable) { + // It's valid to "forward-declare" #pragma weak, in which case we + // have to do this. + if (Inheritable && !WeakUndeclaredIdentifiers.empty()) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { + if (IdentifierInfo *Id = ND->getIdentifier()) { + llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I + = WeakUndeclaredIdentifiers.find(Id); + if (I != WeakUndeclaredIdentifiers.end() && ND->hasLinkage()) { + WeakInfo W = I->second; + DeclApplyPragmaWeak(S, ND, W); + WeakUndeclaredIdentifiers[Id] = W; + } + } + } + } + + // Apply decl attributes from the DeclSpec if present. + if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); + + // Walk the declarator structure, applying decl attributes that were in a type + // position to the decl itself. This handles cases like: + // int *__attr__(x)** D; + // when X is a decl attribute. + for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) + if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); + + // Finally, apply any attributes on the decl itself. + if (const AttributeList *Attrs = PD.getAttributes()) + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); +} + +// This duplicates a vector push_back but hides the need to know the +// size of the type. +void Sema::DelayedDiagnostics::add(const DelayedDiagnostic &diag) { + assert(StackSize <= StackCapacity); + + // Grow the stack if necessary. + if (StackSize == StackCapacity) { + unsigned newCapacity = 2 * StackCapacity + 2; + char *newBuffer = new char[newCapacity * sizeof(DelayedDiagnostic)]; + const char *oldBuffer = (const char*) Stack; + + if (StackCapacity) + memcpy(newBuffer, oldBuffer, StackCapacity * sizeof(DelayedDiagnostic)); + + delete[] oldBuffer; + Stack = reinterpret_cast<sema::DelayedDiagnostic*>(newBuffer); + StackCapacity = newCapacity; + } + + assert(StackSize < StackCapacity); + new (&Stack[StackSize++]) DelayedDiagnostic(diag); +} + +void Sema::DelayedDiagnostics::popParsingDecl(Sema &S, ParsingDeclState state, + Decl *decl) { + DelayedDiagnostics &DD = S.DelayedDiagnostics; + + // Check the invariants. + assert(DD.StackSize >= state.SavedStackSize); + assert(state.SavedStackSize >= DD.ActiveStackBase); + assert(DD.ParsingDepth > 0); + + // Drop the parsing depth. + DD.ParsingDepth--; + + // If there are no active diagnostics, we're done. + if (DD.StackSize == DD.ActiveStackBase) + return; + + // We only want to actually emit delayed diagnostics when we + // successfully parsed a decl. + if (decl) { + // We emit all the active diagnostics, not just those starting + // from the saved state. The idea is this: we get one push for a + // decl spec and another for each declarator; in a decl group like: + // deprecated_typedef foo, *bar, baz(); + // only the declarator pops will be passed decls. This is correct; + // we really do need to consider delayed diagnostics from the decl spec + // for each of the different declarations. + for (unsigned i = DD.ActiveStackBase, e = DD.StackSize; i != e; ++i) { + DelayedDiagnostic &diag = DD.Stack[i]; + if (diag.Triggered) + continue; + + switch (diag.Kind) { + case DelayedDiagnostic::Deprecation: + S.HandleDelayedDeprecationCheck(diag, decl); + break; + + case DelayedDiagnostic::Access: + S.HandleDelayedAccessCheck(diag, decl); + break; + } + } + } + + // Destroy all the delayed diagnostics we're about to pop off. + for (unsigned i = state.SavedStackSize, e = DD.StackSize; i != e; ++i) + DD.Stack[i].Destroy(); + + DD.StackSize = state.SavedStackSize; +} + +static bool isDeclDeprecated(Decl *D) { + do { + if (D->isDeprecated()) + return true; + } while ((D = cast_or_null<Decl>(D->getDeclContext()))); + return false; +} + +void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, + Decl *Ctx) { + if (isDeclDeprecated(Ctx)) + return; + + DD.Triggered = true; + if (!DD.getDeprecationMessage().empty()) + Diag(DD.Loc, diag::warn_deprecated_message) + << DD.getDeprecationDecl()->getDeclName() + << DD.getDeprecationMessage(); + else + Diag(DD.Loc, diag::warn_deprecated) + << DD.getDeprecationDecl()->getDeclName(); +} + +void Sema::EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message, + SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass) { + // Delay if we're currently parsing a declaration. + if (DelayedDiagnostics.shouldDelayDiagnostics()) { + DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, Message)); + return; + } + + // Otherwise, don't warn if our current context is deprecated. + if (isDeclDeprecated(cast<Decl>(CurContext))) + return; + if (!Message.empty()) + Diag(Loc, diag::warn_deprecated_message) << D->getDeclName() + << Message; + else { + if (!UnknownObjCClass) + Diag(Loc, diag::warn_deprecated) << D->getDeclName(); + else { + Diag(Loc, diag::warn_deprecated_fwdclass_message) << D->getDeclName(); + Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp new file mode 100644 index 0000000..ce99efb --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -0,0 +1,9320 @@ +//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for C++ declarations. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/CharUnits.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeOrdering.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include <map> +#include <set> + +using namespace clang; + +//===----------------------------------------------------------------------===// +// CheckDefaultArgumentVisitor +//===----------------------------------------------------------------------===// + +namespace { + /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses + /// the default argument of a parameter to determine whether it + /// contains any ill-formed subexpressions. For example, this will + /// diagnose the use of local variables or parameters within the + /// default argument expression. + class CheckDefaultArgumentVisitor + : public StmtVisitor<CheckDefaultArgumentVisitor, bool> { + Expr *DefaultArg; + Sema *S; + + public: + CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) + : DefaultArg(defarg), S(s) {} + + bool VisitExpr(Expr *Node); + bool VisitDeclRefExpr(DeclRefExpr *DRE); + bool VisitCXXThisExpr(CXXThisExpr *ThisE); + }; + + /// VisitExpr - Visit all of the children of this expression. + bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) { + bool IsInvalid = false; + for (Stmt::child_range I = Node->children(); I; ++I) + IsInvalid |= Visit(*I); + return IsInvalid; + } + + /// VisitDeclRefExpr - Visit a reference to a declaration, to + /// determine whether this declaration can be used in the default + /// argument expression. + bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) { + NamedDecl *Decl = DRE->getDecl(); + if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) { + // C++ [dcl.fct.default]p9 + // Default arguments are evaluated each time the function is + // called. The order of evaluation of function arguments is + // unspecified. Consequently, parameters of a function shall not + // be used in default argument expressions, even if they are not + // evaluated. Parameters of a function declared before a default + // argument expression are in scope and can hide namespace and + // class member names. + return S->Diag(DRE->getSourceRange().getBegin(), + diag::err_param_default_argument_references_param) + << Param->getDeclName() << DefaultArg->getSourceRange(); + } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) { + // C++ [dcl.fct.default]p7 + // Local variables shall not be used in default argument + // expressions. + if (VDecl->isLocalVarDecl()) + return S->Diag(DRE->getSourceRange().getBegin(), + diag::err_param_default_argument_references_local) + << VDecl->getDeclName() << DefaultArg->getSourceRange(); + } + + return false; + } + + /// VisitCXXThisExpr - Visit a C++ "this" expression. + bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) { + // C++ [dcl.fct.default]p8: + // The keyword this shall not be used in a default argument of a + // member function. + return S->Diag(ThisE->getSourceRange().getBegin(), + diag::err_param_default_argument_references_this) + << ThisE->getSourceRange(); + } +} + +void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) { + assert(Context && "ImplicitExceptionSpecification without an ASTContext"); + // If we have an MSAny or unknown spec already, don't bother. + if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed) + return; + + const FunctionProtoType *Proto + = Method->getType()->getAs<FunctionProtoType>(); + + ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + + // If this function can throw any exceptions, make a note of that. + if (EST == EST_Delayed || EST == EST_MSAny || EST == EST_None) { + ClearExceptions(); + ComputedEST = EST; + return; + } + + // FIXME: If the call to this decl is using any of its default arguments, we + // need to search them for potentially-throwing calls. + + // If this function has a basic noexcept, it doesn't affect the outcome. + if (EST == EST_BasicNoexcept) + return; + + // If we have a throw-all spec at this point, ignore the function. + if (ComputedEST == EST_None) + return; + + // If we're still at noexcept(true) and there's a nothrow() callee, + // change to that specification. + if (EST == EST_DynamicNone) { + if (ComputedEST == EST_BasicNoexcept) + ComputedEST = EST_DynamicNone; + return; + } + + // Check out noexcept specs. + if (EST == EST_ComputedNoexcept) { + FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(*Context); + assert(NR != FunctionProtoType::NR_NoNoexcept && + "Must have noexcept result for EST_ComputedNoexcept."); + assert(NR != FunctionProtoType::NR_Dependent && + "Should not generate implicit declarations for dependent cases, " + "and don't know how to handle them anyway."); + + // noexcept(false) -> no spec on the new function + if (NR == FunctionProtoType::NR_Throw) { + ClearExceptions(); + ComputedEST = EST_None; + } + // noexcept(true) won't change anything either. + return; + } + + assert(EST == EST_Dynamic && "EST case not considered earlier."); + assert(ComputedEST != EST_None && + "Shouldn't collect exceptions when throw-all is guaranteed."); + ComputedEST = EST_Dynamic; + // Record the exceptions in this function's exception specification. + for (FunctionProtoType::exception_iterator E = Proto->exception_begin(), + EEnd = Proto->exception_end(); + E != EEnd; ++E) + if (ExceptionsSeen.insert(Context->getCanonicalType(*E))) + Exceptions.push_back(*E); +} + +void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) { + if (!E || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed) + return; + + // FIXME: + // + // C++0x [except.spec]p14: + // [An] implicit exception-specification specifies the type-id T if and + // only if T is allowed by the exception-specification of a function directly + // invoked by f’s implicit definition; f shall allow all exceptions if any + // function it directly invokes allows all exceptions, and f shall allow no + // exceptions if every function it directly invokes allows no exceptions. + // + // Note in particular that if an implicit exception-specification is generated + // for a function containing a throw-expression, that specification can still + // be noexcept(true). + // + // Note also that 'directly invoked' is not defined in the standard, and there + // is no indication that we should only consider potentially-evaluated calls. + // + // Ultimately we should implement the intent of the standard: the exception + // specification should be the set of exceptions which can be thrown by the + // implicit definition. For now, we assume that any non-nothrow expression can + // throw any exception. + + if (E->CanThrow(*Context)) + ComputedEST = EST_None; +} + +bool +Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, + SourceLocation EqualLoc) { + if (RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) { + Param->setInvalidDecl(); + return true; + } + + // C++ [dcl.fct.default]p5 + // A default argument expression is implicitly converted (clause + // 4) to the parameter type. The default argument expression has + // the same semantic constraints as the initializer expression in + // a declaration of a variable of the parameter type, using the + // copy-initialization semantics (8.5). + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + Param); + InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), + EqualLoc); + InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &Arg, 1)); + if (Result.isInvalid()) + return true; + Arg = Result.takeAs<Expr>(); + + CheckImplicitConversions(Arg, EqualLoc); + Arg = MaybeCreateExprWithCleanups(Arg); + + // Okay: add the default argument to the parameter + Param->setDefaultArg(Arg); + + // We have already instantiated this parameter; provide each of the + // instantiations with the uninstantiated default argument. + UnparsedDefaultArgInstantiationsMap::iterator InstPos + = UnparsedDefaultArgInstantiations.find(Param); + if (InstPos != UnparsedDefaultArgInstantiations.end()) { + for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I) + InstPos->second[I]->setUninstantiatedDefaultArg(Arg); + + // We're done tracking this parameter's instantiations. + UnparsedDefaultArgInstantiations.erase(InstPos); + } + + return false; +} + +/// ActOnParamDefaultArgument - Check whether the default argument +/// provided for a function parameter is well-formed. If so, attach it +/// to the parameter declaration. +void +Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, + Expr *DefaultArg) { + if (!param || !DefaultArg) + return; + + ParmVarDecl *Param = cast<ParmVarDecl>(param); + UnparsedDefaultArgLocs.erase(Param); + + // Default arguments are only permitted in C++ + if (!getLangOptions().CPlusPlus) { + Diag(EqualLoc, diag::err_param_default_argument) + << DefaultArg->getSourceRange(); + Param->setInvalidDecl(); + return; + } + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) { + Param->setInvalidDecl(); + return; + } + + // Check that the default argument is well-formed + CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); + if (DefaultArgChecker.Visit(DefaultArg)) { + Param->setInvalidDecl(); + return; + } + + SetParamDefaultArgument(Param, DefaultArg, EqualLoc); +} + +/// ActOnParamUnparsedDefaultArgument - We've seen a default +/// argument for a function parameter, but we can't parse it yet +/// because we're inside a class definition. Note that this default +/// argument will be parsed later. +void Sema::ActOnParamUnparsedDefaultArgument(Decl *param, + SourceLocation EqualLoc, + SourceLocation ArgLoc) { + if (!param) + return; + + ParmVarDecl *Param = cast<ParmVarDecl>(param); + if (Param) + Param->setUnparsedDefaultArg(); + + UnparsedDefaultArgLocs[Param] = ArgLoc; +} + +/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of +/// the default argument for the parameter param failed. +void Sema::ActOnParamDefaultArgumentError(Decl *param) { + if (!param) + return; + + ParmVarDecl *Param = cast<ParmVarDecl>(param); + + Param->setInvalidDecl(); + + UnparsedDefaultArgLocs.erase(Param); +} + +/// CheckExtraCXXDefaultArguments - Check for any extra default +/// arguments in the declarator, which is not a function declaration +/// or definition and therefore is not permitted to have default +/// arguments. This routine should be invoked for every declarator +/// that is not a function declaration or definition. +void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { + // C++ [dcl.fct.default]p3 + // A default argument expression shall be specified only in the + // parameter-declaration-clause of a function declaration or in a + // template-parameter (14.1). It shall not be specified for a + // parameter pack. If it is specified in a + // parameter-declaration-clause, it shall not occur within a + // declarator or abstract-declarator of a parameter-declaration. + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + DeclaratorChunk &chunk = D.getTypeObject(i); + if (chunk.Kind == DeclaratorChunk::Function) { + for (unsigned argIdx = 0, e = chunk.Fun.NumArgs; argIdx != e; ++argIdx) { + ParmVarDecl *Param = + cast<ParmVarDecl>(chunk.Fun.ArgInfo[argIdx].Param); + if (Param->hasUnparsedDefaultArg()) { + CachedTokens *Toks = chunk.Fun.ArgInfo[argIdx].DefaultArgTokens; + Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) + << SourceRange((*Toks)[1].getLocation(), Toks->back().getLocation()); + delete Toks; + chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0; + } else if (Param->getDefaultArg()) { + Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) + << Param->getDefaultArg()->getSourceRange(); + Param->setDefaultArg(0); + } + } + } + } +} + +// MergeCXXFunctionDecl - Merge two declarations of the same C++ +// function, once we already know that they have the same +// type. Subroutine of MergeFunctionDecl. Returns true if there was an +// error, false otherwise. +bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { + bool Invalid = false; + + // C++ [dcl.fct.default]p4: + // For non-template functions, default arguments can be added in + // later declarations of a function in the same + // scope. Declarations in different scopes have completely + // distinct sets of default arguments. That is, declarations in + // inner scopes do not acquire default arguments from + // declarations in outer scopes, and vice versa. In a given + // function declaration, all parameters subsequent to a + // parameter with a default argument shall have default + // arguments supplied in this or previous declarations. A + // default argument shall not be redefined by a later + // declaration (not even to the same value). + // + // C++ [dcl.fct.default]p6: + // Except for member functions of class templates, the default arguments + // in a member function definition that appears outside of the class + // definition are added to the set of default arguments provided by the + // member function declaration in the class definition. + for (unsigned p = 0, NumParams = Old->getNumParams(); p < NumParams; ++p) { + ParmVarDecl *OldParam = Old->getParamDecl(p); + ParmVarDecl *NewParam = New->getParamDecl(p); + + if (OldParam->hasDefaultArg() && NewParam->hasDefaultArg()) { + + unsigned DiagDefaultParamID = + diag::err_param_default_argument_redefinition; + + // MSVC accepts that default parameters be redefined for member functions + // of template class. The new default parameter's value is ignored. + Invalid = true; + if (getLangOptions().Microsoft) { + CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(New); + if (MD && MD->getParent()->getDescribedClassTemplate()) { + // Merge the old default argument into the new parameter. + NewParam->setHasInheritedDefaultArg(); + if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getInit()); + DiagDefaultParamID = diag::warn_param_default_argument_redefinition; + Invalid = false; + } + } + + // FIXME: If we knew where the '=' was, we could easily provide a fix-it + // hint here. Alternatively, we could walk the type-source information + // for NewParam to find the last source location in the type... but it + // isn't worth the effort right now. This is the kind of test case that + // is hard to get right: + // int f(int); + // void g(int (*fp)(int) = f); + // void g(int (*fp)(int) = &f); + Diag(NewParam->getLocation(), DiagDefaultParamID) + << NewParam->getDefaultArgRange(); + + // Look for the function declaration where the default argument was + // actually written, which may be a declaration prior to Old. + for (FunctionDecl *Older = Old->getPreviousDeclaration(); + Older; Older = Older->getPreviousDeclaration()) { + if (!Older->getParamDecl(p)->hasDefaultArg()) + break; + + OldParam = Older->getParamDecl(p); + } + + Diag(OldParam->getLocation(), diag::note_previous_definition) + << OldParam->getDefaultArgRange(); + } else if (OldParam->hasDefaultArg()) { + // Merge the old default argument into the new parameter. + // It's important to use getInit() here; getDefaultArg() + // strips off any top-level ExprWithCleanups. + NewParam->setHasInheritedDefaultArg(); + if (OldParam->hasUninstantiatedDefaultArg()) + NewParam->setUninstantiatedDefaultArg( + OldParam->getUninstantiatedDefaultArg()); + else + NewParam->setDefaultArg(OldParam->getInit()); + } else if (NewParam->hasDefaultArg()) { + if (New->getDescribedFunctionTemplate()) { + // Paragraph 4, quoted above, only applies to non-template functions. + Diag(NewParam->getLocation(), + diag::err_param_default_argument_template_redecl) + << NewParam->getDefaultArgRange(); + Diag(Old->getLocation(), diag::note_template_prev_declaration) + << false; + } else if (New->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation && + New->getTemplateSpecializationKind() != TSK_Undeclared) { + // C++ [temp.expr.spec]p21: + // Default function arguments shall not be specified in a declaration + // or a definition for one of the following explicit specializations: + // - the explicit specialization of a function template; + // - the explicit specialization of a member function template; + // - the explicit specialization of a member function of a class + // template where the class template specialization to which the + // member function specialization belongs is implicitly + // instantiated. + Diag(NewParam->getLocation(), diag::err_template_spec_default_arg) + << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization) + << New->getDeclName() + << NewParam->getDefaultArgRange(); + } else if (New->getDeclContext()->isDependentContext()) { + // C++ [dcl.fct.default]p6 (DR217): + // Default arguments for a member function of a class template shall + // be specified on the initial declaration of the member function + // within the class template. + // + // Reading the tea leaves a bit in DR217 and its reference to DR205 + // leads me to the conclusion that one cannot add default function + // arguments for an out-of-line definition of a member function of a + // dependent type. + int WhichKind = 2; + if (CXXRecordDecl *Record + = dyn_cast<CXXRecordDecl>(New->getDeclContext())) { + if (Record->getDescribedClassTemplate()) + WhichKind = 0; + else if (isa<ClassTemplatePartialSpecializationDecl>(Record)) + WhichKind = 1; + else + WhichKind = 2; + } + + Diag(NewParam->getLocation(), + diag::err_param_default_argument_member_template_redecl) + << WhichKind + << NewParam->getDefaultArgRange(); + } else if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(New)) { + CXXSpecialMember NewSM = getSpecialMember(Ctor), + OldSM = getSpecialMember(cast<CXXConstructorDecl>(Old)); + if (NewSM != OldSM) { + Diag(NewParam->getLocation(),diag::warn_default_arg_makes_ctor_special) + << NewParam->getDefaultArgRange() << NewSM; + Diag(Old->getLocation(), diag::note_previous_declaration_special) + << OldSM; + } + } + } + } + + if (CheckEquivalentExceptionSpec(Old, New)) + Invalid = true; + + return Invalid; +} + +/// \brief Merge the exception specifications of two variable declarations. +/// +/// This is called when there's a redeclaration of a VarDecl. The function +/// checks if the redeclaration might have an exception specification and +/// validates compatibility and merges the specs if necessary. +void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { + // Shortcut if exceptions are disabled. + if (!getLangOptions().CXXExceptions) + return; + + assert(Context.hasSameType(New->getType(), Old->getType()) && + "Should only be called if types are otherwise the same."); + + QualType NewType = New->getType(); + QualType OldType = Old->getType(); + + // We're only interested in pointers and references to functions, as well + // as pointers to member functions. + if (const ReferenceType *R = NewType->getAs<ReferenceType>()) { + NewType = R->getPointeeType(); + OldType = OldType->getAs<ReferenceType>()->getPointeeType(); + } else if (const PointerType *P = NewType->getAs<PointerType>()) { + NewType = P->getPointeeType(); + OldType = OldType->getAs<PointerType>()->getPointeeType(); + } else if (const MemberPointerType *M = NewType->getAs<MemberPointerType>()) { + NewType = M->getPointeeType(); + OldType = OldType->getAs<MemberPointerType>()->getPointeeType(); + } + + if (!NewType->isFunctionProtoType()) + return; + + // There's lots of special cases for functions. For function pointers, system + // libraries are hopefully not as broken so that we don't need these + // workarounds. + if (CheckEquivalentExceptionSpec( + OldType->getAs<FunctionProtoType>(), Old->getLocation(), + NewType->getAs<FunctionProtoType>(), New->getLocation())) { + New->setInvalidDecl(); + } +} + +/// CheckCXXDefaultArguments - Verify that the default arguments for a +/// function declaration are well-formed according to C++ +/// [dcl.fct.default]. +void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { + unsigned NumParams = FD->getNumParams(); + unsigned p; + + // Find first parameter with a default argument + for (p = 0; p < NumParams; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + if (Param->hasDefaultArg()) + break; + } + + // C++ [dcl.fct.default]p4: + // In a given function declaration, all parameters + // subsequent to a parameter with a default argument shall + // have default arguments supplied in this or previous + // declarations. A default argument shall not be redefined + // by a later declaration (not even to the same value). + unsigned LastMissingDefaultArg = 0; + for (; p < NumParams; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + if (!Param->hasDefaultArg()) { + if (Param->isInvalidDecl()) + /* We already complained about this parameter. */; + else if (Param->getIdentifier()) + Diag(Param->getLocation(), + diag::err_param_default_argument_missing_name) + << Param->getIdentifier(); + else + Diag(Param->getLocation(), + diag::err_param_default_argument_missing); + + LastMissingDefaultArg = p; + } + } + + if (LastMissingDefaultArg > 0) { + // Some default arguments were missing. Clear out all of the + // default arguments up to (and including) the last missing + // default argument, so that we leave the function parameters + // in a semantically valid state. + for (p = 0; p <= LastMissingDefaultArg; ++p) { + ParmVarDecl *Param = FD->getParamDecl(p); + if (Param->hasDefaultArg()) { + Param->setDefaultArg(0); + } + } + } +} + +/// isCurrentClassName - Determine whether the identifier II is the +/// name of the class type currently being defined. In the case of +/// nested classes, this will only return true if II is the name of +/// the innermost class. +bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, + const CXXScopeSpec *SS) { + assert(getLangOptions().CPlusPlus && "No class names in C!"); + + CXXRecordDecl *CurDecl; + if (SS && SS->isSet() && !SS->isInvalid()) { + DeclContext *DC = computeDeclContext(*SS, true); + CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC); + } else + CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext); + + if (CurDecl && CurDecl->getIdentifier()) + return &II == CurDecl->getIdentifier(); + else + return false; +} + +/// \brief Check the validity of a C++ base class specifier. +/// +/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics +/// and returns NULL otherwise. +CXXBaseSpecifier * +Sema::CheckBaseSpecifier(CXXRecordDecl *Class, + SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + TypeSourceInfo *TInfo, + SourceLocation EllipsisLoc) { + QualType BaseType = TInfo->getType(); + + // C++ [class.union]p1: + // A union shall not have base classes. + if (Class->isUnion()) { + Diag(Class->getLocation(), diag::err_base_clause_on_union) + << SpecifierRange; + return 0; + } + + if (EllipsisLoc.isValid() && + !TInfo->getType()->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << TInfo->getTypeLoc().getSourceRange(); + EllipsisLoc = SourceLocation(); + } + + if (BaseType->isDependentType()) + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, + Class->getTagKind() == TTK_Class, + Access, TInfo, EllipsisLoc); + + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + + // Base specifiers must be record types. + if (!BaseType->isRecordType()) { + Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; + return 0; + } + + // C++ [class.union]p1: + // A union shall not be used as a base class. + if (BaseType->isUnionType()) { + Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; + return 0; + } + + // C++ [class.derived]p2: + // The class-name in a base-specifier shall not be an incompletely + // defined class. + if (RequireCompleteType(BaseLoc, BaseType, + PDiag(diag::err_incomplete_base_class) + << SpecifierRange)) { + Class->setInvalidDecl(); + return 0; + } + + // If the base class is polymorphic or isn't empty, the new one is/isn't, too. + RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl(); + assert(BaseDecl && "Record type has no declaration"); + BaseDecl = BaseDecl->getDefinition(); + assert(BaseDecl && "Base type is not incomplete, but has no definition"); + CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); + assert(CXXBaseDecl && "Base type is not a C++ type"); + + // C++ [class]p3: + // If a class is marked final and it appears as a base-type-specifier in + // base-clause, the program is ill-formed. + if (CXXBaseDecl->hasAttr<FinalAttr>()) { + Diag(BaseLoc, diag::err_class_marked_final_used_as_base) + << CXXBaseDecl->getDeclName(); + Diag(CXXBaseDecl->getLocation(), diag::note_previous_decl) + << CXXBaseDecl->getDeclName(); + return 0; + } + + if (BaseDecl->isInvalidDecl()) + Class->setInvalidDecl(); + + // Create the base specifier. + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, + Class->getTagKind() == TTK_Class, + Access, TInfo, EllipsisLoc); +} + +/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is +/// one entry in the base class list of a class specifier, for +/// example: +/// class foo : public bar, virtual private baz { +/// 'public bar' and 'virtual private baz' are each base-specifiers. +BaseResult +Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + ParsedType basetype, SourceLocation BaseLoc, + SourceLocation EllipsisLoc) { + if (!classdecl) + return true; + + AdjustDeclIfTemplate(classdecl); + CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl); + if (!Class) + return true; + + TypeSourceInfo *TInfo = 0; + GetTypeFromParser(basetype, &TInfo); + + if (EllipsisLoc.isInvalid() && + DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo, + UPPC_BaseType)) + return true; + + if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, + Virtual, Access, TInfo, + EllipsisLoc)) + return BaseSpec; + + return true; +} + +/// \brief Performs the actual work of attaching the given base class +/// specifiers to a C++ class. +bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, + unsigned NumBases) { + if (NumBases == 0) + return false; + + // Used to keep track of which base types we have already seen, so + // that we can properly diagnose redundant direct base types. Note + // that the key is always the unqualified canonical type of the base + // class. + std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes; + + // Copy non-redundant base specifiers into permanent storage. + unsigned NumGoodBases = 0; + bool Invalid = false; + for (unsigned idx = 0; idx < NumBases; ++idx) { + QualType NewBaseType + = Context.getCanonicalType(Bases[idx]->getType()); + NewBaseType = NewBaseType.getLocalUnqualifiedType(); + if (!Class->hasObjectMember()) { + if (const RecordType *FDTTy = + NewBaseType.getTypePtr()->getAs<RecordType>()) + if (FDTTy->getDecl()->hasObjectMember()) + Class->setHasObjectMember(true); + } + + if (KnownBaseTypes[NewBaseType]) { + // C++ [class.mi]p3: + // A class shall not be specified as a direct base class of a + // derived class more than once. + Diag(Bases[idx]->getSourceRange().getBegin(), + diag::err_duplicate_base_class) + << KnownBaseTypes[NewBaseType]->getType() + << Bases[idx]->getSourceRange(); + + // Delete the duplicate base class specifier; we're going to + // overwrite its pointer later. + Context.Deallocate(Bases[idx]); + + Invalid = true; + } else { + // Okay, add this new base class. + KnownBaseTypes[NewBaseType] = Bases[idx]; + Bases[NumGoodBases++] = Bases[idx]; + } + } + + // Attach the remaining base class specifiers to the derived class. + Class->setBases(Bases, NumGoodBases); + + // Delete the remaining (good) base class specifiers, since their + // data has been copied into the CXXRecordDecl. + for (unsigned idx = 0; idx < NumGoodBases; ++idx) + Context.Deallocate(Bases[idx]); + + return Invalid; +} + +/// ActOnBaseSpecifiers - Attach the given base specifiers to the +/// class, after checking whether there are any duplicate base +/// classes. +void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, BaseTy **Bases, + unsigned NumBases) { + if (!ClassDecl || !Bases || !NumBases) + return; + + AdjustDeclIfTemplate(ClassDecl); + AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), + (CXXBaseSpecifier**)(Bases), NumBases); +} + +static CXXRecordDecl *GetClassForType(QualType T) { + if (const RecordType *RT = T->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl()); + else if (const InjectedClassNameType *ICT = T->getAs<InjectedClassNameType>()) + return ICT->getDecl(); + else + return 0; +} + +/// \brief Determine whether the type \p Derived is a C++ class that is +/// derived from the type \p Base. +bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { + if (!getLangOptions().CPlusPlus) + return false; + + CXXRecordDecl *DerivedRD = GetClassForType(Derived); + if (!DerivedRD) + return false; + + CXXRecordDecl *BaseRD = GetClassForType(Base); + if (!BaseRD) + return false; + + // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. + return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); +} + +/// \brief Determine whether the type \p Derived is a C++ class that is +/// derived from the type \p Base. +bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { + if (!getLangOptions().CPlusPlus) + return false; + + CXXRecordDecl *DerivedRD = GetClassForType(Derived); + if (!DerivedRD) + return false; + + CXXRecordDecl *BaseRD = GetClassForType(Base); + if (!BaseRD) + return false; + + return DerivedRD->isDerivedFrom(BaseRD, Paths); +} + +void Sema::BuildBasePathArray(const CXXBasePaths &Paths, + CXXCastPath &BasePathArray) { + assert(BasePathArray.empty() && "Base path array must be empty!"); + assert(Paths.isRecordingPaths() && "Must record paths!"); + + const CXXBasePath &Path = Paths.front(); + + // We first go backward and check if we have a virtual base. + // FIXME: It would be better if CXXBasePath had the base specifier for + // the nearest virtual base. + unsigned Start = 0; + for (unsigned I = Path.size(); I != 0; --I) { + if (Path[I - 1].Base->isVirtual()) { + Start = I - 1; + break; + } + } + + // Now add all bases. + for (unsigned I = Start, E = Path.size(); I != E; ++I) + BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base)); +} + +/// \brief Determine whether the given base path includes a virtual +/// base class. +bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) { + for (CXXCastPath::const_iterator B = BasePath.begin(), + BEnd = BasePath.end(); + B != BEnd; ++B) + if ((*B)->isVirtual()) + return true; + + return false; +} + +/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base +/// conversion (where Derived and Base are class types) is +/// well-formed, meaning that the conversion is unambiguous (and +/// that all of the base classes are accessible). Returns true +/// and emits a diagnostic if the code is ill-formed, returns false +/// otherwise. Loc is the location where this routine should point to +/// if there is an error, and Range is the source range to highlight +/// if there is an error. +bool +Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, + unsigned InaccessibleBaseID, + unsigned AmbigiousBaseConvID, + SourceLocation Loc, SourceRange Range, + DeclarationName Name, + CXXCastPath *BasePath) { + // First, determine whether the path from Derived to Base is + // ambiguous. This is slightly more expensive than checking whether + // the Derived to Base conversion exists, because here we need to + // explore multiple paths to determine if there is an ambiguity. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths); + assert(DerivationOkay && + "Can only be used with a derived-to-base conversion"); + (void)DerivationOkay; + + if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { + if (InaccessibleBaseID) { + // Check that the base class can be accessed. + switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(), + InaccessibleBaseID)) { + case AR_inaccessible: + return true; + case AR_accessible: + case AR_dependent: + case AR_delayed: + break; + } + } + + // Build a base path if necessary. + if (BasePath) + BuildBasePathArray(Paths, *BasePath); + return false; + } + + // We know that the derived-to-base conversion is ambiguous, and + // we're going to produce a diagnostic. Perform the derived-to-base + // search just one more time to compute all of the possible paths so + // that we can print them out. This is more expensive than any of + // the previous derived-to-base checks we've done, but at this point + // performance isn't as much of an issue. + Paths.clear(); + Paths.setRecordingPaths(true); + bool StillOkay = IsDerivedFrom(Derived, Base, Paths); + assert(StillOkay && "Can only be used with a derived-to-base conversion"); + (void)StillOkay; + + // Build up a textual representation of the ambiguous paths, e.g., + // D -> B -> A, that will be used to illustrate the ambiguous + // conversions in the diagnostic. We only print one of the paths + // to each base class subobject. + std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); + + Diag(Loc, AmbigiousBaseConvID) + << Derived << Base << PathDisplayStr << Range << Name; + return true; +} + +bool +Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, + SourceLocation Loc, SourceRange Range, + CXXCastPath *BasePath, + bool IgnoreAccess) { + return CheckDerivedToBaseConversion(Derived, Base, + IgnoreAccess ? 0 + : diag::err_upcast_to_inaccessible_base, + diag::err_ambiguous_derived_to_base_conv, + Loc, Range, DeclarationName(), + BasePath); +} + + +/// @brief Builds a string representing ambiguous paths from a +/// specific derived class to different subobjects of the same base +/// class. +/// +/// This function builds a string that can be used in error messages +/// to show the different paths that one can take through the +/// inheritance hierarchy to go from the derived class to different +/// subobjects of a base class. The result looks something like this: +/// @code +/// struct D -> struct B -> struct A +/// struct D -> struct C -> struct A +/// @endcode +std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { + std::string PathDisplayStr; + std::set<unsigned> DisplayedPaths; + for (CXXBasePaths::paths_iterator Path = Paths.begin(); + Path != Paths.end(); ++Path) { + if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { + // We haven't displayed a path to this particular base + // class subobject yet. + PathDisplayStr += "\n "; + PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString(); + for (CXXBasePath::const_iterator Element = Path->begin(); + Element != Path->end(); ++Element) + PathDisplayStr += " -> " + Element->Base->getType().getAsString(); + } + } + + return PathDisplayStr; +} + +//===----------------------------------------------------------------------===// +// C++ class member Handling +//===----------------------------------------------------------------------===// + +/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. +Decl *Sema::ActOnAccessSpecifier(AccessSpecifier Access, + SourceLocation ASLoc, + SourceLocation ColonLoc) { + assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); + AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, + ASLoc, ColonLoc); + CurContext->addHiddenDecl(ASDecl); + return ASDecl; +} + +/// CheckOverrideControl - Check C++0x override control semantics. +void Sema::CheckOverrideControl(const Decl *D) { + const CXXMethodDecl *MD = llvm::dyn_cast<CXXMethodDecl>(D); + if (!MD || !MD->isVirtual()) + return; + + if (MD->isDependentContext()) + return; + + // C++0x [class.virtual]p3: + // If a virtual function is marked with the virt-specifier override and does + // not override a member function of a base class, + // the program is ill-formed. + bool HasOverriddenMethods = + MD->begin_overridden_methods() != MD->end_overridden_methods(); + if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods) { + Diag(MD->getLocation(), + diag::err_function_marked_override_not_overriding) + << MD->getDeclName(); + return; + } +} + +/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member +/// function overrides a virtual member function marked 'final', according to +/// C++0x [class.virtual]p3. +bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + if (!Old->hasAttr<FinalAttr>()) + return false; + + Diag(New->getLocation(), diag::err_final_function_overridden) + << New->getDeclName(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; +} + +/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member +/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the +/// bitfield width if there is one, 'InitExpr' specifies the initializer if +/// one has been parsed, and 'HasDeferredInit' is true if an initializer is +/// present but parsing it has been deferred. +Decl * +Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + ExprTy *BW, const VirtSpecifiers &VS, + ExprTy *InitExpr, bool HasDeferredInit, + bool IsDefinition) { + const DeclSpec &DS = D.getDeclSpec(); + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + SourceLocation Loc = NameInfo.getLoc(); + + // For anonymous bitfields, the location should point to the type. + if (Loc.isInvalid()) + Loc = D.getSourceRange().getBegin(); + + Expr *BitWidth = static_cast<Expr*>(BW); + Expr *Init = static_cast<Expr*>(InitExpr); + + assert(isa<CXXRecordDecl>(CurContext)); + assert(!DS.isFriendSpecified()); + assert(!Init || !HasDeferredInit); + + bool isFunc = false; + if (D.isFunctionDeclarator()) + isFunc = true; + else if (D.getNumTypeObjects() == 0 && + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename) { + QualType TDType = GetTypeFromParser(DS.getRepAsType()); + isFunc = TDType->isFunctionType(); + } + + // C++ 9.2p6: A member shall not be declared to have automatic storage + // duration (auto, register) or with the extern storage-class-specifier. + // C++ 7.1.1p8: The mutable specifier can be applied only to names of class + // data members and cannot be applied to names declared const or static, + // and cannot be applied to reference members. + switch (DS.getStorageClassSpec()) { + case DeclSpec::SCS_unspecified: + case DeclSpec::SCS_typedef: + case DeclSpec::SCS_static: + // FALL THROUGH. + break; + case DeclSpec::SCS_mutable: + if (isFunc) { + if (DS.getStorageClassSpecLoc().isValid()) + Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function); + else + Diag(DS.getThreadSpecLoc(), diag::err_mutable_function); + + // FIXME: It would be nicer if the keyword was ignored only for this + // declarator. Otherwise we could get follow-up errors. + D.getMutableDeclSpec().ClearStorageClassSpecs(); + } + break; + default: + if (DS.getStorageClassSpecLoc().isValid()) + Diag(DS.getStorageClassSpecLoc(), + diag::err_storageclass_invalid_for_member); + else + Diag(DS.getThreadSpecLoc(), diag::err_storageclass_invalid_for_member); + D.getMutableDeclSpec().ClearStorageClassSpecs(); + } + + bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified || + DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && + !isFunc); + + Decl *Member; + if (isInstField) { + CXXScopeSpec &SS = D.getCXXScopeSpec(); + + if (SS.isSet() && !SS.isInvalid()) { + // The user provided a superfluous scope specifier inside a class + // definition: + // + // class X { + // int X::member; + // }; + DeclContext *DC = 0; + if ((DC = computeDeclContext(SS, false)) && DC->Equals(CurContext)) + Diag(D.getIdentifierLoc(), diag::warn_member_extra_qualification) + << Name << FixItHint::CreateRemoval(SS.getRange()); + else + Diag(D.getIdentifierLoc(), diag::err_member_qualification) + << Name << SS.getRange(); + + SS.clear(); + } + + // FIXME: Check for template parameters! + // FIXME: Check that the name is an identifier! + Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, BitWidth, + HasDeferredInit, AS); + assert(Member && "HandleField never returns null"); + } else { + assert(!HasDeferredInit); + + Member = HandleDeclarator(S, D, move(TemplateParameterLists), IsDefinition); + if (!Member) { + return 0; + } + + // Non-instance-fields can't have a bitfield. + if (BitWidth) { + if (Member->isInvalidDecl()) { + // don't emit another diagnostic. + } else if (isa<VarDecl>(Member)) { + // C++ 9.6p3: A bit-field shall not be a static member. + // "static member 'A' cannot be a bit-field" + Diag(Loc, diag::err_static_not_bitfield) + << Name << BitWidth->getSourceRange(); + } else if (isa<TypedefDecl>(Member)) { + // "typedef member 'x' cannot be a bit-field" + Diag(Loc, diag::err_typedef_not_bitfield) + << Name << BitWidth->getSourceRange(); + } else { + // A function typedef ("typedef int f(); f a;"). + // C++ 9.6p3: A bit-field shall have integral or enumeration type. + Diag(Loc, diag::err_not_integral_type_bitfield) + << Name << cast<ValueDecl>(Member)->getType() + << BitWidth->getSourceRange(); + } + + BitWidth = 0; + Member->setInvalidDecl(); + } + + Member->setAccess(AS); + + // If we have declared a member function template, set the access of the + // templated declaration as well. + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member)) + FunTmpl->getTemplatedDecl()->setAccess(AS); + } + + if (VS.isOverrideSpecified()) { + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member); + if (!MD || !MD->isVirtual()) { + Diag(Member->getLocStart(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "override" << FixItHint::CreateRemoval(VS.getOverrideLoc()); + } else + MD->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context)); + } + if (VS.isFinalSpecified()) { + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member); + if (!MD || !MD->isVirtual()) { + Diag(Member->getLocStart(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "final" << FixItHint::CreateRemoval(VS.getFinalLoc()); + } else + MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); + } + + if (VS.getLastLocation().isValid()) { + // Update the end location of a method that has a virt-specifiers. + if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member)) + MD->setRangeEnd(VS.getLastLocation()); + } + + CheckOverrideControl(Member); + + assert((Name || isInstField) && "No identifier for non-field ?"); + + if (Init) + AddInitializerToDecl(Member, Init, false, + DS.getTypeSpecType() == DeclSpec::TST_auto); + else if (DS.getTypeSpecType() == DeclSpec::TST_auto && + DS.getStorageClassSpec() == DeclSpec::SCS_static) { + // C++0x [dcl.spec.auto]p4: 'auto' can only be used in the type of a static + // data member if a brace-or-equal-initializer is provided. + Diag(Loc, diag::err_auto_var_requires_init) + << Name << cast<ValueDecl>(Member)->getType(); + Member->setInvalidDecl(); + } + + FinalizeDeclaration(Member); + + if (isInstField) + FieldCollector->Add(cast<FieldDecl>(Member)); + return Member; +} + +/// ActOnCXXInClassMemberInitializer - This is invoked after parsing an +/// in-class initializer for a non-static C++ class member. Such parsing +/// is deferred until the class is complete. +void +Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation EqualLoc, + Expr *InitExpr) { + FieldDecl *FD = cast<FieldDecl>(D); + + if (!InitExpr) { + FD->setInvalidDecl(); + FD->removeInClassInitializer(); + return; + } + + ExprResult Init = InitExpr; + if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { + // FIXME: if there is no EqualLoc, this is list-initialization. + Init = PerformCopyInitialization( + InitializedEntity::InitializeMember(FD), EqualLoc, InitExpr); + if (Init.isInvalid()) { + FD->setInvalidDecl(); + return; + } + + CheckImplicitConversions(Init.get(), EqualLoc); + } + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + Init = MaybeCreateExprWithCleanups(Init); + if (Init.isInvalid()) { + FD->setInvalidDecl(); + return; + } + + InitExpr = Init.release(); + + FD->setInClassInitializer(InitExpr); +} + +/// \brief Find the direct and/or virtual base specifiers that +/// correspond to the given base type, for use in base initialization +/// within a constructor. +static bool FindBaseInitializer(Sema &SemaRef, + CXXRecordDecl *ClassDecl, + QualType BaseType, + const CXXBaseSpecifier *&DirectBaseSpec, + const CXXBaseSpecifier *&VirtualBaseSpec) { + // First, check for a direct base class. + DirectBaseSpec = 0; + for (CXXRecordDecl::base_class_const_iterator Base + = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base->getType())) { + // We found a direct base of this type. That's what we're + // initializing. + DirectBaseSpec = &*Base; + break; + } + } + + // Check for a virtual base class. + // FIXME: We might be able to short-circuit this if we know in advance that + // there are no virtual bases. + VirtualBaseSpec = 0; + if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) { + // We haven't found a base yet; search the class hierarchy for a + // virtual base class. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl), + BaseType, Paths)) { + for (CXXBasePaths::paths_iterator Path = Paths.begin(); + Path != Paths.end(); ++Path) { + if (Path->back().Base->isVirtual()) { + VirtualBaseSpec = Path->back().Base; + break; + } + } + } + } + + return DirectBaseSpec || VirtualBaseSpec; +} + +/// ActOnMemInitializer - Handle a C++ member initializer. +MemInitResult +Sema::ActOnMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + SourceLocation IdLoc, + SourceLocation LParenLoc, + ExprTy **Args, unsigned NumArgs, + SourceLocation RParenLoc, + SourceLocation EllipsisLoc) { + if (!ConstructorD) + return true; + + AdjustDeclIfTemplate(ConstructorD); + + CXXConstructorDecl *Constructor + = dyn_cast<CXXConstructorDecl>(ConstructorD); + if (!Constructor) { + // The user wrote a constructor initializer on a function that is + // not a C++ constructor. Ignore the error for now, because we may + // have more member initializers coming; we'll diagnose it just + // once in ActOnMemInitializers. + return true; + } + + CXXRecordDecl *ClassDecl = Constructor->getParent(); + + // C++ [class.base.init]p2: + // Names in a mem-initializer-id are looked up in the scope of the + // constructor's class and, if not found in that scope, are looked + // up in the scope containing the constructor's definition. + // [Note: if the constructor's class contains a member with the + // same name as a direct or virtual base class of the class, a + // mem-initializer-id naming the member or base class and composed + // of a single identifier refers to the class member. A + // mem-initializer-id for the hidden base class may be specified + // using a qualified name. ] + if (!SS.getScopeRep() && !TemplateTypeTy) { + // Look for a member, first. + FieldDecl *Member = 0; + DeclContext::lookup_result Result + = ClassDecl->lookup(MemberOrBase); + if (Result.first != Result.second) { + Member = dyn_cast<FieldDecl>(*Result.first); + + if (Member) { + if (EllipsisLoc.isValid()) + Diag(EllipsisLoc, diag::err_pack_expansion_member_init) + << MemberOrBase << SourceRange(IdLoc, RParenLoc); + + return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, + LParenLoc, RParenLoc); + } + + // Handle anonymous union case. + if (IndirectFieldDecl* IndirectField + = dyn_cast<IndirectFieldDecl>(*Result.first)) { + if (EllipsisLoc.isValid()) + Diag(EllipsisLoc, diag::err_pack_expansion_member_init) + << MemberOrBase << SourceRange(IdLoc, RParenLoc); + + return BuildMemberInitializer(IndirectField, (Expr**)Args, + NumArgs, IdLoc, + LParenLoc, RParenLoc); + } + } + } + // It didn't name a member, so see if it names a class. + QualType BaseType; + TypeSourceInfo *TInfo = 0; + + if (TemplateTypeTy) { + BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); + } else { + LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); + LookupParsedName(R, S, &SS); + + TypeDecl *TyD = R.getAsSingle<TypeDecl>(); + if (!TyD) { + if (R.isAmbiguous()) return true; + + // We don't want access-control diagnostics here. + R.suppressDiagnostics(); + + if (SS.isSet() && isDependentScopeSpecifier(SS)) { + bool NotUnknownSpecialization = false; + DeclContext *DC = computeDeclContext(SS, false); + if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC)) + NotUnknownSpecialization = !Record->hasAnyDependentBases(); + + if (!NotUnknownSpecialization) { + // When the scope specifier can refer to a member of an unknown + // specialization, we take it as a type name. + BaseType = CheckTypenameType(ETK_None, SourceLocation(), + SS.getWithLocInContext(Context), + *MemberOrBase, IdLoc); + if (BaseType.isNull()) + return true; + + R.clear(); + R.setLookupName(MemberOrBase); + } + } + + // If no results were found, try to correct typos. + if (R.empty() && BaseType.isNull() && + CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) && + R.isSingleResult()) { + if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) { + if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) { + // We have found a non-static data member with a similar + // name to what was typed; complain and initialize that + // member. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << true << R.getLookupName() + << FixItHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + Diag(Member->getLocation(), diag::note_previous_decl) + << Member->getDeclName(); + + return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, + LParenLoc, RParenLoc); + } + } else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) { + const CXXBaseSpecifier *DirectBaseSpec; + const CXXBaseSpecifier *VirtualBaseSpec; + if (FindBaseInitializer(*this, ClassDecl, + Context.getTypeDeclType(Type), + DirectBaseSpec, VirtualBaseSpec)) { + // We have found a direct or virtual base class with a + // similar name to what was typed; complain and initialize + // that base class. + Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) + << MemberOrBase << false << R.getLookupName() + << FixItHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + + const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec + : VirtualBaseSpec; + Diag(BaseSpec->getSourceRange().getBegin(), + diag::note_base_class_specified_here) + << BaseSpec->getType() + << BaseSpec->getSourceRange(); + + TyD = Type; + } + } + } + + if (!TyD && BaseType.isNull()) { + Diag(IdLoc, diag::err_mem_init_not_member_or_class) + << MemberOrBase << SourceRange(IdLoc, RParenLoc); + return true; + } + } + + if (BaseType.isNull()) { + BaseType = Context.getTypeDeclType(TyD); + if (SS.isSet()) { + NestedNameSpecifier *Qualifier = + static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + + // FIXME: preserve source range information + BaseType = Context.getElaboratedType(ETK_None, Qualifier, BaseType); + } + } + } + + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); + + return BuildBaseInitializer(BaseType, TInfo, (Expr **)Args, NumArgs, + LParenLoc, RParenLoc, ClassDecl, EllipsisLoc); +} + +/// Checks an initializer expression for use of uninitialized fields, such as +/// containing the field that is being initialized. Returns true if there is an +/// uninitialized field was used an updates the SourceLocation parameter; false +/// otherwise. +static bool InitExprContainsUninitializedFields(const Stmt *S, + const ValueDecl *LhsField, + SourceLocation *L) { + assert(isa<FieldDecl>(LhsField) || isa<IndirectFieldDecl>(LhsField)); + + if (isa<CallExpr>(S)) { + // Do not descend into function calls or constructors, as the use + // of an uninitialized field may be valid. One would have to inspect + // the contents of the function/ctor to determine if it is safe or not. + // i.e. Pass-by-value is never safe, but pass-by-reference and pointers + // may be safe, depending on what the function/ctor does. + return false; + } + if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { + const NamedDecl *RhsField = ME->getMemberDecl(); + + if (const VarDecl *VD = dyn_cast<VarDecl>(RhsField)) { + // The member expression points to a static data member. + assert(VD->isStaticDataMember() && + "Member points to non-static data member!"); + (void)VD; + return false; + } + + if (isa<EnumConstantDecl>(RhsField)) { + // The member expression points to an enum. + return false; + } + + if (RhsField == LhsField) { + // Initializing a field with itself. Throw a warning. + // But wait; there are exceptions! + // Exception #1: The field may not belong to this record. + // e.g. Foo(const Foo& rhs) : A(rhs.A) {} + const Expr *base = ME->getBase(); + if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) { + // Even though the field matches, it does not belong to this record. + return false; + } + // None of the exceptions triggered; return true to indicate an + // uninitialized field was used. + *L = ME->getMemberLoc(); + return true; + } + } else if (isa<UnaryExprOrTypeTraitExpr>(S)) { + // sizeof/alignof doesn't reference contents, do not warn. + return false; + } else if (const UnaryOperator *UOE = dyn_cast<UnaryOperator>(S)) { + // address-of doesn't reference contents (the pointer may be dereferenced + // in the same expression but it would be rare; and weird). + if (UOE->getOpcode() == UO_AddrOf) + return false; + } + for (Stmt::const_child_range it = S->children(); it; ++it) { + if (!*it) { + // An expression such as 'member(arg ?: "")' may trigger this. + continue; + } + if (InitExprContainsUninitializedFields(*it, LhsField, L)) + return true; + } + return false; +} + +MemInitResult +Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, + unsigned NumArgs, SourceLocation IdLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member); + IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member); + assert((DirectMember || IndirectMember) && + "Member must be a FieldDecl or IndirectFieldDecl"); + + if (Member->isInvalidDecl()) + return true; + + // Diagnose value-uses of fields to initialize themselves, e.g. + // foo(foo) + // where foo is not also a parameter to the constructor. + // TODO: implement -Wuninitialized and fold this into that framework. + for (unsigned i = 0; i < NumArgs; ++i) { + SourceLocation L; + if (InitExprContainsUninitializedFields(Args[i], Member, &L)) { + // FIXME: Return true in the case when other fields are used before being + // uninitialized. For example, let this field be the i'th field. When + // initializing the i'th field, throw a warning if any of the >= i'th + // fields are used, as they are not yet initialized. + // Right now we are only handling the case where the i'th field uses + // itself in its initializer. + Diag(L, diag::warn_field_is_uninit); + } + } + + bool HasDependentArg = false; + for (unsigned i = 0; i < NumArgs; i++) + HasDependentArg |= Args[i]->isTypeDependent(); + + Expr *Init; + if (Member->getType()->isDependentType() || HasDependentArg) { + // Can't check initialization for a member of dependent type or when + // any of the arguments are type-dependent expressions. + Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); + + // Erase any temporaries within this evaluation context; we're not + // going to track them in the AST, since we'll be rebuilding the + // ASTs during template instantiation. + ExprTemporaries.erase( + ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries, + ExprTemporaries.end()); + } else { + // Initialize the member. + InitializedEntity MemberEntity = + DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0) + : InitializedEntity::InitializeMember(IndirectMember, 0); + InitializationKind Kind = + InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); + + ExprResult MemberInit = + InitSeq.Perform(*this, MemberEntity, Kind, + MultiExprArg(*this, Args, NumArgs), 0); + if (MemberInit.isInvalid()) + return true; + + CheckImplicitConversions(MemberInit.get(), LParenLoc); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + MemberInit = MaybeCreateExprWithCleanups(MemberInit); + if (MemberInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the member + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) + Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); + else + Init = MemberInit.get(); + } + + if (DirectMember) { + return new (Context) CXXCtorInitializer(Context, DirectMember, + IdLoc, LParenLoc, Init, + RParenLoc); + } else { + return new (Context) CXXCtorInitializer(Context, IndirectMember, + IdLoc, LParenLoc, Init, + RParenLoc); + } +} + +MemInitResult +Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, + Expr **Args, unsigned NumArgs, + SourceLocation NameLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc, + CXXRecordDecl *ClassDecl) { + SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); + if (!LangOpts.CPlusPlus0x) + return Diag(Loc, diag::err_delegation_0x_only) + << TInfo->getTypeLoc().getLocalSourceRange(); + + // Initialize the object. + InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( + QualType(ClassDecl->getTypeForDecl(), 0)); + InitializationKind Kind = + InitializationKind::CreateDirect(NameLoc, LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + + ExprResult DelegationInit = + InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args, NumArgs), 0); + if (DelegationInit.isInvalid()) + return true; + + CXXConstructExpr *ConExpr = cast<CXXConstructExpr>(DelegationInit.get()); + CXXConstructorDecl *Constructor + = ConExpr->getConstructor(); + assert(Constructor && "Delegating constructor with no target?"); + + CheckImplicitConversions(DelegationInit.get(), LParenLoc); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + DelegationInit = MaybeCreateExprWithCleanups(DelegationInit); + if (DelegationInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) { + ExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, + NumArgs, RParenLoc)); + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, + Constructor, Init.takeAs<Expr>(), + RParenLoc); + } + + return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, Constructor, + DelegationInit.takeAs<Expr>(), + RParenLoc); +} + +MemInitResult +Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, + Expr **Args, unsigned NumArgs, + SourceLocation LParenLoc, SourceLocation RParenLoc, + CXXRecordDecl *ClassDecl, + SourceLocation EllipsisLoc) { + bool HasDependentArg = false; + for (unsigned i = 0; i < NumArgs; i++) + HasDependentArg |= Args[i]->isTypeDependent(); + + SourceLocation BaseLoc + = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); + + if (!BaseType->isDependentType() && !BaseType->isRecordType()) + return Diag(BaseLoc, diag::err_base_init_does_not_name_class) + << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); + + // C++ [class.base.init]p2: + // [...] Unless the mem-initializer-id names a nonstatic data + // member of the constructor's class or a direct or virtual base + // of that class, the mem-initializer is ill-formed. A + // mem-initializer-list can initialize a base class using any + // name that denotes that base class type. + bool Dependent = BaseType->isDependentType() || HasDependentArg; + + if (EllipsisLoc.isValid()) { + // This is a pack expansion. + if (!BaseType->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(BaseLoc, RParenLoc); + + EllipsisLoc = SourceLocation(); + } + } else { + // Check for any unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer)) + return true; + + for (unsigned I = 0; I != NumArgs; ++I) + if (DiagnoseUnexpandedParameterPack(Args[I])) + return true; + } + + // Check for direct and virtual base classes. + const CXXBaseSpecifier *DirectBaseSpec = 0; + const CXXBaseSpecifier *VirtualBaseSpec = 0; + if (!Dependent) { + if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), + BaseType)) + return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, BaseLoc, + LParenLoc, RParenLoc, ClassDecl); + + FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, + VirtualBaseSpec); + + // C++ [base.class.init]p2: + // Unless the mem-initializer-id names a nonstatic data member of the + // constructor's class or a direct or virtual base of that class, the + // mem-initializer is ill-formed. + if (!DirectBaseSpec && !VirtualBaseSpec) { + // If the class has any dependent bases, then it's possible that + // one of those types will resolve to the same type as + // BaseType. Therefore, just treat this as a dependent base + // class initialization. FIXME: Should we try to check the + // initialization anyway? It seems odd. + if (ClassDecl->hasAnyDependentBases()) + Dependent = true; + else + return Diag(BaseLoc, diag::err_not_direct_base_or_virtual) + << BaseType << Context.getTypeDeclType(ClassDecl) + << BaseTInfo->getTypeLoc().getLocalSourceRange(); + } + } + + if (Dependent) { + // Can't check initialization for a base of dependent type or when + // any of the arguments are type-dependent expressions. + ExprResult BaseInit + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc)); + + // Erase any temporaries within this evaluation context; we're not + // going to track them in the AST, since we'll be rebuilding the + // ASTs during template instantiation. + ExprTemporaries.erase( + ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries, + ExprTemporaries.end()); + + return new (Context) CXXCtorInitializer(Context, BaseTInfo, + /*IsVirtual=*/false, + LParenLoc, + BaseInit.takeAs<Expr>(), + RParenLoc, + EllipsisLoc); + } + + // C++ [base.class.init]p2: + // If a mem-initializer-id is ambiguous because it designates both + // a direct non-virtual base class and an inherited virtual base + // class, the mem-initializer is ill-formed. + if (DirectBaseSpec && VirtualBaseSpec) + return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) + << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); + + CXXBaseSpecifier *BaseSpec + = const_cast<CXXBaseSpecifier *>(DirectBaseSpec); + if (!BaseSpec) + BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec); + + // Initialize the base. + InitializedEntity BaseEntity = + InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); + InitializationKind Kind = + InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); + + ExprResult BaseInit = + InitSeq.Perform(*this, BaseEntity, Kind, + MultiExprArg(*this, Args, NumArgs), 0); + if (BaseInit.isInvalid()) + return true; + + CheckImplicitConversions(BaseInit.get(), LParenLoc); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + BaseInit = MaybeCreateExprWithCleanups(BaseInit); + if (BaseInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) { + ExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc)); + return new (Context) CXXCtorInitializer(Context, BaseTInfo, + BaseSpec->isVirtual(), + LParenLoc, + Init.takeAs<Expr>(), + RParenLoc, + EllipsisLoc); + } + + return new (Context) CXXCtorInitializer(Context, BaseTInfo, + BaseSpec->isVirtual(), + LParenLoc, + BaseInit.takeAs<Expr>(), + RParenLoc, + EllipsisLoc); +} + +/// ImplicitInitializerKind - How an implicit base or member initializer should +/// initialize its base or member. +enum ImplicitInitializerKind { + IIK_Default, + IIK_Copy, + IIK_Move +}; + +static bool +BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, + ImplicitInitializerKind ImplicitInitKind, + CXXBaseSpecifier *BaseSpec, + bool IsInheritedVirtualBase, + CXXCtorInitializer *&CXXBaseInit) { + InitializedEntity InitEntity + = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec, + IsInheritedVirtualBase); + + ExprResult BaseInit; + + switch (ImplicitInitKind) { + case IIK_Default: { + InitializationKind InitKind + = InitializationKind::CreateDefault(Constructor->getLocation()); + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); + BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, + MultiExprArg(SemaRef, 0, 0)); + break; + } + + case IIK_Copy: { + ParmVarDecl *Param = Constructor->getParamDecl(0); + QualType ParamType = Param->getType().getNonReferenceType(); + + Expr *CopyCtorArg = + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, + Constructor->getLocation(), ParamType, + VK_LValue, 0); + + // Cast to the base class to avoid ambiguities. + QualType ArgTy = + SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), + ParamType.getQualifiers()); + + CXXCastPath BasePath; + BasePath.push_back(BaseSpec); + CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath).take(); + + InitializationKind InitKind + = InitializationKind::CreateDirect(Constructor->getLocation(), + SourceLocation(), SourceLocation()); + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, + &CopyCtorArg, 1); + BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, + MultiExprArg(&CopyCtorArg, 1)); + break; + } + + case IIK_Move: + assert(false && "Unhandled initializer kind!"); + } + + BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit); + if (BaseInit.isInvalid()) + return true; + + CXXBaseInit = + new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, + SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(), + SourceLocation()), + BaseSpec->isVirtual(), + SourceLocation(), + BaseInit.takeAs<Expr>(), + SourceLocation(), + SourceLocation()); + + return false; +} + +static bool +BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, + ImplicitInitializerKind ImplicitInitKind, + FieldDecl *Field, + CXXCtorInitializer *&CXXMemberInit) { + if (Field->isInvalidDecl()) + return true; + + SourceLocation Loc = Constructor->getLocation(); + + if (ImplicitInitKind == IIK_Copy) { + ParmVarDecl *Param = Constructor->getParamDecl(0); + QualType ParamType = Param->getType().getNonReferenceType(); + + Expr *MemberExprBase = + DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), Param, + Loc, ParamType, VK_LValue, 0); + + // Build a reference to this field within the parameter. + CXXScopeSpec SS; + LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc, + Sema::LookupMemberName); + MemberLookup.addDecl(Field, AS_public); + MemberLookup.resolveKind(); + ExprResult CopyCtorArg + = SemaRef.BuildMemberReferenceExpr(MemberExprBase, + ParamType, Loc, + /*IsArrow=*/false, + SS, + /*FirstQualifierInScope=*/0, + MemberLookup, + /*TemplateArgs=*/0); + if (CopyCtorArg.isInvalid()) + return true; + + // When the field we are copying is an array, create index variables for + // each dimension of the array. We use these index variables to subscript + // the source array, and other clients (e.g., CodeGen) will perform the + // necessary iteration with these index variables. + llvm::SmallVector<VarDecl *, 4> IndexVariables; + QualType BaseType = Field->getType(); + QualType SizeType = SemaRef.Context.getSizeType(); + while (const ConstantArrayType *Array + = SemaRef.Context.getAsConstantArrayType(BaseType)) { + // Create the iteration variable for this array index. + IdentifierInfo *IterationVarName = 0; + { + llvm::SmallString<8> Str; + llvm::raw_svector_ostream OS(Str); + OS << "__i" << IndexVariables.size(); + IterationVarName = &SemaRef.Context.Idents.get(OS.str()); + } + VarDecl *IterationVar + = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, + IterationVarName, SizeType, + SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), + SC_None, SC_None); + IndexVariables.push_back(IterationVar); + + // Create a reference to the iteration variable. + ExprResult IterationVarRef + = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc); + assert(!IterationVarRef.isInvalid() && + "Reference to invented variable cannot fail!"); + + // Subscript the array with this iteration variable. + CopyCtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CopyCtorArg.take(), + Loc, + IterationVarRef.take(), + Loc); + if (CopyCtorArg.isInvalid()) + return true; + + BaseType = Array->getElementType(); + } + + // Construct the entity that we will be initializing. For an array, this + // will be first element in the array, which may require several levels + // of array-subscript entities. + llvm::SmallVector<InitializedEntity, 4> Entities; + Entities.reserve(1 + IndexVariables.size()); + Entities.push_back(InitializedEntity::InitializeMember(Field)); + for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I) + Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context, + 0, + Entities.back())); + + // Direct-initialize to use the copy constructor. + InitializationKind InitKind = + InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation()); + + Expr *CopyCtorArgE = CopyCtorArg.takeAs<Expr>(); + InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind, + &CopyCtorArgE, 1); + + ExprResult MemberInit + = InitSeq.Perform(SemaRef, Entities.back(), InitKind, + MultiExprArg(&CopyCtorArgE, 1)); + MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); + if (MemberInit.isInvalid()) + return true; + + CXXMemberInit + = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc, Loc, + MemberInit.takeAs<Expr>(), Loc, + IndexVariables.data(), + IndexVariables.size()); + return false; + } + + assert(ImplicitInitKind == IIK_Default && "Unhandled implicit init kind!"); + + QualType FieldBaseElementType = + SemaRef.Context.getBaseElementType(Field->getType()); + + if (FieldBaseElementType->isRecordType()) { + InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); + InitializationKind InitKind = + InitializationKind::CreateDefault(Loc); + + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); + ExprResult MemberInit = + InitSeq.Perform(SemaRef, InitEntity, InitKind, MultiExprArg()); + + MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); + if (MemberInit.isInvalid()) + return true; + + CXXMemberInit = + new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, + Field, Loc, Loc, + MemberInit.get(), + Loc); + return false; + } + + if (!Field->getParent()->isUnion()) { + if (FieldBaseElementType->isReferenceType()) { + SemaRef.Diag(Constructor->getLocation(), + diag::err_uninitialized_member_in_ctor) + << (int)Constructor->isImplicit() + << SemaRef.Context.getTagDeclType(Constructor->getParent()) + << 0 << Field->getDeclName(); + SemaRef.Diag(Field->getLocation(), diag::note_declared_at); + return true; + } + + if (FieldBaseElementType.isConstQualified()) { + SemaRef.Diag(Constructor->getLocation(), + diag::err_uninitialized_member_in_ctor) + << (int)Constructor->isImplicit() + << SemaRef.Context.getTagDeclType(Constructor->getParent()) + << 1 << Field->getDeclName(); + SemaRef.Diag(Field->getLocation(), diag::note_declared_at); + return true; + } + } + + // Nothing to initialize. + CXXMemberInit = 0; + return false; +} + +namespace { +struct BaseAndFieldInfo { + Sema &S; + CXXConstructorDecl *Ctor; + bool AnyErrorsInInits; + ImplicitInitializerKind IIK; + llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields; + llvm::SmallVector<CXXCtorInitializer*, 8> AllToInit; + + BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits) + : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) { + // FIXME: Handle implicit move constructors. + if (Ctor->isImplicit() && Ctor->isCopyConstructor()) + IIK = IIK_Copy; + else + IIK = IIK_Default; + } +}; +} + +static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, + FieldDecl *Top, FieldDecl *Field) { + + // Overwhelmingly common case: we have a direct initializer for this field. + if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(Field)) { + Info.AllToInit.push_back(Init); + return false; + } + + // C++0x [class.base.init]p8: if the entity is a non-static data member that + // has a brace-or-equal-initializer, the entity is initialized as specified + // in [dcl.init]. + if (Field->hasInClassInitializer()) { + Info.AllToInit.push_back( + new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, + SourceLocation(), + SourceLocation(), 0, + SourceLocation())); + return false; + } + + if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) { + const RecordType *FieldClassType = Field->getType()->getAs<RecordType>(); + assert(FieldClassType && "anonymous struct/union without record type"); + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + + // Even though union members never have non-trivial default + // constructions in C++03, we still build member initializers for aggregate + // record types which can be union members, and C++0x allows non-trivial + // default constructors for union members, so we ensure that only one + // member is initialized for these. + if (FieldClassDecl->isUnion()) { + // First check for an explicit initializer for one field. + for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), + EA = FieldClassDecl->field_end(); FA != EA; FA++) { + if (CXXCtorInitializer *Init = Info.AllBaseFields.lookup(*FA)) { + Info.AllToInit.push_back(Init); + + // Once we've initialized a field of an anonymous union, the union + // field in the class is also initialized, so exit immediately. + return false; + } else if ((*FA)->isAnonymousStructOrUnion()) { + if (CollectFieldInitializer(SemaRef, Info, Top, *FA)) + return true; + } + } + + // Fallthrough and construct a default initializer for the union as + // a whole, which can call its default constructor if such a thing exists + // (C++0x perhaps). FIXME: It's not clear that this is the correct + // behavior going forward with C++0x, when anonymous unions there are + // finalized, we should revisit this. + } else { + // For structs, we simply descend through to initialize all members where + // necessary. + for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), + EA = FieldClassDecl->field_end(); FA != EA; FA++) { + if (CollectFieldInitializer(SemaRef, Info, Top, *FA)) + return true; + } + } + } + + // Don't try to build an implicit initializer if there were semantic + // errors in any of the initializers (and therefore we might be + // missing some that the user actually wrote). + if (Info.AnyErrorsInInits || Field->isInvalidDecl()) + return false; + + CXXCtorInitializer *Init = 0; + if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init)) + return true; + + if (Init) + Info.AllToInit.push_back(Init); + + return false; +} + +bool +Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, + CXXCtorInitializer *Initializer) { + assert(Initializer->isDelegatingInitializer()); + Constructor->setNumCtorInitializers(1); + CXXCtorInitializer **initializer = + new (Context) CXXCtorInitializer*[1]; + memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*)); + Constructor->setCtorInitializers(initializer); + + if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { + MarkDeclarationReferenced(Initializer->getSourceLocation(), Dtor); + DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); + } + + DelegatingCtorDecls.push_back(Constructor); + + return false; +} + +bool +Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, + CXXCtorInitializer **Initializers, + unsigned NumInitializers, + bool AnyErrors) { + if (Constructor->getDeclContext()->isDependentContext()) { + // Just store the initializers as written, they will be checked during + // instantiation. + if (NumInitializers > 0) { + Constructor->setNumCtorInitializers(NumInitializers); + CXXCtorInitializer **baseOrMemberInitializers = + new (Context) CXXCtorInitializer*[NumInitializers]; + memcpy(baseOrMemberInitializers, Initializers, + NumInitializers * sizeof(CXXCtorInitializer*)); + Constructor->setCtorInitializers(baseOrMemberInitializers); + } + + return false; + } + + BaseAndFieldInfo Info(*this, Constructor, AnyErrors); + + // We need to build the initializer AST according to order of construction + // and not what user specified in the Initializers list. + CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition(); + if (!ClassDecl) + return true; + + bool HadError = false; + + for (unsigned i = 0; i < NumInitializers; i++) { + CXXCtorInitializer *Member = Initializers[i]; + + if (Member->isBaseInitializer()) + Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member; + else + Info.AllBaseFields[Member->getAnyMember()] = Member; + } + + // Keep track of the direct virtual bases. + llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases; + for (CXXRecordDecl::base_class_iterator I = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); I != E; ++I) { + if (I->isVirtual()) + DirectVBases.insert(I); + } + + // Push virtual bases before others. + for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + + if (CXXCtorInitializer *Value + = Info.AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { + Info.AllToInit.push_back(Value); + } else if (!AnyErrors) { + bool IsInheritedVirtualBase = !DirectVBases.count(VBase); + CXXCtorInitializer *CXXBaseInit; + if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, + VBase, IsInheritedVirtualBase, + CXXBaseInit)) { + HadError = true; + continue; + } + + Info.AllToInit.push_back(CXXBaseInit); + } + } + + // Non-virtual bases. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Virtuals are in the virtual base list and already constructed. + if (Base->isVirtual()) + continue; + + if (CXXCtorInitializer *Value + = Info.AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { + Info.AllToInit.push_back(Value); + } else if (!AnyErrors) { + CXXCtorInitializer *CXXBaseInit; + if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, + Base, /*IsInheritedVirtualBase=*/false, + CXXBaseInit)) { + HadError = true; + continue; + } + + Info.AllToInit.push_back(CXXBaseInit); + } + } + + // Fields. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { + if ((*Field)->getType()->isIncompleteArrayType()) { + assert(ClassDecl->hasFlexibleArrayMember() && + "Incomplete array type is not valid"); + continue; + } + if (CollectFieldInitializer(*this, Info, *Field, *Field)) + HadError = true; + } + + NumInitializers = Info.AllToInit.size(); + if (NumInitializers > 0) { + Constructor->setNumCtorInitializers(NumInitializers); + CXXCtorInitializer **baseOrMemberInitializers = + new (Context) CXXCtorInitializer*[NumInitializers]; + memcpy(baseOrMemberInitializers, Info.AllToInit.data(), + NumInitializers * sizeof(CXXCtorInitializer*)); + Constructor->setCtorInitializers(baseOrMemberInitializers); + + // Constructors implicitly reference the base and member + // destructors. + MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(), + Constructor->getParent()); + } + + return HadError; +} + +static void *GetKeyForTopLevelField(FieldDecl *Field) { + // For anonymous unions, use the class declaration as the key. + if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { + if (RT->getDecl()->isAnonymousStructOrUnion()) + return static_cast<void *>(RT->getDecl()); + } + return static_cast<void *>(Field); +} + +static void *GetKeyForBase(ASTContext &Context, QualType BaseType) { + return const_cast<Type*>(Context.getCanonicalType(BaseType).getTypePtr()); +} + +static void *GetKeyForMember(ASTContext &Context, + CXXCtorInitializer *Member) { + if (!Member->isAnyMemberInitializer()) + return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0)); + + // For fields injected into the class via declaration of an anonymous union, + // use its anonymous union class declaration as the unique key. + FieldDecl *Field = Member->getAnyMember(); + + // If the field is a member of an anonymous struct or union, our key + // is the anonymous record decl that's a direct child of the class. + RecordDecl *RD = Field->getParent(); + if (RD->isAnonymousStructOrUnion()) { + while (true) { + RecordDecl *Parent = cast<RecordDecl>(RD->getDeclContext()); + if (Parent->isAnonymousStructOrUnion()) + RD = Parent; + else + break; + } + + return static_cast<void *>(RD); + } + + return static_cast<void *>(Field); +} + +static void +DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, + const CXXConstructorDecl *Constructor, + CXXCtorInitializer **Inits, + unsigned NumInits) { + if (Constructor->getDeclContext()->isDependentContext()) + return; + + // Don't check initializers order unless the warning is enabled at the + // location of at least one initializer. + bool ShouldCheckOrder = false; + for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + CXXCtorInitializer *Init = Inits[InitIndex]; + if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order, + Init->getSourceLocation()) + != Diagnostic::Ignored) { + ShouldCheckOrder = true; + break; + } + } + if (!ShouldCheckOrder) + return; + + // Build the list of bases and members in the order that they'll + // actually be initialized. The explicit initializers should be in + // this same order but may be missing things. + llvm::SmallVector<const void*, 32> IdealInitKeys; + + const CXXRecordDecl *ClassDecl = Constructor->getParent(); + + // 1. Virtual bases. + for (CXXRecordDecl::base_class_const_iterator VBase = + ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) + IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase->getType())); + + // 2. Non-virtual bases. + for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + if (Base->isVirtual()) + continue; + IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base->getType())); + } + + // 3. Direct fields. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) + IdealInitKeys.push_back(GetKeyForTopLevelField(*Field)); + + unsigned NumIdealInits = IdealInitKeys.size(); + unsigned IdealIndex = 0; + + CXXCtorInitializer *PrevInit = 0; + for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + CXXCtorInitializer *Init = Inits[InitIndex]; + void *InitKey = GetKeyForMember(SemaRef.Context, Init); + + // Scan forward to try to find this initializer in the idealized + // initializers list. + for (; IdealIndex != NumIdealInits; ++IdealIndex) + if (InitKey == IdealInitKeys[IdealIndex]) + break; + + // If we didn't find this initializer, it must be because we + // scanned past it on a previous iteration. That can only + // happen if we're out of order; emit a warning. + if (IdealIndex == NumIdealInits && PrevInit) { + Sema::SemaDiagnosticBuilder D = + SemaRef.Diag(PrevInit->getSourceLocation(), + diag::warn_initializer_out_of_order); + + if (PrevInit->isAnyMemberInitializer()) + D << 0 << PrevInit->getAnyMember()->getDeclName(); + else + D << 1 << PrevInit->getBaseClassInfo()->getType(); + + if (Init->isAnyMemberInitializer()) + D << 0 << Init->getAnyMember()->getDeclName(); + else + D << 1 << Init->getBaseClassInfo()->getType(); + + // Move back to the initializer's location in the ideal list. + for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex) + if (InitKey == IdealInitKeys[IdealIndex]) + break; + + assert(IdealIndex != NumIdealInits && + "initializer not found in initializer list"); + } + + PrevInit = Init; + } +} + +namespace { +bool CheckRedundantInit(Sema &S, + CXXCtorInitializer *Init, + CXXCtorInitializer *&PrevInit) { + if (!PrevInit) { + PrevInit = Init; + return false; + } + + if (FieldDecl *Field = Init->getMember()) + S.Diag(Init->getSourceLocation(), + diag::err_multiple_mem_initialization) + << Field->getDeclName() + << Init->getSourceRange(); + else { + const Type *BaseClass = Init->getBaseClass(); + assert(BaseClass && "neither field nor base"); + S.Diag(Init->getSourceLocation(), + diag::err_multiple_base_initialization) + << QualType(BaseClass, 0) + << Init->getSourceRange(); + } + S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer) + << 0 << PrevInit->getSourceRange(); + + return true; +} + +typedef std::pair<NamedDecl *, CXXCtorInitializer *> UnionEntry; +typedef llvm::DenseMap<RecordDecl*, UnionEntry> RedundantUnionMap; + +bool CheckRedundantUnionInit(Sema &S, + CXXCtorInitializer *Init, + RedundantUnionMap &Unions) { + FieldDecl *Field = Init->getAnyMember(); + RecordDecl *Parent = Field->getParent(); + if (!Parent->isAnonymousStructOrUnion()) + return false; + + NamedDecl *Child = Field; + do { + if (Parent->isUnion()) { + UnionEntry &En = Unions[Parent]; + if (En.first && En.first != Child) { + S.Diag(Init->getSourceLocation(), + diag::err_multiple_mem_union_initialization) + << Field->getDeclName() + << Init->getSourceRange(); + S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer) + << 0 << En.second->getSourceRange(); + return true; + } else if (!En.first) { + En.first = Child; + En.second = Init; + } + } + + Child = Parent; + Parent = cast<RecordDecl>(Parent->getDeclContext()); + } while (Parent->isAnonymousStructOrUnion()); + + return false; +} +} + +/// ActOnMemInitializers - Handle the member initializers for a constructor. +void Sema::ActOnMemInitializers(Decl *ConstructorDecl, + SourceLocation ColonLoc, + MemInitTy **meminits, unsigned NumMemInits, + bool AnyErrors) { + if (!ConstructorDecl) + return; + + AdjustDeclIfTemplate(ConstructorDecl); + + CXXConstructorDecl *Constructor + = dyn_cast<CXXConstructorDecl>(ConstructorDecl); + + if (!Constructor) { + Diag(ColonLoc, diag::err_only_constructors_take_base_inits); + return; + } + + CXXCtorInitializer **MemInits = + reinterpret_cast<CXXCtorInitializer **>(meminits); + + // Mapping for the duplicate initializers check. + // For member initializers, this is keyed with a FieldDecl*. + // For base initializers, this is keyed with a Type*. + llvm::DenseMap<void*, CXXCtorInitializer *> Members; + + // Mapping for the inconsistent anonymous-union initializers check. + RedundantUnionMap MemberUnions; + + bool HadError = false; + for (unsigned i = 0; i < NumMemInits; i++) { + CXXCtorInitializer *Init = MemInits[i]; + + // Set the source order index. + Init->setSourceOrder(i); + + if (Init->isAnyMemberInitializer()) { + FieldDecl *Field = Init->getAnyMember(); + if (CheckRedundantInit(*this, Init, Members[Field]) || + CheckRedundantUnionInit(*this, Init, MemberUnions)) + HadError = true; + } else if (Init->isBaseInitializer()) { + void *Key = GetKeyForBase(Context, QualType(Init->getBaseClass(), 0)); + if (CheckRedundantInit(*this, Init, Members[Key])) + HadError = true; + } else { + assert(Init->isDelegatingInitializer()); + // This must be the only initializer + if (i != 0 || NumMemInits > 1) { + Diag(MemInits[0]->getSourceLocation(), + diag::err_delegating_initializer_alone) + << MemInits[0]->getSourceRange(); + HadError = true; + // We will treat this as being the only initializer. + } + SetDelegatingInitializer(Constructor, MemInits[i]); + // Return immediately as the initializer is set. + return; + } + } + + if (HadError) + return; + + DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits); + + SetCtorInitializers(Constructor, MemInits, NumMemInits, AnyErrors); +} + +void +Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, + CXXRecordDecl *ClassDecl) { + // Ignore dependent contexts. + if (ClassDecl->isDependentContext()) + return; + + // FIXME: all the access-control diagnostics are positioned on the + // field/base declaration. That's probably good; that said, the + // user might reasonably want to know why the destructor is being + // emitted, and we currently don't say. + + // Non-static data members. + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + FieldDecl *Field = *I; + if (Field->isInvalidDecl()) + continue; + QualType FieldType = Context.getBaseElementType(Field->getType()); + + const RecordType* RT = FieldType->getAs<RecordType>(); + if (!RT) + continue; + + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->isInvalidDecl()) + continue; + if (FieldClassDecl->hasTrivialDestructor()) + continue; + + CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); + assert(Dtor && "No dtor found for FieldClassDecl!"); + CheckDestructorAccess(Field->getLocation(), Dtor, + PDiag(diag::err_access_dtor_field) + << Field->getDeclName() + << FieldType); + + MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + } + + llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; + + // Bases. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Bases are always records in a well-formed non-dependent class. + const RecordType *RT = Base->getType()->getAs<RecordType>(); + + // Remember direct virtual bases. + if (Base->isVirtual()) + DirectVirtualBases.insert(RT); + + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + // Ignore trivial destructors. + if (BaseClassDecl->hasTrivialDestructor()) + continue; + + CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); + assert(Dtor && "No dtor found for BaseClassDecl!"); + + // FIXME: caret should be on the start of the class name + CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor, + PDiag(diag::err_access_dtor_base) + << Base->getType() + << Base->getSourceRange()); + + MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + } + + // Virtual bases. + for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), + E = ClassDecl->vbases_end(); VBase != E; ++VBase) { + + // Bases are always records in a well-formed non-dependent class. + const RecordType *RT = VBase->getType()->getAs<RecordType>(); + + // Ignore direct virtual bases. + if (DirectVirtualBases.count(RT)) + continue; + + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + // If our base class is invalid, we probably can't get its dtor anyway. + if (BaseClassDecl->isInvalidDecl()) + continue; + // Ignore trivial destructors. + if (BaseClassDecl->hasTrivialDestructor()) + continue; + + CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); + assert(Dtor && "No dtor found for BaseClassDecl!"); + CheckDestructorAccess(ClassDecl->getLocation(), Dtor, + PDiag(diag::err_access_dtor_vbase) + << VBase->getType()); + + MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor)); + } +} + +void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { + if (!CDtorDecl) + return; + + if (CXXConstructorDecl *Constructor + = dyn_cast<CXXConstructorDecl>(CDtorDecl)) + SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + unsigned DiagID, AbstractDiagSelID SelID) { + if (SelID == -1) + return RequireNonAbstractType(Loc, T, PDiag(DiagID)); + else + return RequireNonAbstractType(Loc, T, PDiag(DiagID) << SelID); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD) { + if (!getLangOptions().CPlusPlus) + return false; + + if (const ArrayType *AT = Context.getAsArrayType(T)) + return RequireNonAbstractType(Loc, AT->getElementType(), PD); + + if (const PointerType *PT = T->getAs<PointerType>()) { + // Find the innermost pointer type. + while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>()) + PT = T; + + if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) + return RequireNonAbstractType(Loc, AT->getElementType(), PD); + } + + const RecordType *RT = T->getAs<RecordType>(); + if (!RT) + return false; + + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + // We can't answer whether something is abstract until it has a + // definition. If it's currently being defined, we'll walk back + // over all the declarations when we have a full definition. + const CXXRecordDecl *Def = RD->getDefinition(); + if (!Def || Def->isBeingDefined()) + return false; + + if (!RD->isAbstract()) + return false; + + Diag(Loc, PD) << RD->getDeclName(); + DiagnoseAbstractType(RD); + + return true; +} + +void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) { + // Check if we've already emitted the list of pure virtual functions + // for this class. + if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD)) + return; + + CXXFinalOverriderMap FinalOverriders; + RD->getFinalOverriders(FinalOverriders); + + // Keep a set of seen pure methods so we won't diagnose the same method + // more than once. + llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods; + + for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), + MEnd = FinalOverriders.end(); + M != MEnd; + ++M) { + for (OverridingMethods::iterator SO = M->second.begin(), + SOEnd = M->second.end(); + SO != SOEnd; ++SO) { + // C++ [class.abstract]p4: + // A class is abstract if it contains or inherits at least one + // pure virtual function for which the final overrider is pure + // virtual. + + // + if (SO->second.size() != 1) + continue; + + if (!SO->second.front().Method->isPure()) + continue; + + if (!SeenPureMethods.insert(SO->second.front().Method)) + continue; + + Diag(SO->second.front().Method->getLocation(), + diag::note_pure_virtual_function) + << SO->second.front().Method->getDeclName() << RD->getDeclName(); + } + } + + if (!PureVirtualClassDiagSet) + PureVirtualClassDiagSet.reset(new RecordDeclSetTy); + PureVirtualClassDiagSet->insert(RD); +} + +namespace { +struct AbstractUsageInfo { + Sema &S; + CXXRecordDecl *Record; + CanQualType AbstractType; + bool Invalid; + + AbstractUsageInfo(Sema &S, CXXRecordDecl *Record) + : S(S), Record(Record), + AbstractType(S.Context.getCanonicalType( + S.Context.getTypeDeclType(Record))), + Invalid(false) {} + + void DiagnoseAbstractType() { + if (Invalid) return; + S.DiagnoseAbstractType(Record); + Invalid = true; + } + + void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel); +}; + +struct CheckAbstractUsage { + AbstractUsageInfo &Info; + const NamedDecl *Ctx; + + CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx) + : Info(Info), Ctx(Ctx) {} + + void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) { + switch (TL.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: Check(cast<CLASS##TypeLoc>(TL), Sel); break; +#include "clang/AST/TypeLocNodes.def" + } + } + + void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) { + Visit(TL.getResultLoc(), Sema::AbstractReturnType); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + if (!TL.getArg(I)) + continue; + + TypeSourceInfo *TSI = TL.getArg(I)->getTypeSourceInfo(); + if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType); + } + } + + void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) { + Visit(TL.getElementLoc(), Sema::AbstractArrayType); + } + + void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) { + // Visit the type parameters from a permissive context. + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TemplateArgumentLoc TAL = TL.getArgLoc(I); + if (TAL.getArgument().getKind() == TemplateArgument::Type) + if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo()) + Visit(TSI->getTypeLoc(), Sema::AbstractNone); + // TODO: other template argument types? + } + } + + // Visit pointee types from a permissive context. +#define CheckPolymorphic(Type) \ + void Check(Type TL, Sema::AbstractDiagSelID Sel) { \ + Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \ + } + CheckPolymorphic(PointerTypeLoc) + CheckPolymorphic(ReferenceTypeLoc) + CheckPolymorphic(MemberPointerTypeLoc) + CheckPolymorphic(BlockPointerTypeLoc) + + /// Handle all the types we haven't given a more specific + /// implementation for above. + void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) { + // Every other kind of type that we haven't called out already + // that has an inner type is either (1) sugar or (2) contains that + // inner type in some way as a subobject. + if (TypeLoc Next = TL.getNextTypeLoc()) + return Visit(Next, Sel); + + // If there's no inner type and we're in a permissive context, + // don't diagnose. + if (Sel == Sema::AbstractNone) return; + + // Check whether the type matches the abstract type. + QualType T = TL.getType(); + if (T->isArrayType()) { + Sel = Sema::AbstractArrayType; + T = Info.S.Context.getBaseElementType(T); + } + CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType(); + if (CT != Info.AbstractType) return; + + // It matched; do some magic. + if (Sel == Sema::AbstractArrayType) { + Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type) + << T << TL.getSourceRange(); + } else { + Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl) + << Sel << T << TL.getSourceRange(); + } + Info.DiagnoseAbstractType(); + } +}; + +void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL, + Sema::AbstractDiagSelID Sel) { + CheckAbstractUsage(*this, D).Visit(TL, Sel); +} + +} + +/// Check for invalid uses of an abstract type in a method declaration. +static void CheckAbstractClassUsage(AbstractUsageInfo &Info, + CXXMethodDecl *MD) { + // No need to do the check on definitions, which require that + // the return/param types be complete. + if (MD->doesThisDeclarationHaveABody()) + return; + + // For safety's sake, just ignore it if we don't have type source + // information. This should never happen for non-implicit methods, + // but... + if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) + Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone); +} + +/// Check for invalid uses of an abstract type within a class definition. +static void CheckAbstractClassUsage(AbstractUsageInfo &Info, + CXXRecordDecl *RD) { + for (CXXRecordDecl::decl_iterator + I = RD->decls_begin(), E = RD->decls_end(); I != E; ++I) { + Decl *D = *I; + if (D->isImplicit()) continue; + + // Methods and method templates. + if (isa<CXXMethodDecl>(D)) { + CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D)); + } else if (isa<FunctionTemplateDecl>(D)) { + FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl(); + CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD)); + + // Fields and static variables. + } else if (isa<FieldDecl>(D)) { + FieldDecl *FD = cast<FieldDecl>(D); + if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) + Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType); + } else if (isa<VarDecl>(D)) { + VarDecl *VD = cast<VarDecl>(D); + if (TypeSourceInfo *TSI = VD->getTypeSourceInfo()) + Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType); + + // Nested classes and class templates. + } else if (isa<CXXRecordDecl>(D)) { + CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D)); + } else if (isa<ClassTemplateDecl>(D)) { + CheckAbstractClassUsage(Info, + cast<ClassTemplateDecl>(D)->getTemplatedDecl()); + } + } +} + +/// \brief Perform semantic checks on a class definition that has been +/// completing, introducing implicitly-declared members, checking for +/// abstract types, etc. +void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { + if (!Record) + return; + + if (Record->isAbstract() && !Record->isInvalidDecl()) { + AbstractUsageInfo Info(*this, Record); + CheckAbstractClassUsage(Info, Record); + } + + // If this is not an aggregate type and has no user-declared constructor, + // complain about any non-static data members of reference or const scalar + // type, since they will never get initializers. + if (!Record->isInvalidDecl() && !Record->isDependentType() && + !Record->isAggregate() && !Record->hasUserDeclaredConstructor()) { + bool Complained = false; + for (RecordDecl::field_iterator F = Record->field_begin(), + FEnd = Record->field_end(); + F != FEnd; ++F) { + if (F->hasInClassInitializer()) + continue; + + if (F->getType()->isReferenceType() || + (F->getType().isConstQualified() && F->getType()->isScalarType())) { + if (!Complained) { + Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst) + << Record->getTagKind() << Record; + Complained = true; + } + + Diag(F->getLocation(), diag::note_refconst_member_not_initialized) + << F->getType()->isReferenceType() + << F->getDeclName(); + } + } + } + + if (Record->isDynamicClass() && !Record->isDependentType()) + DynamicClasses.push_back(Record); + + if (Record->getIdentifier()) { + // C++ [class.mem]p13: + // If T is the name of a class, then each of the following shall have a + // name different from T: + // - every member of every anonymous union that is a member of class T. + // + // C++ [class.mem]p14: + // In addition, if class T has a user-declared constructor (12.1), every + // non-static data member of class T shall have a name different from T. + for (DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); + R.first != R.second; ++R.first) { + NamedDecl *D = *R.first; + if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) || + isa<IndirectFieldDecl>(D)) { + Diag(D->getLocation(), diag::err_member_name_of_class) + << D->getDeclName(); + break; + } + } + } + + // Warn if the class has virtual methods but non-virtual public destructor. + if (Record->isPolymorphic() && !Record->isDependentType()) { + CXXDestructorDecl *dtor = Record->getDestructor(); + if (!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) + Diag(dtor ? dtor->getLocation() : Record->getLocation(), + diag::warn_non_virtual_dtor) << Context.getRecordType(Record); + } + + // See if a method overloads virtual methods in a base + /// class without overriding any. + if (!Record->isDependentType()) { + for (CXXRecordDecl::method_iterator M = Record->method_begin(), + MEnd = Record->method_end(); + M != MEnd; ++M) { + if (!(*M)->isStatic()) + DiagnoseHiddenVirtualMethods(Record, *M); + } + } + + // Declare inherited constructors. We do this eagerly here because: + // - The standard requires an eager diagnostic for conflicting inherited + // constructors from different classes. + // - The lazy declaration of the other implicit constructors is so as to not + // waste space and performance on classes that are not meant to be + // instantiated (e.g. meta-functions). This doesn't apply to classes that + // have inherited constructors. + DeclareInheritedConstructors(Record); + + if (!Record->isDependentType()) + CheckExplicitlyDefaultedMethods(Record); +} + +void Sema::CheckExplicitlyDefaultedMethods(CXXRecordDecl *Record) { + for (CXXRecordDecl::method_iterator MI = Record->method_begin(), + ME = Record->method_end(); + MI != ME; ++MI) { + if (!MI->isInvalidDecl() && MI->isExplicitlyDefaulted()) { + switch (getSpecialMember(*MI)) { + case CXXDefaultConstructor: + CheckExplicitlyDefaultedDefaultConstructor( + cast<CXXConstructorDecl>(*MI)); + break; + + case CXXDestructor: + CheckExplicitlyDefaultedDestructor(cast<CXXDestructorDecl>(*MI)); + break; + + case CXXCopyConstructor: + CheckExplicitlyDefaultedCopyConstructor(cast<CXXConstructorDecl>(*MI)); + break; + + case CXXCopyAssignment: + CheckExplicitlyDefaultedCopyAssignment(*MI); + break; + + case CXXMoveConstructor: + case CXXMoveAssignment: + Diag(MI->getLocation(), diag::err_defaulted_move_unsupported); + break; + + default: + // FIXME: Do moves once they exist + llvm_unreachable("non-special member explicitly defaulted!"); + } + } + } + +} + +void Sema::CheckExplicitlyDefaultedDefaultConstructor(CXXConstructorDecl *CD) { + assert(CD->isExplicitlyDefaulted() && CD->isDefaultConstructor()); + + // Whether this was the first-declared instance of the constructor. + // This affects whether we implicitly add an exception spec (and, eventually, + // constexpr). It is also ill-formed to explicitly default a constructor such + // that it would be deleted. (C++0x [decl.fct.def.default]) + bool First = CD == CD->getCanonicalDecl(); + + bool HadError = false; + if (CD->getNumParams() != 0) { + Diag(CD->getLocation(), diag::err_defaulted_default_ctor_params) + << CD->getSourceRange(); + HadError = true; + } + + ImplicitExceptionSpecification Spec + = ComputeDefaultedDefaultCtorExceptionSpec(CD->getParent()); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + if (EPI.ExceptionSpecType == EST_Delayed) { + // Exception specification depends on some deferred part of the class. We'll + // try again when the class's definition has been fully processed. + return; + } + const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + + if (CtorType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXDefaultConstructor, + PDiag(), + ExceptionType, SourceLocation(), + CtorType, CD->getLocation())) { + HadError = true; + } + } else if (First) { + // We set the declaration to have the computed exception spec here. + // We know there are no parameters. + EPI.ExtInfo = CtorType->getExtInfo(); + CD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + } + + if (HadError) { + CD->setInvalidDecl(); + return; + } + + if (ShouldDeleteDefaultConstructor(CD)) { + if (First) { + CD->setDeletedAsWritten(); + } else { + Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXDefaultConstructor; + CD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) { + assert(CD->isExplicitlyDefaulted() && CD->isCopyConstructor()); + + // Whether this was the first-declared instance of the constructor. + bool First = CD == CD->getCanonicalDecl(); + + bool HadError = false; + if (CD->getNumParams() != 1) { + Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_params) + << CD->getSourceRange(); + HadError = true; + } + + ImplicitExceptionSpecification Spec(Context); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent()); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *CtorType = CD->getType()->getAs<FunctionProtoType>(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + + // Check for parameter type matching. + // This is a copy ctor so we know it's a cv-qualified reference to T. + QualType ArgType = CtorType->getArgType(0); + if (ArgType->getPointeeType().isVolatileQualified()) { + Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_volatile_param); + HadError = true; + } + if (ArgType->getPointeeType().isConstQualified() && !Const) { + Diag(CD->getLocation(), diag::err_defaulted_copy_ctor_const_param); + HadError = true; + } + + if (CtorType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXCopyConstructor, + PDiag(), + ExceptionType, SourceLocation(), + CtorType, CD->getLocation())) { + HadError = true; + } + } else if (First) { + // We set the declaration to have the computed exception spec here. + // We duplicate the one parameter type. + EPI.ExtInfo = CtorType->getExtInfo(); + CD->setType(Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + } + + if (HadError) { + CD->setInvalidDecl(); + return; + } + + if (ShouldDeleteCopyConstructor(CD)) { + if (First) { + CD->setDeletedAsWritten(); + } else { + Diag(CD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXCopyConstructor; + CD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) { + assert(MD->isExplicitlyDefaulted()); + + // Whether this was the first-declared instance of the operator + bool First = MD == MD->getCanonicalDecl(); + + bool HadError = false; + if (MD->getNumParams() != 1) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_params) + << MD->getSourceRange(); + HadError = true; + } + + QualType ReturnType = + MD->getType()->getAs<FunctionType>()->getResultType(); + if (!ReturnType->isLValueReferenceType() || + !Context.hasSameType( + Context.getCanonicalType(ReturnType->getPointeeType()), + Context.getCanonicalType(Context.getTypeDeclType(MD->getParent())))) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_return_type); + HadError = true; + } + + ImplicitExceptionSpecification Spec(Context); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent()); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *OperType = MD->getType()->getAs<FunctionProtoType>(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + + QualType ArgType = OperType->getArgType(0); + if (!ArgType->isReferenceType()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); + HadError = true; + } else { + if (ArgType->getPointeeType().isVolatileQualified()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_volatile_param); + HadError = true; + } + if (ArgType->getPointeeType().isConstQualified() && !Const) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_const_param); + HadError = true; + } + } + + if (OperType->getTypeQuals()) { + Diag(MD->getLocation(), diag::err_defaulted_copy_assign_quals); + HadError = true; + } + + if (OperType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXCopyAssignment, + PDiag(), + ExceptionType, SourceLocation(), + OperType, MD->getLocation())) { + HadError = true; + } + } else if (First) { + // We set the declaration to have the computed exception spec here. + // We duplicate the one parameter type. + EPI.RefQualifier = OperType->getRefQualifier(); + EPI.ExtInfo = OperType->getExtInfo(); + MD->setType(Context.getFunctionType(ReturnType, &ArgType, 1, EPI)); + } + + if (HadError) { + MD->setInvalidDecl(); + return; + } + + if (ShouldDeleteCopyAssignmentOperator(MD)) { + if (First) { + MD->setDeletedAsWritten(); + } else { + Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXCopyAssignment; + MD->setInvalidDecl(); + } + } +} + +void Sema::CheckExplicitlyDefaultedDestructor(CXXDestructorDecl *DD) { + assert(DD->isExplicitlyDefaulted()); + + // Whether this was the first-declared instance of the destructor. + bool First = DD == DD->getCanonicalDecl(); + + ImplicitExceptionSpecification Spec + = ComputeDefaultedDtorExceptionSpec(DD->getParent()); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + const FunctionProtoType *DtorType = DD->getType()->getAs<FunctionProtoType>(), + *ExceptionType = Context.getFunctionType( + Context.VoidTy, 0, 0, EPI)->getAs<FunctionProtoType>(); + + if (DtorType->hasExceptionSpec()) { + if (CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << CXXDestructor, + PDiag(), + ExceptionType, SourceLocation(), + DtorType, DD->getLocation())) { + DD->setInvalidDecl(); + return; + } + } else if (First) { + // We set the declaration to have the computed exception spec here. + // There are no parameters. + EPI.ExtInfo = DtorType->getExtInfo(); + DD->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + } + + if (ShouldDeleteDestructor(DD)) { + if (First) { + DD->setDeletedAsWritten(); + } else { + Diag(DD->getLocation(), diag::err_out_of_line_default_deletes) + << CXXDestructor; + DD->setInvalidDecl(); + } + } +} + +bool Sema::ShouldDeleteDefaultConstructor(CXXConstructorDecl *CD) { + CXXRecordDecl *RD = CD->getParent(); + assert(!RD->isDependentType() && "do deletion after instantiation"); + if (!LangOpts.CPlusPlus0x) + return false; + + SourceLocation Loc = CD->getLocation(); + + // Do access control from the constructor + ContextRAII CtorContext(*this, CD); + + bool Union = RD->isUnion(); + bool AllConst = true; + + // We do this because we should never actually use an anonymous + // union's constructor. + if (Union && RD->isAnonymousStructOrUnion()) + return false; + + // FIXME: We should put some diagnostic logic right into this function. + + // C++0x [class.ctor]/5 + // A defaulted default constructor for class X is defined as deleted if: + + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); + BI != BE; ++BI) { + // We'll handle this one later + if (BI->isVirtual()) + continue; + + CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); + assert(BaseDecl && "base isn't a CXXRecordDecl"); + + // -- any [direct base class] has a type with a destructor that is + // deleted or inaccessible from the defaulted default constructor + CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); + if (BaseDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != + AR_accessible) + return true; + + // -- any [direct base class either] has no default constructor or + // overload resolution as applied to [its] default constructor + // results in an ambiguity or in a function that is deleted or + // inaccessible from the defaulted default constructor + CXXConstructorDecl *BaseDefault = LookupDefaultConstructor(BaseDecl); + if (!BaseDefault || BaseDefault->isDeleted()) + return true; + + if (CheckConstructorAccess(Loc, BaseDefault, BaseDefault->getAccess(), + PDiag()) != AR_accessible) + return true; + } + + for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), + BE = RD->vbases_end(); + BI != BE; ++BI) { + CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); + assert(BaseDecl && "base isn't a CXXRecordDecl"); + + // -- any [virtual base class] has a type with a destructor that is + // delete or inaccessible from the defaulted default constructor + CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); + if (BaseDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != + AR_accessible) + return true; + + // -- any [virtual base class either] has no default constructor or + // overload resolution as applied to [its] default constructor + // results in an ambiguity or in a function that is deleted or + // inaccessible from the defaulted default constructor + CXXConstructorDecl *BaseDefault = LookupDefaultConstructor(BaseDecl); + if (!BaseDefault || BaseDefault->isDeleted()) + return true; + + if (CheckConstructorAccess(Loc, BaseDefault, BaseDefault->getAccess(), + PDiag()) != AR_accessible) + return true; + } + + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); + FI != FE; ++FI) { + if (FI->isInvalidDecl()) + continue; + + QualType FieldType = Context.getBaseElementType(FI->getType()); + CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + + // -- any non-static data member with no brace-or-equal-initializer is of + // reference type + if (FieldType->isReferenceType() && !FI->hasInClassInitializer()) + return true; + + // -- X is a union and all its variant members are of const-qualified type + // (or array thereof) + if (Union && !FieldType.isConstQualified()) + AllConst = false; + + if (FieldRecord) { + // -- X is a union-like class that has a variant member with a non-trivial + // default constructor + if (Union && !FieldRecord->hasTrivialDefaultConstructor()) + return true; + + CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); + if (FieldDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != + AR_accessible) + return true; + + // -- any non-variant non-static data member of const-qualified type (or + // array thereof) with no brace-or-equal-initializer does not have a + // user-provided default constructor + if (FieldType.isConstQualified() && + !FI->hasInClassInitializer() && + !FieldRecord->hasUserProvidedDefaultConstructor()) + return true; + + if (!Union && FieldRecord->isUnion() && + FieldRecord->isAnonymousStructOrUnion()) { + // We're okay to reuse AllConst here since we only care about the + // value otherwise if we're in a union. + AllConst = true; + + for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), + UE = FieldRecord->field_end(); + UI != UE; ++UI) { + QualType UnionFieldType = Context.getBaseElementType(UI->getType()); + CXXRecordDecl *UnionFieldRecord = + UnionFieldType->getAsCXXRecordDecl(); + + if (!UnionFieldType.isConstQualified()) + AllConst = false; + + if (UnionFieldRecord && + !UnionFieldRecord->hasTrivialDefaultConstructor()) + return true; + } + + if (AllConst) + return true; + + // Don't try to initialize the anonymous union + // This is technically non-conformant, but sanity demands it. + continue; + } + + // -- any non-static data member with no brace-or-equal-initializer has + // class type M (or array thereof) and either M has no default + // constructor or overload resolution as applied to M's default + // constructor results in an ambiguity or in a function that is deleted + // or inaccessible from the defaulted default constructor. + if (!FI->hasInClassInitializer()) { + CXXConstructorDecl *FieldDefault = LookupDefaultConstructor(FieldRecord); + if (!FieldDefault || FieldDefault->isDeleted()) + return true; + if (CheckConstructorAccess(Loc, FieldDefault, FieldDefault->getAccess(), + PDiag()) != AR_accessible) + return true; + } + } else if (!Union && FieldType.isConstQualified() && + !FI->hasInClassInitializer()) { + // -- any non-variant non-static data member of const-qualified type (or + // array thereof) with no brace-or-equal-initializer does not have a + // user-provided default constructor + return true; + } + } + + if (Union && AllConst) + return true; + + return false; +} + +bool Sema::ShouldDeleteCopyConstructor(CXXConstructorDecl *CD) { + CXXRecordDecl *RD = CD->getParent(); + assert(!RD->isDependentType() && "do deletion after instantiation"); + if (!LangOpts.CPlusPlus0x) + return false; + + SourceLocation Loc = CD->getLocation(); + + // Do access control from the constructor + ContextRAII CtorContext(*this, CD); + + bool Union = RD->isUnion(); + + assert(!CD->getParamDecl(0)->getType()->getPointeeType().isNull() && + "copy assignment arg has no pointee type"); + unsigned ArgQuals = + CD->getParamDecl(0)->getType()->getPointeeType().isConstQualified() ? + Qualifiers::Const : 0; + + // We do this because we should never actually use an anonymous + // union's constructor. + if (Union && RD->isAnonymousStructOrUnion()) + return false; + + // FIXME: We should put some diagnostic logic right into this function. + + // C++0x [class.copy]/11 + // A defaulted [copy] constructor for class X is defined as delete if X has: + + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); + BI != BE; ++BI) { + // We'll handle this one later + if (BI->isVirtual()) + continue; + + QualType BaseType = BI->getType(); + CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); + assert(BaseDecl && "base isn't a CXXRecordDecl"); + + // -- any [direct base class] of a type with a destructor that is deleted or + // inaccessible from the defaulted constructor + CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); + if (BaseDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != + AR_accessible) + return true; + + // -- a [direct base class] B that cannot be [copied] because overload + // resolution, as applied to B's [copy] constructor, results in an + // ambiguity or a function that is deleted or inaccessible from the + // defaulted constructor + CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals); + if (!BaseCtor || BaseCtor->isDeleted()) + return true; + if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) != + AR_accessible) + return true; + } + + for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), + BE = RD->vbases_end(); + BI != BE; ++BI) { + QualType BaseType = BI->getType(); + CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); + assert(BaseDecl && "base isn't a CXXRecordDecl"); + + // -- any [virtual base class] of a type with a destructor that is deleted or + // inaccessible from the defaulted constructor + CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); + if (BaseDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != + AR_accessible) + return true; + + // -- a [virtual base class] B that cannot be [copied] because overload + // resolution, as applied to B's [copy] constructor, results in an + // ambiguity or a function that is deleted or inaccessible from the + // defaulted constructor + CXXConstructorDecl *BaseCtor = LookupCopyConstructor(BaseDecl, ArgQuals); + if (!BaseCtor || BaseCtor->isDeleted()) + return true; + if (CheckConstructorAccess(Loc, BaseCtor, BaseCtor->getAccess(), PDiag()) != + AR_accessible) + return true; + } + + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); + FI != FE; ++FI) { + QualType FieldType = Context.getBaseElementType(FI->getType()); + + // -- for a copy constructor, a non-static data member of rvalue reference + // type + if (FieldType->isRValueReferenceType()) + return true; + + CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + + if (FieldRecord) { + // This is an anonymous union + if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { + // Anonymous unions inside unions do not variant members create + if (!Union) { + for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), + UE = FieldRecord->field_end(); + UI != UE; ++UI) { + QualType UnionFieldType = Context.getBaseElementType(UI->getType()); + CXXRecordDecl *UnionFieldRecord = + UnionFieldType->getAsCXXRecordDecl(); + + // -- a variant member with a non-trivial [copy] constructor and X + // is a union-like class + if (UnionFieldRecord && + !UnionFieldRecord->hasTrivialCopyConstructor()) + return true; + } + } + + // Don't try to initalize an anonymous union + continue; + } else { + // -- a variant member with a non-trivial [copy] constructor and X is a + // union-like class + if (Union && !FieldRecord->hasTrivialCopyConstructor()) + return true; + + // -- any [non-static data member] of a type with a destructor that is + // deleted or inaccessible from the defaulted constructor + CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); + if (FieldDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != + AR_accessible) + return true; + } + + // -- a [non-static data member of class type (or array thereof)] B that + // cannot be [copied] because overload resolution, as applied to B's + // [copy] constructor, results in an ambiguity or a function that is + // deleted or inaccessible from the defaulted constructor + CXXConstructorDecl *FieldCtor = LookupCopyConstructor(FieldRecord, + ArgQuals); + if (!FieldCtor || FieldCtor->isDeleted()) + return true; + if (CheckConstructorAccess(Loc, FieldCtor, FieldCtor->getAccess(), + PDiag()) != AR_accessible) + return true; + } + } + + return false; +} + +bool Sema::ShouldDeleteCopyAssignmentOperator(CXXMethodDecl *MD) { + CXXRecordDecl *RD = MD->getParent(); + assert(!RD->isDependentType() && "do deletion after instantiation"); + if (!LangOpts.CPlusPlus0x) + return false; + + SourceLocation Loc = MD->getLocation(); + + // Do access control from the constructor + ContextRAII MethodContext(*this, MD); + + bool Union = RD->isUnion(); + + bool ConstArg = + MD->getParamDecl(0)->getType()->getPointeeType().isConstQualified(); + + // We do this because we should never actually use an anonymous + // union's constructor. + if (Union && RD->isAnonymousStructOrUnion()) + return false; + + DeclarationName OperatorName = + Context.DeclarationNames.getCXXOperatorName(OO_Equal); + LookupResult R(*this, OperatorName, Loc, LookupOrdinaryName); + R.suppressDiagnostics(); + + // FIXME: We should put some diagnostic logic right into this function. + + // C++0x [class.copy]/11 + // A defaulted [copy] assignment operator for class X is defined as deleted + // if X has: + + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); + BI != BE; ++BI) { + // We'll handle this one later + if (BI->isVirtual()) + continue; + + QualType BaseType = BI->getType(); + CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); + assert(BaseDecl && "base isn't a CXXRecordDecl"); + + // -- a [direct base class] B that cannot be [copied] because overload + // resolution, as applied to B's [copy] assignment operator, results in + // an ambiguity or a function that is deleted or inaccessible from the + // assignment operator + + LookupQualifiedName(R, BaseDecl, false); + + // Filter out any result that isn't a copy-assignment operator. + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + if (Method->isCopyAssignmentOperator()) + continue; + + F.erase(); + } + F.done(); + + // Build a fake argument expression + QualType ArgType = BaseType; + QualType ThisType = BaseType; + if (ConstArg) + ArgType.addConst(); + Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue) + , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue) + }; + + OverloadCandidateSet OCS((Loc)); + OverloadCandidateSet::iterator Best; + + AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS); + + if (OCS.BestViableFunction(*this, Loc, Best, false) != + OR_Success) + return true; + } + + for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), + BE = RD->vbases_end(); + BI != BE; ++BI) { + QualType BaseType = BI->getType(); + CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl(); + assert(BaseDecl && "base isn't a CXXRecordDecl"); + + // -- a [virtual base class] B that cannot be [copied] because overload + // resolution, as applied to B's [copy] assignment operator, results in + // an ambiguity or a function that is deleted or inaccessible from the + // assignment operator + + LookupQualifiedName(R, BaseDecl, false); + + // Filter out any result that isn't a copy-assignment operator. + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + if (Method->isCopyAssignmentOperator()) + continue; + + F.erase(); + } + F.done(); + + // Build a fake argument expression + QualType ArgType = BaseType; + QualType ThisType = BaseType; + if (ConstArg) + ArgType.addConst(); + Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue) + , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue) + }; + + OverloadCandidateSet OCS((Loc)); + OverloadCandidateSet::iterator Best; + + AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS); + + if (OCS.BestViableFunction(*this, Loc, Best, false) != + OR_Success) + return true; + } + + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); + FI != FE; ++FI) { + QualType FieldType = Context.getBaseElementType(FI->getType()); + + // -- a non-static data member of reference type + if (FieldType->isReferenceType()) + return true; + + // -- a non-static data member of const non-class type (or array thereof) + if (FieldType.isConstQualified() && !FieldType->isRecordType()) + return true; + + CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + + if (FieldRecord) { + // This is an anonymous union + if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { + // Anonymous unions inside unions do not variant members create + if (!Union) { + for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), + UE = FieldRecord->field_end(); + UI != UE; ++UI) { + QualType UnionFieldType = Context.getBaseElementType(UI->getType()); + CXXRecordDecl *UnionFieldRecord = + UnionFieldType->getAsCXXRecordDecl(); + + // -- a variant member with a non-trivial [copy] assignment operator + // and X is a union-like class + if (UnionFieldRecord && + !UnionFieldRecord->hasTrivialCopyAssignment()) + return true; + } + } + + // Don't try to initalize an anonymous union + continue; + // -- a variant member with a non-trivial [copy] assignment operator + // and X is a union-like class + } else if (Union && !FieldRecord->hasTrivialCopyAssignment()) { + return true; + } + + LookupQualifiedName(R, FieldRecord, false); + + // Filter out any result that isn't a copy-assignment operator. + LookupResult::Filter F = R.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + if (Method->isCopyAssignmentOperator()) + continue; + + F.erase(); + } + F.done(); + + // Build a fake argument expression + QualType ArgType = FieldType; + QualType ThisType = FieldType; + if (ConstArg) + ArgType.addConst(); + Expr *Args[] = { new (Context) OpaqueValueExpr(Loc, ThisType, VK_LValue) + , new (Context) OpaqueValueExpr(Loc, ArgType, VK_LValue) + }; + + OverloadCandidateSet OCS((Loc)); + OverloadCandidateSet::iterator Best; + + AddFunctionCandidates(R.asUnresolvedSet(), Args, 2, OCS); + + if (OCS.BestViableFunction(*this, Loc, Best, false) != + OR_Success) + return true; + } + } + + return false; +} + +bool Sema::ShouldDeleteDestructor(CXXDestructorDecl *DD) { + CXXRecordDecl *RD = DD->getParent(); + assert(!RD->isDependentType() && "do deletion after instantiation"); + if (!LangOpts.CPlusPlus0x) + return false; + + SourceLocation Loc = DD->getLocation(); + + // Do access control from the destructor + ContextRAII CtorContext(*this, DD); + + bool Union = RD->isUnion(); + + // We do this because we should never actually use an anonymous + // union's destructor. + if (Union && RD->isAnonymousStructOrUnion()) + return false; + + // C++0x [class.dtor]p5 + // A defaulted destructor for a class X is defined as deleted if: + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); + BI != BE; ++BI) { + // We'll handle this one later + if (BI->isVirtual()) + continue; + + CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); + CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); + assert(BaseDtor && "base has no destructor"); + + // -- any direct or virtual base class has a deleted destructor or + // a destructor that is inaccessible from the defaulted destructor + if (BaseDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != + AR_accessible) + return true; + } + + for (CXXRecordDecl::base_class_iterator BI = RD->vbases_begin(), + BE = RD->vbases_end(); + BI != BE; ++BI) { + CXXRecordDecl *BaseDecl = BI->getType()->getAsCXXRecordDecl(); + CXXDestructorDecl *BaseDtor = LookupDestructor(BaseDecl); + assert(BaseDtor && "base has no destructor"); + + // -- any direct or virtual base class has a deleted destructor or + // a destructor that is inaccessible from the defaulted destructor + if (BaseDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, BaseDtor, PDiag()) != + AR_accessible) + return true; + } + + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); + FI != FE; ++FI) { + QualType FieldType = Context.getBaseElementType(FI->getType()); + CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); + if (FieldRecord) { + if (FieldRecord->isUnion() && FieldRecord->isAnonymousStructOrUnion()) { + for (CXXRecordDecl::field_iterator UI = FieldRecord->field_begin(), + UE = FieldRecord->field_end(); + UI != UE; ++UI) { + QualType UnionFieldType = Context.getBaseElementType(FI->getType()); + CXXRecordDecl *UnionFieldRecord = + UnionFieldType->getAsCXXRecordDecl(); + + // -- X is a union-like class that has a variant member with a non- + // trivial destructor. + if (UnionFieldRecord && !UnionFieldRecord->hasTrivialDestructor()) + return true; + } + // Technically we are supposed to do this next check unconditionally. + // But that makes absolutely no sense. + } else { + CXXDestructorDecl *FieldDtor = LookupDestructor(FieldRecord); + + // -- any of the non-static data members has class type M (or array + // thereof) and M has a deleted destructor or a destructor that is + // inaccessible from the defaulted destructor + if (FieldDtor->isDeleted()) + return true; + if (CheckDestructorAccess(Loc, FieldDtor, PDiag()) != + AR_accessible) + return true; + + // -- X is a union-like class that has a variant member with a non- + // trivial destructor. + if (Union && !FieldDtor->isTrivial()) + return true; + } + } + } + + if (DD->isVirtual()) { + FunctionDecl *OperatorDelete = 0; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete, + false)) + return true; + } + + + return false; +} + +/// \brief Data used with FindHiddenVirtualMethod +namespace { + struct FindHiddenVirtualMethodData { + Sema *S; + CXXMethodDecl *Method; + llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; + llvm::SmallVector<CXXMethodDecl *, 8> OverloadedMethods; + }; +} + +/// \brief Member lookup function that determines whether a given C++ +/// method overloads virtual methods in a base class without overriding any, +/// to be used with CXXRecordDecl::lookupInBases(). +static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *UserData) { + RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); + + FindHiddenVirtualMethodData &Data + = *static_cast<FindHiddenVirtualMethodData*>(UserData); + + DeclarationName Name = Data.Method->getDeclName(); + assert(Name.getNameKind() == DeclarationName::Identifier); + + bool foundSameNameMethod = false; + llvm::SmallVector<CXXMethodDecl *, 8> overloadedMethods; + for (Path.Decls = BaseRecord->lookup(Name); + Path.Decls.first != Path.Decls.second; + ++Path.Decls.first) { + NamedDecl *D = *Path.Decls.first; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + MD = MD->getCanonicalDecl(); + foundSameNameMethod = true; + // Interested only in hidden virtual methods. + if (!MD->isVirtual()) + continue; + // If the method we are checking overrides a method from its base + // don't warn about the other overloaded methods. + if (!Data.S->IsOverload(Data.Method, MD, false)) + return true; + // Collect the overload only if its hidden. + if (!Data.OverridenAndUsingBaseMethods.count(MD)) + overloadedMethods.push_back(MD); + } + } + + if (foundSameNameMethod) + Data.OverloadedMethods.append(overloadedMethods.begin(), + overloadedMethods.end()); + return foundSameNameMethod; +} + +/// \brief See if a method overloads virtual methods in a base class without +/// overriding any. +void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { + if (Diags.getDiagnosticLevel(diag::warn_overloaded_virtual, + MD->getLocation()) == Diagnostic::Ignored) + return; + if (MD->getDeclName().getNameKind() != DeclarationName::Identifier) + return; + + CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases. + /*bool RecordPaths=*/false, + /*bool DetectVirtual=*/false); + FindHiddenVirtualMethodData Data; + Data.Method = MD; + Data.S = this; + + // Keep the base methods that were overriden or introduced in the subclass + // by 'using' in a set. A base method not in this set is hidden. + for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName()); + res.first != res.second; ++res.first) { + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*res.first)) + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) + Data.OverridenAndUsingBaseMethods.insert((*I)->getCanonicalDecl()); + if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first)) + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(shad->getTargetDecl())) + Data.OverridenAndUsingBaseMethods.insert(MD->getCanonicalDecl()); + } + + if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) && + !Data.OverloadedMethods.empty()) { + Diag(MD->getLocation(), diag::warn_overloaded_virtual) + << MD << (Data.OverloadedMethods.size() > 1); + + for (unsigned i = 0, e = Data.OverloadedMethods.size(); i != e; ++i) { + CXXMethodDecl *overloadedMD = Data.OverloadedMethods[i]; + Diag(overloadedMD->getLocation(), + diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD; + } + } +} + +void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, + Decl *TagDecl, + SourceLocation LBrac, + SourceLocation RBrac, + AttributeList *AttrList) { + if (!TagDecl) + return; + + AdjustDeclIfTemplate(TagDecl); + + ActOnFields(S, RLoc, TagDecl, + // strict aliasing violation! + reinterpret_cast<Decl**>(FieldCollector->getCurFields()), + FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList); + + CheckCompletedCXXClass( + dyn_cast_or_null<CXXRecordDecl>(TagDecl)); +} + +/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared +/// special functions, such as the default constructor, copy +/// constructor, or destructor, to the given C++ class (C++ +/// [special]p1). This routine can only be executed just before the +/// definition of the class is complete. +void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { + if (!ClassDecl->hasUserDeclaredConstructor()) + ++ASTContext::NumImplicitDefaultConstructors; + + if (!ClassDecl->hasUserDeclaredCopyConstructor()) + ++ASTContext::NumImplicitCopyConstructors; + + if (!ClassDecl->hasUserDeclaredCopyAssignment()) { + ++ASTContext::NumImplicitCopyAssignmentOperators; + + // If we have a dynamic class, then the copy assignment operator may be + // virtual, so we have to declare it immediately. This ensures that, e.g., + // it shows up in the right place in the vtable and that we diagnose + // problems with the implicit exception specification. + if (ClassDecl->isDynamicClass()) + DeclareImplicitCopyAssignment(ClassDecl); + } + + if (!ClassDecl->hasUserDeclaredDestructor()) { + ++ASTContext::NumImplicitDestructors; + + // If we have a dynamic class, then the destructor may be virtual, so we + // have to declare the destructor immediately. This ensures that, e.g., it + // shows up in the right place in the vtable and that we diagnose problems + // with the implicit exception specification. + if (ClassDecl->isDynamicClass()) + DeclareImplicitDestructor(ClassDecl); + } +} + +void Sema::ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D) { + if (!D) + return; + + int NumParamList = D->getNumTemplateParameterLists(); + for (int i = 0; i < NumParamList; i++) { + TemplateParameterList* Params = D->getTemplateParameterList(i); + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + NamedDecl *Named = cast<NamedDecl>(*Param); + if (Named->getDeclName()) { + S->AddDecl(Named); + IdResolver.AddDecl(Named); + } + } + } +} + +void Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { + if (!D) + return; + + TemplateParameterList *Params = 0; + if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) + Params = Template->getTemplateParameters(); + else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) + Params = PartialSpec->getTemplateParameters(); + else + return; + + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + Param != ParamEnd; ++Param) { + NamedDecl *Named = cast<NamedDecl>(*Param); + if (Named->getDeclName()) { + S->AddDecl(Named); + IdResolver.AddDecl(Named); + } + } +} + +void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) { + if (!RecordD) return; + AdjustDeclIfTemplate(RecordD); + CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD); + PushDeclContext(S, Record); +} + +void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) { + if (!RecordD) return; + PopDeclContext(); +} + +/// ActOnStartDelayedCXXMethodDeclaration - We have completed +/// parsing a top-level (non-nested) C++ class, and we are now +/// parsing those parts of the given Method declaration that could +/// not be parsed earlier (C++ [class.mem]p2), such as default +/// arguments. This action should enter the scope of the given +/// Method declaration as if we had just parsed the qualified method +/// name. However, it should not bring the parameters into scope; +/// that will be performed by ActOnDelayedCXXMethodParameter. +void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { +} + +/// ActOnDelayedCXXMethodParameter - We've already started a delayed +/// C++ method declaration. We're (re-)introducing the given +/// function parameter into scope for use in parsing later parts of +/// the method declaration. For example, we could see an +/// ActOnParamDefaultArgument event for this parameter. +void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { + if (!ParamD) + return; + + ParmVarDecl *Param = cast<ParmVarDecl>(ParamD); + + // If this parameter has an unparsed default argument, clear it out + // to make way for the parsed default argument. + if (Param->hasUnparsedDefaultArg()) + Param->setDefaultArg(0); + + S->AddDecl(Param); + if (Param->getDeclName()) + IdResolver.AddDecl(Param); +} + +/// ActOnFinishDelayedCXXMethodDeclaration - We have finished +/// processing the delayed method declaration for Method. The method +/// declaration is now considered finished. There may be a separate +/// ActOnStartOfFunctionDef action later (not necessarily +/// immediately!) for this method, if it was also defined inside the +/// class body. +void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { + if (!MethodD) + return; + + AdjustDeclIfTemplate(MethodD); + + FunctionDecl *Method = cast<FunctionDecl>(MethodD); + + // Now that we have our default arguments, check the constructor + // again. It could produce additional diagnostics or affect whether + // the class has implicitly-declared destructors, among other + // things. + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method)) + CheckConstructor(Constructor); + + // Check the default arguments, which we may have added. + if (!Method->isInvalidDecl()) + CheckCXXDefaultArguments(Method); +} + +/// CheckConstructorDeclarator - Called by ActOnDeclarator to check +/// the well-formedness of the constructor declarator @p D with type @p +/// R. If there are any errors in the declarator, this routine will +/// emit diagnostics and set the invalid bit to true. In any case, the type +/// will be updated to reflect a well-formed type for the constructor and +/// returned. +QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, + StorageClass &SC) { + bool isVirtual = D.getDeclSpec().isVirtualSpecified(); + + // C++ [class.ctor]p3: + // A constructor shall not be virtual (10.3) or static (9.4). A + // constructor can be invoked for a const, volatile or const + // volatile object. A constructor shall not be declared const, + // volatile, or const volatile (9.3.2). + if (isVirtual) { + if (!D.isInvalidType()) + Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) + << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc()) + << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + if (SC == SC_Static) { + if (!D.isInvalidType()) + Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) + << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) + << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + SC = SC_None; + } + + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.TypeQuals != 0) { + if (FTI.TypeQuals & Qualifiers::Const) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) + << "const" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Volatile) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) + << "volatile" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Restrict) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) + << "restrict" << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + + // C++0x [class.ctor]p4: + // A constructor shall not be declared with a ref-qualifier. + if (FTI.hasRefQualifier()) { + Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor) + << FTI.RefQualifierIsLValueRef + << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); + D.setInvalidType(); + } + + // Rebuild the function type "R" without any type qualifiers (in + // case any of the errors above fired) and with "void" as the + // return type, since constructors don't have return types. + const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); + if (Proto->getResultType() == Context.VoidTy && !D.isInvalidType()) + return R; + + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.TypeQuals = 0; + EPI.RefQualifier = RQ_None; + + return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), + Proto->getNumArgs(), EPI); +} + +/// CheckConstructor - Checks a fully-formed constructor for +/// well-formedness, issuing any diagnostics required. Returns true if +/// the constructor declarator is invalid. +void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { + CXXRecordDecl *ClassDecl + = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext()); + if (!ClassDecl) + return Constructor->setInvalidDecl(); + + // C++ [class.copy]p3: + // A declaration of a constructor for a class X is ill-formed if + // its first parameter is of type (optionally cv-qualified) X and + // either there are no other parameters or else all other + // parameters have default arguments. + if (!Constructor->isInvalidDecl() && + ((Constructor->getNumParams() == 1) || + (Constructor->getNumParams() > 1 && + Constructor->getParamDecl(1)->hasDefaultArg())) && + Constructor->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation) { + QualType ParamType = Constructor->getParamDecl(0)->getType(); + QualType ClassTy = Context.getTagDeclType(ClassDecl); + if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { + SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); + const char *ConstRef + = Constructor->getParamDecl(0)->getIdentifier() ? "const &" + : " const &"; + Diag(ParamLoc, diag::err_constructor_byvalue_arg) + << FixItHint::CreateInsertion(ParamLoc, ConstRef); + + // FIXME: Rather that making the constructor invalid, we should endeavor + // to fix the type. + Constructor->setInvalidDecl(); + } + } +} + +/// CheckDestructor - Checks a fully-formed destructor definition for +/// well-formedness, issuing any diagnostics required. Returns true +/// on error. +bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { + CXXRecordDecl *RD = Destructor->getParent(); + + if (Destructor->isVirtual()) { + SourceLocation Loc; + + if (!Destructor->isImplicit()) + Loc = Destructor->getLocation(); + else + Loc = RD->getLocation(); + + // If we have a virtual destructor, look up the deallocation function + FunctionDecl *OperatorDelete = 0; + DeclarationName Name = + Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) + return true; + + MarkDeclarationReferenced(Loc, OperatorDelete); + + Destructor->setOperatorDelete(OperatorDelete); + } + + return false; +} + +static inline bool +FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { + return (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && + FTI.ArgInfo[0].Param && + cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()); +} + +/// CheckDestructorDeclarator - Called by ActOnDeclarator to check +/// the well-formednes of the destructor declarator @p D with type @p +/// R. If there are any errors in the declarator, this routine will +/// emit diagnostics and set the declarator to invalid. Even if this happens, +/// will be updated to reflect a well-formed type for the destructor and +/// returned. +QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, + StorageClass& SC) { + // C++ [class.dtor]p1: + // [...] A typedef-name that names a class is a class-name + // (7.1.3); however, a typedef-name that names a class shall not + // be used as the identifier in the declarator for a destructor + // declaration. + QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); + if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>()) + Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) + << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl()); + else if (const TemplateSpecializationType *TST = + DeclaratorType->getAs<TemplateSpecializationType>()) + if (TST->isTypeAlias()) + Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) + << DeclaratorType << 1; + + // C++ [class.dtor]p2: + // A destructor is used to destroy objects of its class type. A + // destructor takes no parameters, and no return type can be + // specified for it (not even void). The address of a destructor + // shall not be taken. A destructor shall not be static. A + // destructor can be invoked for a const, volatile or const + // volatile object. A destructor shall not be declared const, + // volatile or const volatile (9.3.2). + if (SC == SC_Static) { + if (!D.isInvalidType()) + Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be) + << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) + << SourceRange(D.getIdentifierLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + + SC = SC_None; + } + if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { + // Destructors don't have return types, but the parser will + // happily parse something like: + // + // class X { + // float ~X(); + // }; + // + // The return type will be eliminated later. + Diag(D.getIdentifierLoc(), diag::err_destructor_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + } + + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.TypeQuals != 0 && !D.isInvalidType()) { + if (FTI.TypeQuals & Qualifiers::Const) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) + << "const" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Volatile) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) + << "volatile" << SourceRange(D.getIdentifierLoc()); + if (FTI.TypeQuals & Qualifiers::Restrict) + Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) + << "restrict" << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + + // C++0x [class.dtor]p2: + // A destructor shall not be declared with a ref-qualifier. + if (FTI.hasRefQualifier()) { + Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor) + << FTI.RefQualifierIsLValueRef + << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); + D.setInvalidType(); + } + + // Make sure we don't have any parameters. + if (FTI.NumArgs > 0 && !FTIHasSingleVoidArgument(FTI)) { + Diag(D.getIdentifierLoc(), diag::err_destructor_with_params); + + // Delete the parameters. + FTI.freeArgs(); + D.setInvalidType(); + } + + // Make sure the destructor isn't variadic. + if (FTI.isVariadic) { + Diag(D.getIdentifierLoc(), diag::err_destructor_variadic); + D.setInvalidType(); + } + + // Rebuild the function type "R" without any type qualifiers or + // parameters (in case any of the errors above fired) and with + // "void" as the return type, since destructors don't have return + // types. + if (!D.isInvalidType()) + return R; + + const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.Variadic = false; + EPI.TypeQuals = 0; + EPI.RefQualifier = RQ_None; + return Context.getFunctionType(Context.VoidTy, 0, 0, EPI); +} + +/// CheckConversionDeclarator - Called by ActOnDeclarator to check the +/// well-formednes of the conversion function declarator @p D with +/// type @p R. If there are any errors in the declarator, this routine +/// will emit diagnostics and return true. Otherwise, it will return +/// false. Either way, the type @p R will be updated to reflect a +/// well-formed type for the conversion operator. +void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, + StorageClass& SC) { + // C++ [class.conv.fct]p1: + // Neither parameter types nor return type can be specified. The + // type of a conversion function (8.3.5) is "function taking no + // parameter returning conversion-type-id." + if (SC == SC_Static) { + if (!D.isInvalidType()) + Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member) + << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) + << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + SC = SC_None; + } + + QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId); + + if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { + // Conversion functions don't have return types, but the parser will + // happily parse something like: + // + // class X { + // float operator bool(); + // }; + // + // The return type will be changed later anyway. + Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type) + << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) + << SourceRange(D.getIdentifierLoc()); + D.setInvalidType(); + } + + const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); + + // Make sure we don't have any parameters. + if (Proto->getNumArgs() > 0) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); + + // Delete the parameters. + D.getFunctionTypeInfo().freeArgs(); + D.setInvalidType(); + } else if (Proto->isVariadic()) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); + D.setInvalidType(); + } + + // Diagnose "&operator bool()" and other such nonsense. This + // is actually a gcc extension which we don't support. + if (Proto->getResultType() != ConvType) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl) + << Proto->getResultType(); + D.setInvalidType(); + ConvType = Proto->getResultType(); + } + + // C++ [class.conv.fct]p4: + // The conversion-type-id shall not represent a function type nor + // an array type. + if (ConvType->isArrayType()) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array); + ConvType = Context.getPointerType(ConvType); + D.setInvalidType(); + } else if (ConvType->isFunctionType()) { + Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function); + ConvType = Context.getPointerType(ConvType); + D.setInvalidType(); + } + + // Rebuild the function type "R" without any parameters (in case any + // of the errors above fired) and with the conversion type as the + // return type. + if (D.isInvalidType()) + R = Context.getFunctionType(ConvType, 0, 0, Proto->getExtProtoInfo()); + + // C++0x explicit conversion operators. + if (D.getDeclSpec().isExplicitSpecified() && !getLangOptions().CPlusPlus0x) + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::warn_explicit_conversion_functions) + << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); +} + +/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete +/// the declaration of the given C++ conversion function. This routine +/// is responsible for recording the conversion function in the C++ +/// class, if possible. +Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { + assert(Conversion && "Expected to receive a conversion function declaration"); + + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext()); + + // Make sure we aren't redeclaring the conversion function. + QualType ConvType = Context.getCanonicalType(Conversion->getConversionType()); + + // C++ [class.conv.fct]p1: + // [...] A conversion function is never used to convert a + // (possibly cv-qualified) object to the (possibly cv-qualified) + // same object type (or a reference to it), to a (possibly + // cv-qualified) base class of that type (or a reference to it), + // or to (possibly cv-qualified) void. + // FIXME: Suppress this warning if the conversion function ends up being a + // virtual function that overrides a virtual function in a base class. + QualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>()) + ConvType = ConvTypeRef->getPointeeType(); + if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared && + Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + /* Suppress diagnostics for instantiations. */; + else if (ConvType->isRecordType()) { + ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType(); + if (ConvType == ClassType) + Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used) + << ClassType; + else if (IsDerivedFrom(ClassType, ConvType)) + Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used) + << ClassType << ConvType; + } else if (ConvType->isVoidType()) { + Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used) + << ClassType << ConvType; + } + + if (FunctionTemplateDecl *ConversionTemplate + = Conversion->getDescribedFunctionTemplate()) + return ConversionTemplate; + + return Conversion; +} + +//===----------------------------------------------------------------------===// +// Namespace Handling +//===----------------------------------------------------------------------===// + + + +/// ActOnStartNamespaceDef - This is called at the start of a namespace +/// definition. +Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, + SourceLocation InlineLoc, + SourceLocation NamespaceLoc, + SourceLocation IdentLoc, + IdentifierInfo *II, + SourceLocation LBrace, + AttributeList *AttrList) { + SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; + // For anonymous namespace, take the location of the left brace. + SourceLocation Loc = II ? IdentLoc : LBrace; + NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, + StartLoc, Loc, II); + Namespc->setInline(InlineLoc.isValid()); + + Scope *DeclRegionScope = NamespcScope->getParent(); + + ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); + + if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) + PushNamespaceVisibilityAttr(Attr); + + if (II) { + // C++ [namespace.def]p2: + // The identifier in an original-namespace-definition shall not + // have been previously defined in the declarative region in + // which the original-namespace-definition appears. The + // identifier in an original-namespace-definition is the name of + // the namespace. Subsequently in that declarative region, it is + // treated as an original-namespace-name. + // + // Since namespace names are unique in their scope, and we don't + // look through using directives, just look for any ordinary names. + + const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | + Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | + Decl::IDNS_Namespace; + NamedDecl *PrevDecl = 0; + for (DeclContext::lookup_result R + = CurContext->getRedeclContext()->lookup(II); + R.first != R.second; ++R.first) { + if ((*R.first)->getIdentifierNamespace() & IDNS) { + PrevDecl = *R.first; + break; + } + } + + if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) { + // This is an extended namespace definition. + if (Namespc->isInline() != OrigNS->isInline()) { + // inline-ness must match + if (OrigNS->isInline()) { + // The user probably just forgot the 'inline', so suggest that it + // be added back. + Diag(Namespc->getLocation(), + diag::warn_inline_namespace_reopened_noninline) + << FixItHint::CreateInsertion(NamespaceLoc, "inline "); + } else { + Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) + << Namespc->isInline(); + } + Diag(OrigNS->getLocation(), diag::note_previous_definition); + + // Recover by ignoring the new namespace's inline status. + Namespc->setInline(OrigNS->isInline()); + } + + // Attach this namespace decl to the chain of extended namespace + // definitions. + OrigNS->setNextNamespace(Namespc); + Namespc->setOriginalNamespace(OrigNS->getOriginalNamespace()); + + // Remove the previous declaration from the scope. + if (DeclRegionScope->isDeclScope(OrigNS)) { + IdResolver.RemoveDecl(OrigNS); + DeclRegionScope->RemoveDecl(OrigNS); + } + } else if (PrevDecl) { + // This is an invalid name redefinition. + Diag(Namespc->getLocation(), diag::err_redefinition_different_kind) + << Namespc->getDeclName(); + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + Namespc->setInvalidDecl(); + // Continue on to push Namespc as current DeclContext and return it. + } else if (II->isStr("std") && + CurContext->getRedeclContext()->isTranslationUnit()) { + // This is the first "real" definition of the namespace "std", so update + // our cache of the "std" namespace to point at this definition. + if (NamespaceDecl *StdNS = getStdNamespace()) { + // We had already defined a dummy namespace "std". Link this new + // namespace definition to the dummy namespace "std". + StdNS->setNextNamespace(Namespc); + StdNS->setLocation(IdentLoc); + Namespc->setOriginalNamespace(StdNS->getOriginalNamespace()); + } + + // Make our StdNamespace cache point at the first real definition of the + // "std" namespace. + StdNamespace = Namespc; + } + + PushOnScopeChains(Namespc, DeclRegionScope); + } else { + // Anonymous namespaces. + assert(Namespc->isAnonymousNamespace()); + + // Link the anonymous namespace into its parent. + NamespaceDecl *PrevDecl; + DeclContext *Parent = CurContext->getRedeclContext(); + if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { + PrevDecl = TU->getAnonymousNamespace(); + TU->setAnonymousNamespace(Namespc); + } else { + NamespaceDecl *ND = cast<NamespaceDecl>(Parent); + PrevDecl = ND->getAnonymousNamespace(); + ND->setAnonymousNamespace(Namespc); + } + + // Link the anonymous namespace with its previous declaration. + if (PrevDecl) { + assert(PrevDecl->isAnonymousNamespace()); + assert(!PrevDecl->getNextNamespace()); + Namespc->setOriginalNamespace(PrevDecl->getOriginalNamespace()); + PrevDecl->setNextNamespace(Namespc); + + if (Namespc->isInline() != PrevDecl->isInline()) { + // inline-ness must match + Diag(Namespc->getLocation(), diag::err_inline_namespace_mismatch) + << Namespc->isInline(); + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + Namespc->setInvalidDecl(); + // Recover by ignoring the new namespace's inline status. + Namespc->setInline(PrevDecl->isInline()); + } + } + + CurContext->addDecl(Namespc); + + // C++ [namespace.unnamed]p1. An unnamed-namespace-definition + // behaves as if it were replaced by + // namespace unique { /* empty body */ } + // using namespace unique; + // namespace unique { namespace-body } + // where all occurrences of 'unique' in a translation unit are + // replaced by the same identifier and this identifier differs + // from all other identifiers in the entire program. + + // We just create the namespace with an empty name and then add an + // implicit using declaration, just like the standard suggests. + // + // CodeGen enforces the "universally unique" aspect by giving all + // declarations semantically contained within an anonymous + // namespace internal linkage. + + if (!PrevDecl) { + UsingDirectiveDecl* UD + = UsingDirectiveDecl::Create(Context, CurContext, + /* 'using' */ LBrace, + /* 'namespace' */ SourceLocation(), + /* qualifier */ NestedNameSpecifierLoc(), + /* identifier */ SourceLocation(), + Namespc, + /* Ancestor */ CurContext); + UD->setImplicit(); + CurContext->addDecl(UD); + } + } + + // Although we could have an invalid decl (i.e. the namespace name is a + // redefinition), push it as current DeclContext and try to continue parsing. + // FIXME: We should be able to push Namespc here, so that the each DeclContext + // for the namespace has the declarations that showed up in that particular + // namespace definition. + PushDeclContext(NamespcScope, Namespc); + return Namespc; +} + +/// getNamespaceDecl - Returns the namespace a decl represents. If the decl +/// is a namespace alias, returns the namespace it points to. +static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { + if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D)) + return AD->getNamespace(); + return dyn_cast_or_null<NamespaceDecl>(D); +} + +/// ActOnFinishNamespaceDef - This callback is called after a namespace is +/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. +void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { + NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl); + assert(Namespc && "Invalid parameter, expected NamespaceDecl"); + Namespc->setRBraceLoc(RBrace); + PopDeclContext(); + if (Namespc->hasAttr<VisibilityAttr>()) + PopPragmaVisibility(); +} + +CXXRecordDecl *Sema::getStdBadAlloc() const { + return cast_or_null<CXXRecordDecl>( + StdBadAlloc.get(Context.getExternalSource())); +} + +NamespaceDecl *Sema::getStdNamespace() const { + return cast_or_null<NamespaceDecl>( + StdNamespace.get(Context.getExternalSource())); +} + +/// \brief Retrieve the special "std" namespace, which may require us to +/// implicitly define the namespace. +NamespaceDecl *Sema::getOrCreateStdNamespace() { + if (!StdNamespace) { + // The "std" namespace has not yet been defined, so build one implicitly. + StdNamespace = NamespaceDecl::Create(Context, + Context.getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &PP.getIdentifierTable().get("std")); + getStdNamespace()->setImplicit(true); + } + + return getStdNamespace(); +} + +/// \brief Determine whether a using statement is in a context where it will be +/// apply in all contexts. +static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { + switch (CurContext->getDeclKind()) { + case Decl::TranslationUnit: + return true; + case Decl::LinkageSpec: + return IsUsingDirectiveInToplevelContext(CurContext->getParent()); + default: + return false; + } +} + +Decl *Sema::ActOnUsingDirective(Scope *S, + SourceLocation UsingLoc, + SourceLocation NamespcLoc, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + AttributeList *AttrList) { + assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); + assert(NamespcName && "Invalid NamespcName."); + assert(IdentLoc.isValid() && "Invalid NamespceName location."); + + // This can only happen along a recovery path. + while (S->getFlags() & Scope::TemplateParamScope) + S = S->getParent(); + assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + + UsingDirectiveDecl *UDir = 0; + NestedNameSpecifier *Qualifier = 0; + if (SS.isSet()) + Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + + // Lookup namespace name. + LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); + if (R.isAmbiguous()) + return 0; + + if (R.empty()) { + // Allow "using namespace std;" or "using namespace ::std;" even if + // "std" hasn't been defined yet, for GCC compatibility. + if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && + NamespcName->isStr("std")) { + Diag(IdentLoc, diag::ext_using_undefined_std); + R.addDecl(getOrCreateStdNamespace()); + R.resolveKind(); + } + // Otherwise, attempt typo correction. + else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, + CTC_NoKeywords, 0)) { + if (R.getAsSingle<NamespaceDecl>() || + R.getAsSingle<NamespaceAliasDecl>()) { + if (DeclContext *DC = computeDeclContext(SS, false)) + Diag(IdentLoc, diag::err_using_directive_member_suggest) + << NamespcName << DC << Corrected << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + else + Diag(IdentLoc, diag::err_using_directive_suggest) + << NamespcName << Corrected + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here) + << Corrected; + + NamespcName = Corrected.getAsIdentifierInfo(); + } else { + R.clear(); + R.setLookupName(NamespcName); + } + } + } + + if (!R.empty()) { + NamedDecl *Named = R.getFoundDecl(); + assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named)) + && "expected namespace decl"); + // C++ [namespace.udir]p1: + // A using-directive specifies that the names in the nominated + // namespace can be used in the scope in which the + // using-directive appears after the using-directive. During + // unqualified name lookup (3.4.1), the names appear as if they + // were declared in the nearest enclosing namespace which + // contains both the using-directive and the nominated + // namespace. [Note: in this context, "contains" means "contains + // directly or indirectly". ] + + // Find enclosing context containing both using-directive and + // nominated namespace. + NamespaceDecl *NS = getNamespaceDecl(Named); + DeclContext *CommonAncestor = cast<DeclContext>(NS); + while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) + CommonAncestor = CommonAncestor->getParent(); + + UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, + SS.getWithLocInContext(Context), + IdentLoc, Named, CommonAncestor); + + if (IsUsingDirectiveInToplevelContext(CurContext) && + !SourceMgr.isFromMainFile(SourceMgr.getInstantiationLoc(IdentLoc))) { + Diag(IdentLoc, diag::warn_using_directive_in_header); + } + + PushUsingDirective(S, UDir); + } else { + Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); + } + + // FIXME: We ignore attributes for now. + return UDir; +} + +void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { + // If scope has associated entity, then using directive is at namespace + // or translation unit scope. We add UsingDirectiveDecls, into + // it's lookup structure. + if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) + Ctx->addDecl(UDir); + else + // Otherwise it is block-sope. using-directives will affect lookup + // only to the end of scope. + S->PushUsingDirective(UDir); +} + + +Decl *Sema::ActOnUsingDeclaration(Scope *S, + AccessSpecifier AS, + bool HasUsingKeyword, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + AttributeList *AttrList, + bool IsTypeName, + SourceLocation TypenameLoc) { + assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedId::IK_ConversionFunctionId: + break; + + case UnqualifiedId::IK_ConstructorName: + case UnqualifiedId::IK_ConstructorTemplateId: + // C++0x inherited constructors. + if (getLangOptions().CPlusPlus0x) break; + + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_constructor) + << SS.getRange(); + return 0; + + case UnqualifiedId::IK_DestructorName: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_destructor) + << SS.getRange(); + return 0; + + case UnqualifiedId::IK_TemplateId: + Diag(Name.getSourceRange().getBegin(), diag::err_using_decl_template_id) + << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); + return 0; + } + + DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); + DeclarationName TargetName = TargetNameInfo.getName(); + if (!TargetName) + return 0; + + // Warn about using declarations. + // TODO: store that the declaration was written without 'using' and + // talk about access decls instead of using decls in the + // diagnostics. + if (!HasUsingKeyword) { + UsingLoc = Name.getSourceRange().getBegin(); + + Diag(UsingLoc, diag::warn_access_decl_deprecated) + << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); + } + + if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || + DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) + return 0; + + NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, + TargetNameInfo, AttrList, + /* IsInstantiation */ false, + IsTypeName, TypenameLoc); + if (UD) + PushOnScopeChains(UD, S, /*AddToContext*/ false); + + return UD; +} + +/// \brief Determine whether a using declaration considers the given +/// declarations as "equivalent", e.g., if they are redeclarations of +/// the same entity or are both typedefs of the same type. +static bool +IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, + bool &SuppressRedeclaration) { + if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) { + SuppressRedeclaration = false; + return true; + } + + if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1)) + if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) { + SuppressRedeclaration = true; + return Context.hasSameType(TD1->getUnderlyingType(), + TD2->getUnderlyingType()); + } + + return false; +} + + +/// Determines whether to create a using shadow decl for a particular +/// decl, given the set of decls existing prior to this using lookup. +bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, + const LookupResult &Previous) { + // Diagnose finding a decl which is not from a base class of the + // current class. We do this now because there are cases where this + // function will silently decide not to build a shadow decl, which + // will pre-empt further diagnostics. + // + // We don't need to do this in C++0x because we do the check once on + // the qualifier. + // + // FIXME: diagnose the following if we care enough: + // struct A { int foo; }; + // struct B : A { using A::foo; }; + // template <class T> struct C : A {}; + // template <class T> struct D : C<T> { using B::foo; } // <--- + // This is invalid (during instantiation) in C++03 because B::foo + // resolves to the using decl in B, which is not a base class of D<T>. + // We can't diagnose it immediately because C<T> is an unknown + // specialization. The UsingShadowDecl in D<T> then points directly + // to A::foo, which will look well-formed when we instantiate. + // The right solution is to not collapse the shadow-decl chain. + if (!getLangOptions().CPlusPlus0x && CurContext->isRecord()) { + DeclContext *OrigDC = Orig->getDeclContext(); + + // Handle enums and anonymous structs. + if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent(); + CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC); + while (OrigRec->isAnonymousStructOrUnion()) + OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext()); + + if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) { + if (OrigDC == CurContext) { + Diag(Using->getLocation(), + diag::err_using_decl_nested_name_specifier_is_current_class) + << Using->getQualifierLoc().getSourceRange(); + Diag(Orig->getLocation(), diag::note_using_decl_target); + return true; + } + + Diag(Using->getQualifierLoc().getBeginLoc(), + diag::err_using_decl_nested_name_specifier_is_not_base_class) + << Using->getQualifier() + << cast<CXXRecordDecl>(CurContext) + << Using->getQualifierLoc().getSourceRange(); + Diag(Orig->getLocation(), diag::note_using_decl_target); + return true; + } + } + + if (Previous.empty()) return false; + + NamedDecl *Target = Orig; + if (isa<UsingShadowDecl>(Target)) + Target = cast<UsingShadowDecl>(Target)->getTargetDecl(); + + // If the target happens to be one of the previous declarations, we + // don't have a conflict. + // + // FIXME: but we might be increasing its access, in which case we + // should redeclare it. + NamedDecl *NonTag = 0, *Tag = 0; + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + bool Result; + if (IsEquivalentForUsingDecl(Context, D, Target, Result)) + return Result; + + (isa<TagDecl>(D) ? Tag : NonTag) = D; + } + + if (Target->isFunctionOrFunctionTemplate()) { + FunctionDecl *FD; + if (isa<FunctionTemplateDecl>(Target)) + FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(Target); + + NamedDecl *OldDecl = 0; + switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) { + case Ovl_Overload: + return false; + + case Ovl_NonFunction: + Diag(Using->getLocation(), diag::err_using_decl_conflict); + break; + + // We found a decl with the exact signature. + case Ovl_Match: + // If we're in a record, we want to hide the target, so we + // return true (without a diagnostic) to tell the caller not to + // build a shadow decl. + if (CurContext->isRecord()) + return true; + + // If we're not in a record, this is an error. + Diag(Using->getLocation(), diag::err_using_decl_conflict); + break; + } + + Diag(Target->getLocation(), diag::note_using_decl_target); + Diag(OldDecl->getLocation(), diag::note_using_decl_conflict); + return true; + } + + // Target is not a function. + + if (isa<TagDecl>(Target)) { + // No conflict between a tag and a non-tag. + if (!Tag) return false; + + Diag(Using->getLocation(), diag::err_using_decl_conflict); + Diag(Target->getLocation(), diag::note_using_decl_target); + Diag(Tag->getLocation(), diag::note_using_decl_conflict); + return true; + } + + // No conflict between a tag and a non-tag. + if (!NonTag) return false; + + Diag(Using->getLocation(), diag::err_using_decl_conflict); + Diag(Target->getLocation(), diag::note_using_decl_target); + Diag(NonTag->getLocation(), diag::note_using_decl_conflict); + return true; +} + +/// Builds a shadow declaration corresponding to a 'using' declaration. +UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, + UsingDecl *UD, + NamedDecl *Orig) { + + // If we resolved to another shadow declaration, just coalesce them. + NamedDecl *Target = Orig; + if (isa<UsingShadowDecl>(Target)) { + Target = cast<UsingShadowDecl>(Target)->getTargetDecl(); + assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration"); + } + + UsingShadowDecl *Shadow + = UsingShadowDecl::Create(Context, CurContext, + UD->getLocation(), UD, Target); + UD->addShadowDecl(Shadow); + + Shadow->setAccess(UD->getAccess()); + if (Orig->isInvalidDecl() || UD->isInvalidDecl()) + Shadow->setInvalidDecl(); + + if (S) + PushOnScopeChains(Shadow, S); + else + CurContext->addDecl(Shadow); + + + return Shadow; +} + +/// Hides a using shadow declaration. This is required by the current +/// using-decl implementation when a resolvable using declaration in a +/// class is followed by a declaration which would hide or override +/// one or more of the using decl's targets; for example: +/// +/// struct Base { void foo(int); }; +/// struct Derived : Base { +/// using Base::foo; +/// void foo(int); +/// }; +/// +/// The governing language is C++03 [namespace.udecl]p12: +/// +/// When a using-declaration brings names from a base class into a +/// derived class scope, member functions in the derived class +/// override and/or hide member functions with the same name and +/// parameter types in a base class (rather than conflicting). +/// +/// There are two ways to implement this: +/// (1) optimistically create shadow decls when they're not hidden +/// by existing declarations, or +/// (2) don't create any shadow decls (or at least don't make them +/// visible) until we've fully parsed/instantiated the class. +/// The problem with (1) is that we might have to retroactively remove +/// a shadow decl, which requires several O(n) operations because the +/// decl structures are (very reasonably) not designed for removal. +/// (2) avoids this but is very fiddly and phase-dependent. +void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { + if (Shadow->getDeclName().getNameKind() == + DeclarationName::CXXConversionFunctionName) + cast<CXXRecordDecl>(Shadow->getDeclContext())->removeConversion(Shadow); + + // Remove it from the DeclContext... + Shadow->getDeclContext()->removeDecl(Shadow); + + // ...and the scope, if applicable... + if (S) { + S->RemoveDecl(Shadow); + IdResolver.RemoveDecl(Shadow); + } + + // ...and the using decl. + Shadow->getUsingDecl()->removeShadowDecl(Shadow); + + // TODO: complain somehow if Shadow was used. It shouldn't + // be possible for this to happen, because...? +} + +/// Builds a using declaration. +/// +/// \param IsInstantiation - Whether this call arises from an +/// instantiation of an unresolved using declaration. We treat +/// the lookup differently for these declarations. +NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, + CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + AttributeList *AttrList, + bool IsInstantiation, + bool IsTypeName, + SourceLocation TypenameLoc) { + assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); + SourceLocation IdentLoc = NameInfo.getLoc(); + assert(IdentLoc.isValid() && "Invalid TargetName location."); + + // FIXME: We ignore attributes for now. + + if (SS.isEmpty()) { + Diag(IdentLoc, diag::err_using_requires_qualname); + return 0; + } + + // Do the redeclaration lookup in the current scope. + LookupResult Previous(*this, NameInfo, LookupUsingDeclName, + ForRedeclaration); + Previous.setHideTags(false); + if (S) { + LookupName(Previous, S); + + // It is really dumb that we have to do this. + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (!isDeclInScope(D, CurContext, S)) + F.erase(); + } + F.done(); + } else { + assert(IsInstantiation && "no scope in non-instantiation"); + assert(CurContext->isRecord() && "scope not record in instantiation"); + LookupQualifiedName(Previous, CurContext); + } + + // Check for invalid redeclarations. + if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous)) + return 0; + + // Check for bad qualifiers. + if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc)) + return 0; + + DeclContext *LookupContext = computeDeclContext(SS); + NamedDecl *D; + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + if (!LookupContext) { + if (IsTypeName) { + // FIXME: not all declaration name kinds are legal here + D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, + UsingLoc, TypenameLoc, + QualifierLoc, + IdentLoc, NameInfo.getName()); + } else { + D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, + QualifierLoc, NameInfo); + } + } else { + D = UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, + NameInfo, IsTypeName); + } + D->setAccess(AS); + CurContext->addDecl(D); + + if (!LookupContext) return D; + UsingDecl *UD = cast<UsingDecl>(D); + + if (RequireCompleteDeclContext(SS, LookupContext)) { + UD->setInvalidDecl(); + return UD; + } + + // Constructor inheriting using decls get special treatment. + if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { + if (CheckInheritedConstructorUsingDecl(UD)) + UD->setInvalidDecl(); + return UD; + } + + // Otherwise, look up the target name. + + LookupResult R(*this, NameInfo, LookupOrdinaryName); + R.setUsingDeclaration(true); + + // Unlike most lookups, we don't always want to hide tag + // declarations: tag names are visible through the using declaration + // even if hidden by ordinary names, *except* in a dependent context + // where it's important for the sanity of two-phase lookup. + if (!IsInstantiation) + R.setHideTags(false); + + LookupQualifiedName(R, LookupContext); + + if (R.empty()) { + Diag(IdentLoc, diag::err_no_member) + << NameInfo.getName() << LookupContext << SS.getRange(); + UD->setInvalidDecl(); + return UD; + } + + if (R.isAmbiguous()) { + UD->setInvalidDecl(); + return UD; + } + + if (IsTypeName) { + // If we asked for a typename and got a non-type decl, error out. + if (!R.getAsSingle<TypeDecl>()) { + Diag(IdentLoc, diag::err_using_typename_non_type); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getUnderlyingDecl()->getLocation(), + diag::note_using_decl_target); + UD->setInvalidDecl(); + return UD; + } + } else { + // If we asked for a non-typename and we got a type, error out, + // but only if this is an instantiation of an unresolved using + // decl. Otherwise just silently find the type name. + if (IsInstantiation && R.getAsSingle<TypeDecl>()) { + Diag(IdentLoc, diag::err_using_dependent_value_is_type); + Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target); + UD->setInvalidDecl(); + return UD; + } + } + + // C++0x N2914 [namespace.udecl]p6: + // A using-declaration shall not name a namespace. + if (R.getAsSingle<NamespaceDecl>()) { + Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) + << SS.getRange(); + UD->setInvalidDecl(); + return UD; + } + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + if (!CheckUsingShadowDecl(UD, *I, Previous)) + BuildUsingShadowDecl(S, UD, *I); + } + + return UD; +} + +/// Additional checks for a using declaration referring to a constructor name. +bool Sema::CheckInheritedConstructorUsingDecl(UsingDecl *UD) { + if (UD->isTypeName()) { + // FIXME: Cannot specify typename when specifying constructor + return true; + } + + const Type *SourceType = UD->getQualifier()->getAsType(); + assert(SourceType && + "Using decl naming constructor doesn't have type in scope spec."); + CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext); + + // Check whether the named type is a direct base class. + CanQualType CanonicalSourceType = SourceType->getCanonicalTypeUnqualified(); + CXXRecordDecl::base_class_iterator BaseIt, BaseE; + for (BaseIt = TargetClass->bases_begin(), BaseE = TargetClass->bases_end(); + BaseIt != BaseE; ++BaseIt) { + CanQualType BaseType = BaseIt->getType()->getCanonicalTypeUnqualified(); + if (CanonicalSourceType == BaseType) + break; + } + + if (BaseIt == BaseE) { + // Did not find SourceType in the bases. + Diag(UD->getUsingLocation(), + diag::err_using_decl_constructor_not_in_direct_base) + << UD->getNameInfo().getSourceRange() + << QualType(SourceType, 0) << TargetClass; + return true; + } + + BaseIt->setInheritConstructors(); + + return false; +} + +/// Checks that the given using declaration is not an invalid +/// redeclaration. Note that this is checking only for the using decl +/// itself, not for any ill-formedness among the UsingShadowDecls. +bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, + bool isTypeName, + const CXXScopeSpec &SS, + SourceLocation NameLoc, + const LookupResult &Prev) { + // C++03 [namespace.udecl]p8: + // C++0x [namespace.udecl]p10: + // A using-declaration is a declaration and can therefore be used + // repeatedly where (and only where) multiple declarations are + // allowed. + // + // That's in non-member contexts. + if (!CurContext->getRedeclContext()->isRecord()) + return false; + + NestedNameSpecifier *Qual + = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + + for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { + NamedDecl *D = *I; + + bool DTypename; + NestedNameSpecifier *DQual; + if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { + DTypename = UD->isTypeName(); + DQual = UD->getQualifier(); + } else if (UnresolvedUsingValueDecl *UD + = dyn_cast<UnresolvedUsingValueDecl>(D)) { + DTypename = false; + DQual = UD->getQualifier(); + } else if (UnresolvedUsingTypenameDecl *UD + = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { + DTypename = true; + DQual = UD->getQualifier(); + } else continue; + + // using decls differ if one says 'typename' and the other doesn't. + // FIXME: non-dependent using decls? + if (isTypeName != DTypename) continue; + + // using decls differ if they name different scopes (but note that + // template instantiation can cause this check to trigger when it + // didn't before instantiation). + if (Context.getCanonicalNestedNameSpecifier(Qual) != + Context.getCanonicalNestedNameSpecifier(DQual)) + continue; + + Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange(); + Diag(D->getLocation(), diag::note_using_decl) << 1; + return true; + } + + return false; +} + + +/// Checks that the given nested-name qualifier used in a using decl +/// in the current context is appropriately related to the current +/// scope. If an error is found, diagnoses it and returns true. +bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, + const CXXScopeSpec &SS, + SourceLocation NameLoc) { + DeclContext *NamedContext = computeDeclContext(SS); + + if (!CurContext->isRecord()) { + // C++03 [namespace.udecl]p3: + // C++0x [namespace.udecl]p8: + // A using-declaration for a class member shall be a member-declaration. + + // If we weren't able to compute a valid scope, it must be a + // dependent class scope. + if (!NamedContext || NamedContext->isRecord()) { + Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member) + << SS.getRange(); + return true; + } + + // Otherwise, everything is known to be fine. + return false; + } + + // The current scope is a record. + + // If the named context is dependent, we can't decide much. + if (!NamedContext) { + // FIXME: in C++0x, we can diagnose if we can prove that the + // nested-name-specifier does not refer to a base class, which is + // still possible in some cases. + + // Otherwise we have to conservatively report that things might be + // okay. + return false; + } + + if (!NamedContext->isRecord()) { + // Ideally this would point at the last name in the specifier, + // but we don't have that level of source info. + Diag(SS.getRange().getBegin(), + diag::err_using_decl_nested_name_specifier_is_not_class) + << (NestedNameSpecifier*) SS.getScopeRep() << SS.getRange(); + return true; + } + + if (!NamedContext->isDependentContext() && + RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext)) + return true; + + if (getLangOptions().CPlusPlus0x) { + // C++0x [namespace.udecl]p3: + // In a using-declaration used as a member-declaration, the + // nested-name-specifier shall name a base class of the class + // being defined. + + if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom( + cast<CXXRecordDecl>(NamedContext))) { + if (CurContext == NamedContext) { + Diag(NameLoc, + diag::err_using_decl_nested_name_specifier_is_current_class) + << SS.getRange(); + return true; + } + + Diag(SS.getRange().getBegin(), + diag::err_using_decl_nested_name_specifier_is_not_base_class) + << (NestedNameSpecifier*) SS.getScopeRep() + << cast<CXXRecordDecl>(CurContext) + << SS.getRange(); + return true; + } + + return false; + } + + // C++03 [namespace.udecl]p4: + // A using-declaration used as a member-declaration shall refer + // to a member of a base class of the class being defined [etc.]. + + // Salient point: SS doesn't have to name a base class as long as + // lookup only finds members from base classes. Therefore we can + // diagnose here only if we can prove that that can't happen, + // i.e. if the class hierarchies provably don't intersect. + + // TODO: it would be nice if "definitely valid" results were cached + // in the UsingDecl and UsingShadowDecl so that these checks didn't + // need to be repeated. + + struct UserData { + llvm::DenseSet<const CXXRecordDecl*> Bases; + + static bool collect(const CXXRecordDecl *Base, void *OpaqueData) { + UserData *Data = reinterpret_cast<UserData*>(OpaqueData); + Data->Bases.insert(Base); + return true; + } + + bool hasDependentBases(const CXXRecordDecl *Class) { + return !Class->forallBases(collect, this); + } + + /// Returns true if the base is dependent or is one of the + /// accumulated base classes. + static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) { + UserData *Data = reinterpret_cast<UserData*>(OpaqueData); + return !Data->Bases.count(Base); + } + + bool mightShareBases(const CXXRecordDecl *Class) { + return Bases.count(Class) || !Class->forallBases(doesNotContain, this); + } + }; + + UserData Data; + + // Returns false if we find a dependent base. + if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext))) + return false; + + // Returns false if the class has a dependent base or if it or one + // of its bases is present in the base set of the current context. + if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext))) + return false; + + Diag(SS.getRange().getBegin(), + diag::err_using_decl_nested_name_specifier_is_not_base_class) + << (NestedNameSpecifier*) SS.getScopeRep() + << cast<CXXRecordDecl>(CurContext) + << SS.getRange(); + + return true; +} + +Decl *Sema::ActOnAliasDeclaration(Scope *S, + AccessSpecifier AS, + MultiTemplateParamsArg TemplateParamLists, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type) { + // Skip up to the relevant declaration scope. + while (S->getFlags() & Scope::TemplateParamScope) + S = S->getParent(); + assert((S->getFlags() & Scope::DeclScope) && + "got alias-declaration outside of declaration scope"); + + if (Type.isInvalid()) + return 0; + + bool Invalid = false; + DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); + TypeSourceInfo *TInfo = 0; + GetTypeFromParser(Type.get(), &TInfo); + + if (DiagnoseClassNameShadow(CurContext, NameInfo)) + return 0; + + if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo, + UPPC_DeclarationType)) { + Invalid = true; + TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, + TInfo->getTypeLoc().getBeginLoc()); + } + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + LookupName(Previous, S); + + // Warn about shadowing the name of a template parameter. + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + if (DiagnoseTemplateParameterShadow(Name.StartLocation, + Previous.getFoundDecl())) + Invalid = true; + Previous.clear(); + } + + assert(Name.Kind == UnqualifiedId::IK_Identifier && + "name in alias declaration must be an identifier"); + TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc, + Name.StartLocation, + Name.Identifier, TInfo); + + NewTD->setAccess(AS); + + if (Invalid) + NewTD->setInvalidDecl(); + + CheckTypedefForVariablyModifiedType(S, NewTD); + Invalid |= NewTD->isInvalidDecl(); + + bool Redeclaration = false; + + NamedDecl *NewND; + if (TemplateParamLists.size()) { + TypeAliasTemplateDecl *OldDecl = 0; + TemplateParameterList *OldTemplateParams = 0; + + if (TemplateParamLists.size() != 1) { + Diag(UsingLoc, diag::err_alias_template_extra_headers) + << SourceRange(TemplateParamLists.get()[1]->getTemplateLoc(), + TemplateParamLists.get()[TemplateParamLists.size()-1]->getRAngleLoc()); + } + TemplateParameterList *TemplateParams = TemplateParamLists.get()[0]; + + // Only consider previous declarations in the same scope. + FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false, + /*ExplicitInstantiationOrSpecialization*/false); + if (!Previous.empty()) { + Redeclaration = true; + + OldDecl = Previous.getAsSingle<TypeAliasTemplateDecl>(); + if (!OldDecl && !Invalid) { + Diag(UsingLoc, diag::err_redefinition_different_kind) + << Name.Identifier; + + NamedDecl *OldD = Previous.getRepresentativeDecl(); + if (OldD->getLocation().isValid()) + Diag(OldD->getLocation(), diag::note_previous_definition); + + Invalid = true; + } + + if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) { + if (TemplateParameterListsAreEqual(TemplateParams, + OldDecl->getTemplateParameters(), + /*Complain=*/true, + TPL_TemplateMatch)) + OldTemplateParams = OldDecl->getTemplateParameters(); + else + Invalid = true; + + TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl(); + if (!Invalid && + !Context.hasSameType(OldTD->getUnderlyingType(), + NewTD->getUnderlyingType())) { + // FIXME: The C++0x standard does not clearly say this is ill-formed, + // but we can't reasonably accept it. + Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef) + << 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType(); + if (OldTD->getLocation().isValid()) + Diag(OldTD->getLocation(), diag::note_previous_definition); + Invalid = true; + } + } + } + + // Merge any previous default template arguments into our parameters, + // and check the parameter list. + if (CheckTemplateParameterList(TemplateParams, OldTemplateParams, + TPC_TypeAliasTemplate)) + return 0; + + TypeAliasTemplateDecl *NewDecl = + TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc, + Name.Identifier, TemplateParams, + NewTD); + + NewDecl->setAccess(AS); + + if (Invalid) + NewDecl->setInvalidDecl(); + else if (OldDecl) + NewDecl->setPreviousDeclaration(OldDecl); + + NewND = NewDecl; + } else { + ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); + NewND = NewTD; + } + + if (!Redeclaration) + PushOnScopeChains(NewND, S); + + return NewND; +} + +Decl *Sema::ActOnNamespaceAliasDef(Scope *S, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, + IdentifierInfo *Alias, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *Ident) { + + // Lookup the namespace name. + LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName); + LookupParsedName(R, S, &SS); + + // Check if we have a previous declaration with the same name. + NamedDecl *PrevDecl + = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) + PrevDecl = 0; + + if (PrevDecl) { + if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) { + // We already have an alias with the same name that points to the same + // namespace, so don't create a new one. + // FIXME: At some point, we'll want to create the (redundant) + // declaration to maintain better source information. + if (!R.isAmbiguous() && !R.empty() && + AD->getNamespace()->Equals(getNamespaceDecl(R.getFoundDecl()))) + return 0; + } + + unsigned DiagID = isa<NamespaceDecl>(PrevDecl) ? diag::err_redefinition : + diag::err_redefinition_different_kind; + Diag(AliasLoc, DiagID) << Alias; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + return 0; + } + + if (R.isAmbiguous()) + return 0; + + if (R.empty()) { + if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, + CTC_NoKeywords, 0)) { + if (R.getAsSingle<NamespaceDecl>() || + R.getAsSingle<NamespaceAliasDecl>()) { + if (DeclContext *DC = computeDeclContext(SS, false)) + Diag(IdentLoc, diag::err_using_directive_member_suggest) + << Ident << DC << Corrected << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + else + Diag(IdentLoc, diag::err_using_directive_suggest) + << Ident << Corrected + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + + Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here) + << Corrected; + + Ident = Corrected.getAsIdentifierInfo(); + } else { + R.clear(); + R.setLookupName(Ident); + } + } + + if (R.empty()) { + Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); + return 0; + } + } + + NamespaceAliasDecl *AliasDecl = + NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, + Alias, SS.getWithLocInContext(Context), + IdentLoc, R.getFoundDecl()); + + PushOnScopeChains(AliasDecl, S); + return AliasDecl; +} + +namespace { + /// \brief Scoped object used to handle the state changes required in Sema + /// to implicitly define the body of a C++ member function; + class ImplicitlyDefinedFunctionScope { + Sema &S; + Sema::ContextRAII SavedContext; + + public: + ImplicitlyDefinedFunctionScope(Sema &S, CXXMethodDecl *Method) + : S(S), SavedContext(S, Method) + { + S.PushFunctionScope(); + S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + } + + ~ImplicitlyDefinedFunctionScope() { + S.PopExpressionEvaluationContext(); + S.PopFunctionOrBlockScope(); + } + }; +} + +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) { + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(Context); + + // Direct base-class constructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) { + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + if (Constructor) + ExceptSpec.CalledDecl(Constructor); + } + } + + // Virtual base-class constructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) { + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + if (Constructor) + ExceptSpec.CalledDecl(Constructor); + } + } + + // Field constructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (F->hasInClassInitializer()) { + if (Expr *E = F->getInClassInitializer()) + ExceptSpec.CalledExpr(E); + else if (!F->isInvalidDecl()) + ExceptSpec.SetDelayed(); + } else if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { + CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); + CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl); + // If this is a deleted function, add it anyway. This might be conformant + // with the standard. This might not. I'm not sure. It might not matter. + // In particular, the problem is that this function never gets called. It + // might just be ill-formed because this function attempts to refer to + // a deleted function here. + if (Constructor) + ExceptSpec.CalledDecl(Constructor); + } + } + + return ExceptSpec; +} + +CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( + CXXRecordDecl *ClassDecl) { + // C++ [class.ctor]p5: + // A default constructor for a class X is a constructor of class X + // that can be called without an argument. If there is no + // user-declared constructor for class X, a default constructor is + // implicitly declared. An implicitly-declared default constructor + // is an inline public member of its class. + assert(!ClassDecl->hasUserDeclaredConstructor() && + "Should not build implicit default constructor!"); + + ImplicitExceptionSpecification Spec = + ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + + // Create the actual constructor declaration. + CanQualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName(ClassType); + DeclarationNameInfo NameInfo(Name, ClassLoc); + CXXConstructorDecl *DefaultCon + = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, + 0, 0, EPI), + /*TInfo=*/0, + /*isExplicit=*/false, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); + DefaultCon->setAccess(AS_public); + DefaultCon->setDefaulted(); + DefaultCon->setImplicit(); + DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); + + // Note that we have declared this constructor. + ++ASTContext::NumImplicitDefaultConstructorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(DefaultCon, S, false); + ClassDecl->addDecl(DefaultCon); + + if (ShouldDeleteDefaultConstructor(DefaultCon)) + DefaultCon->setDeletedAsWritten(); + + return DefaultCon; +} + +void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor) { + assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() && + !Constructor->doesThisDeclarationHaveABody() && + !Constructor->isDeleted()) && + "DefineImplicitDefaultConstructor - call it for implicit default ctor"); + + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); + + ImplicitlyDefinedFunctionScope Scope(*this, Constructor); + DiagnosticErrorTrap Trap(Diags); + if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl); + Constructor->setInvalidDecl(); + return; + } + + SourceLocation Loc = Constructor->getLocation(); + Constructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc)); + + Constructor->setUsed(); + MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Constructor); + } +} + +/// Get any existing defaulted default constructor for the given class. Do not +/// implicitly define one if it does not exist. +static CXXConstructorDecl *getDefaultedDefaultConstructorUnsafe(Sema &Self, + CXXRecordDecl *D) { + ASTContext &Context = Self.Context; + QualType ClassType = Context.getTypeDeclType(D); + DeclarationName ConstructorName + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(ClassType.getUnqualifiedType())); + + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = D->lookup(ConstructorName); + Con != ConEnd; ++Con) { + // A function template cannot be defaulted. + if (isa<FunctionTemplateDecl>(*Con)) + continue; + + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + if (Constructor->isDefaultConstructor()) + return Constructor->isDefaulted() ? Constructor : 0; + } + return 0; +} + +void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { + if (!D) return; + AdjustDeclIfTemplate(D); + + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D); + CXXConstructorDecl *CtorDecl + = getDefaultedDefaultConstructorUnsafe(*this, ClassDecl); + + if (!CtorDecl) return; + + // Compute the exception specification for the default constructor. + const FunctionProtoType *CtorTy = + CtorDecl->getType()->castAs<FunctionProtoType>(); + if (CtorTy->getExceptionSpecType() == EST_Delayed) { + ImplicitExceptionSpecification Spec = + ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + assert(EPI.ExceptionSpecType != EST_Delayed); + + CtorDecl->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + } + + // If the default constructor is explicitly defaulted, checking the exception + // specification is deferred until now. + if (!CtorDecl->isInvalidDecl() && CtorDecl->isExplicitlyDefaulted() && + !ClassDecl->isDependentType()) + CheckExplicitlyDefaultedDefaultConstructor(CtorDecl); +} + +void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { + // We start with an initial pass over the base classes to collect those that + // inherit constructors from. If there are none, we can forgo all further + // processing. + typedef llvm::SmallVector<const RecordType *, 4> BasesVector; + BasesVector BasesToInheritFrom; + for (CXXRecordDecl::base_class_iterator BaseIt = ClassDecl->bases_begin(), + BaseE = ClassDecl->bases_end(); + BaseIt != BaseE; ++BaseIt) { + if (BaseIt->getInheritConstructors()) { + QualType Base = BaseIt->getType(); + if (Base->isDependentType()) { + // If we inherit constructors from anything that is dependent, just + // abort processing altogether. We'll get another chance for the + // instantiations. + return; + } + BasesToInheritFrom.push_back(Base->castAs<RecordType>()); + } + } + if (BasesToInheritFrom.empty()) + return; + + // Now collect the constructors that we already have in the current class. + // Those take precedence over inherited constructors. + // C++0x [class.inhctor]p3: [...] a constructor is implicitly declared [...] + // unless there is a user-declared constructor with the same signature in + // the class where the using-declaration appears. + llvm::SmallSet<const Type *, 8> ExistingConstructors; + for (CXXRecordDecl::ctor_iterator CtorIt = ClassDecl->ctor_begin(), + CtorE = ClassDecl->ctor_end(); + CtorIt != CtorE; ++CtorIt) { + ExistingConstructors.insert( + Context.getCanonicalType(CtorIt->getType()).getTypePtr()); + } + + Scope *S = getScopeForContext(ClassDecl); + DeclarationName CreatedCtorName = + Context.DeclarationNames.getCXXConstructorName( + ClassDecl->getTypeForDecl()->getCanonicalTypeUnqualified()); + + // Now comes the true work. + // First, we keep a map from constructor types to the base that introduced + // them. Needed for finding conflicting constructors. We also keep the + // actually inserted declarations in there, for pretty diagnostics. + typedef std::pair<CanQualType, CXXConstructorDecl *> ConstructorInfo; + typedef llvm::DenseMap<const Type *, ConstructorInfo> ConstructorToSourceMap; + ConstructorToSourceMap InheritedConstructors; + for (BasesVector::iterator BaseIt = BasesToInheritFrom.begin(), + BaseE = BasesToInheritFrom.end(); + BaseIt != BaseE; ++BaseIt) { + const RecordType *Base = *BaseIt; + CanQualType CanonicalBase = Base->getCanonicalTypeUnqualified(); + CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getDecl()); + for (CXXRecordDecl::ctor_iterator CtorIt = BaseDecl->ctor_begin(), + CtorE = BaseDecl->ctor_end(); + CtorIt != CtorE; ++CtorIt) { + // Find the using declaration for inheriting this base's constructors. + DeclarationName Name = + Context.DeclarationNames.getCXXConstructorName(CanonicalBase); + UsingDecl *UD = dyn_cast_or_null<UsingDecl>( + LookupSingleName(S, Name,SourceLocation(), LookupUsingDeclName)); + SourceLocation UsingLoc = UD ? UD->getLocation() : + ClassDecl->getLocation(); + + // C++0x [class.inhctor]p1: The candidate set of inherited constructors + // from the class X named in the using-declaration consists of actual + // constructors and notional constructors that result from the + // transformation of defaulted parameters as follows: + // - all non-template default constructors of X, and + // - for each non-template constructor of X that has at least one + // parameter with a default argument, the set of constructors that + // results from omitting any ellipsis parameter specification and + // successively omitting parameters with a default argument from the + // end of the parameter-type-list. + CXXConstructorDecl *BaseCtor = *CtorIt; + bool CanBeCopyOrMove = BaseCtor->isCopyOrMoveConstructor(); + const FunctionProtoType *BaseCtorType = + BaseCtor->getType()->getAs<FunctionProtoType>(); + + for (unsigned params = BaseCtor->getMinRequiredArguments(), + maxParams = BaseCtor->getNumParams(); + params <= maxParams; ++params) { + // Skip default constructors. They're never inherited. + if (params == 0) + continue; + // Skip copy and move constructors for the same reason. + if (CanBeCopyOrMove && params == 1) + continue; + + // Build up a function type for this particular constructor. + // FIXME: The working paper does not consider that the exception spec + // for the inheriting constructor might be larger than that of the + // source. This code doesn't yet, either. When it does, this code will + // need to be delayed until after exception specifications and in-class + // member initializers are attached. + const Type *NewCtorType; + if (params == maxParams) + NewCtorType = BaseCtorType; + else { + llvm::SmallVector<QualType, 16> Args; + for (unsigned i = 0; i < params; ++i) { + Args.push_back(BaseCtorType->getArgType(i)); + } + FunctionProtoType::ExtProtoInfo ExtInfo = + BaseCtorType->getExtProtoInfo(); + ExtInfo.Variadic = false; + NewCtorType = Context.getFunctionType(BaseCtorType->getResultType(), + Args.data(), params, ExtInfo) + .getTypePtr(); + } + const Type *CanonicalNewCtorType = + Context.getCanonicalType(NewCtorType); + + // Now that we have the type, first check if the class already has a + // constructor with this signature. + if (ExistingConstructors.count(CanonicalNewCtorType)) + continue; + + // Then we check if we have already declared an inherited constructor + // with this signature. + std::pair<ConstructorToSourceMap::iterator, bool> result = + InheritedConstructors.insert(std::make_pair( + CanonicalNewCtorType, + std::make_pair(CanonicalBase, (CXXConstructorDecl*)0))); + if (!result.second) { + // Already in the map. If it came from a different class, that's an + // error. Not if it's from the same. + CanQualType PreviousBase = result.first->second.first; + if (CanonicalBase != PreviousBase) { + const CXXConstructorDecl *PrevCtor = result.first->second.second; + const CXXConstructorDecl *PrevBaseCtor = + PrevCtor->getInheritedConstructor(); + assert(PrevBaseCtor && "Conflicting constructor was not inherited"); + + Diag(UsingLoc, diag::err_using_decl_constructor_conflict); + Diag(BaseCtor->getLocation(), + diag::note_using_decl_constructor_conflict_current_ctor); + Diag(PrevBaseCtor->getLocation(), + diag::note_using_decl_constructor_conflict_previous_ctor); + Diag(PrevCtor->getLocation(), + diag::note_using_decl_constructor_conflict_previous_using); + } + continue; + } + + // OK, we're there, now add the constructor. + // C++0x [class.inhctor]p8: [...] that would be performed by a + // user-writtern inline constructor [...] + DeclarationNameInfo DNI(CreatedCtorName, UsingLoc); + CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create( + Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0), + /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true, + /*ImplicitlyDeclared=*/true); + NewCtor->setAccess(BaseCtor->getAccess()); + + // Build up the parameter decls and add them. + llvm::SmallVector<ParmVarDecl *, 16> ParamDecls; + for (unsigned i = 0; i < params; ++i) { + ParamDecls.push_back(ParmVarDecl::Create(Context, NewCtor, + UsingLoc, UsingLoc, + /*IdentifierInfo=*/0, + BaseCtorType->getArgType(i), + /*TInfo=*/0, SC_None, + SC_None, /*DefaultArg=*/0)); + } + NewCtor->setParams(ParamDecls.data(), ParamDecls.size()); + NewCtor->setInheritedConstructor(BaseCtor); + + PushOnScopeChains(NewCtor, S, false); + ClassDecl->addDecl(NewCtor); + result.first->second.second = NewCtor; + } + } + } +} + +Sema::ImplicitExceptionSpecification +Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) { + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have + // an exception-specification. + ImplicitExceptionSpecification ExceptSpec(Context); + + // Direct base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) + ExceptSpec.CalledDecl( + LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); + } + + // Virtual base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) + ExceptSpec.CalledDecl( + LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); + } + + // Field destructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs<RecordType>()) + ExceptSpec.CalledDecl( + LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl()))); + } + + return ExceptSpec; +} + +CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { + // C++ [class.dtor]p2: + // If a class has no user-declared destructor, a destructor is + // declared implicitly. An implicitly-declared destructor is an + // inline public member of its class. + + ImplicitExceptionSpecification Spec = + ComputeDefaultedDtorExceptionSpec(ClassDecl); + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + + // Create the actual destructor declaration. + QualType Ty = Context.getFunctionType(Context.VoidTy, 0, 0, EPI); + + CanQualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationName Name + = Context.DeclarationNames.getCXXDestructorName(ClassType); + DeclarationNameInfo NameInfo(Name, ClassLoc); + CXXDestructorDecl *Destructor + = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, Ty, 0, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); + Destructor->setAccess(AS_public); + Destructor->setDefaulted(); + Destructor->setImplicit(); + Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); + + // Note that we have declared this destructor. + ++ASTContext::NumImplicitDestructorsDeclared; + + // Introduce this destructor into its scope. + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(Destructor, S, false); + ClassDecl->addDecl(Destructor); + + // This could be uniqued if it ever proves significant. + Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); + + if (ShouldDeleteDestructor(Destructor)) + Destructor->setDeletedAsWritten(); + + AddOverriddenMethods(ClassDecl, Destructor); + + return Destructor; +} + +void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, + CXXDestructorDecl *Destructor) { + assert((Destructor->isDefaulted() && + !Destructor->doesThisDeclarationHaveABody()) && + "DefineImplicitDestructor - call it for implicit default dtor"); + CXXRecordDecl *ClassDecl = Destructor->getParent(); + assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); + + if (Destructor->isInvalidDecl()) + return; + + ImplicitlyDefinedFunctionScope Scope(*this, Destructor); + + DiagnosticErrorTrap Trap(Diags); + MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), + Destructor->getParent()); + + if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXDestructor << Context.getTagDeclType(ClassDecl); + + Destructor->setInvalidDecl(); + return; + } + + SourceLocation Loc = Destructor->getLocation(); + Destructor->setBody(new (Context) CompoundStmt(Context, 0, 0, Loc, Loc)); + + Destructor->setUsed(); + MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Destructor); + } +} + +void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl, + CXXDestructorDecl *destructor) { + // C++11 [class.dtor]p3: + // A declaration of a destructor that does not have an exception- + // specification is implicitly considered to have the same exception- + // specification as an implicit declaration. + const FunctionProtoType *dtorType = destructor->getType()-> + getAs<FunctionProtoType>(); + if (dtorType->hasExceptionSpec()) + return; + + ImplicitExceptionSpecification exceptSpec = + ComputeDefaultedDtorExceptionSpec(classDecl); + + // Replace the destructor's type. + FunctionProtoType::ExtProtoInfo epi; + epi.ExceptionSpecType = exceptSpec.getExceptionSpecType(); + epi.NumExceptions = exceptSpec.size(); + epi.Exceptions = exceptSpec.data(); + QualType ty = Context.getFunctionType(Context.VoidTy, 0, 0, epi); + + destructor->setType(ty); + + // FIXME: If the destructor has a body that could throw, and the newly created + // spec doesn't allow exceptions, we should emit a warning, because this + // change in behavior can break conforming C++03 programs at runtime. + // However, we don't have a body yet, so it needs to be done somewhere else. +} + +/// \brief Builds a statement that copies the given entity from \p From to +/// \c To. +/// +/// This routine is used to copy the members of a class with an +/// implicitly-declared copy assignment operator. When the entities being +/// copied are arrays, this routine builds for loops to copy them. +/// +/// \param S The Sema object used for type-checking. +/// +/// \param Loc The location where the implicit copy is being generated. +/// +/// \param T The type of the expressions being copied. Both expressions must +/// have this type. +/// +/// \param To The expression we are copying to. +/// +/// \param From The expression we are copying from. +/// +/// \param CopyingBaseSubobject Whether we're copying a base subobject. +/// Otherwise, it's a non-static member subobject. +/// +/// \param Depth Internal parameter recording the depth of the recursion. +/// +/// \returns A statement or a loop that copies the expressions. +static StmtResult +BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From, + bool CopyingBaseSubobject, unsigned Depth = 0) { + // C++0x [class.copy]p30: + // Each subobject is assigned in the manner appropriate to its type: + // + // - if the subobject is of class type, the copy assignment operator + // for the class is used (as if by explicit qualification; that is, + // ignoring any possible virtual overriding functions in more derived + // classes); + if (const RecordType *RecordTy = T->getAs<RecordType>()) { + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); + + // Look for operator=. + DeclarationName Name + = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); + LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName); + S.LookupQualifiedName(OpLookup, ClassDecl, false); + + // Filter out any result that isn't a copy-assignment operator. + LookupResult::Filter F = OpLookup.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + if (Method->isCopyAssignmentOperator()) + continue; + + F.erase(); + } + F.done(); + + // Suppress the protected check (C++ [class.protected]) for each of the + // assignment operators we found. This strange dance is required when + // we're assigning via a base classes's copy-assignment operator. To + // ensure that we're getting the right base class subobject (without + // ambiguities), we need to cast "this" to that subobject type; to + // ensure that we don't go through the virtual call mechanism, we need + // to qualify the operator= name with the base class (see below). However, + // this means that if the base class has a protected copy assignment + // operator, the protected member access check will fail. So, we + // rewrite "protected" access to "public" access in this case, since we + // know by construction that we're calling from a derived class. + if (CopyingBaseSubobject) { + for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end(); + L != LEnd; ++L) { + if (L.getAccess() == AS_protected) + L.setAccess(AS_public); + } + } + + // Create the nested-name-specifier that will be used to qualify the + // reference to operator=; this is required to suppress the virtual + // call mechanism. + CXXScopeSpec SS; + SS.MakeTrivial(S.Context, + NestedNameSpecifier::Create(S.Context, 0, false, + T.getTypePtr()), + Loc); + + // Create the reference to operator=. + ExprResult OpEqualRef + = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, + /*FirstQualifierInScope=*/0, OpLookup, + /*TemplateArgs=*/0, + /*SuppressQualifierCheck=*/true); + if (OpEqualRef.isInvalid()) + return StmtError(); + + // Build the call to the assignment operator. + + ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, + OpEqualRef.takeAs<Expr>(), + Loc, &From, 1, Loc); + if (Call.isInvalid()) + return StmtError(); + + return S.Owned(Call.takeAs<Stmt>()); + } + + // - if the subobject is of scalar type, the built-in assignment + // operator is used. + const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); + if (!ArrayTy) { + ExprResult Assignment = S.CreateBuiltinBinOp(Loc, BO_Assign, To, From); + if (Assignment.isInvalid()) + return StmtError(); + + return S.Owned(Assignment.takeAs<Stmt>()); + } + + // - if the subobject is an array, each element is assigned, in the + // manner appropriate to the element type; + + // Construct a loop over the array bounds, e.g., + // + // for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0) + // + // that will copy each of the array elements. + QualType SizeType = S.Context.getSizeType(); + + // Create the iteration variable. + IdentifierInfo *IterationVarName = 0; + { + llvm::SmallString<8> Str; + llvm::raw_svector_ostream OS(Str); + OS << "__i" << Depth; + IterationVarName = &S.Context.Idents.get(OS.str()); + } + VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, + IterationVarName, SizeType, + S.Context.getTrivialTypeSourceInfo(SizeType, Loc), + SC_None, SC_None); + + // Initialize the iteration variable to zero. + llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0); + IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc)); + + // Create a reference to the iteration variable; we'll use this several + // times throughout. + Expr *IterationVarRef + = S.BuildDeclRefExpr(IterationVar, SizeType, VK_RValue, Loc).take(); + assert(IterationVarRef && "Reference to invented variable cannot fail!"); + + // Create the DeclStmt that holds the iteration variable. + Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); + + // Create the comparison against the array bound. + llvm::APInt Upper + = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); + Expr *Comparison + = new (S.Context) BinaryOperator(IterationVarRef, + IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), + BO_NE, S.Context.BoolTy, + VK_RValue, OK_Ordinary, Loc); + + // Create the pre-increment of the iteration variable. + Expr *Increment + = new (S.Context) UnaryOperator(IterationVarRef, UO_PreInc, SizeType, + VK_LValue, OK_Ordinary, Loc); + + // Subscript the "from" and "to" expressions with the iteration variable. + From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, + IterationVarRef, Loc)); + To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, + IterationVarRef, Loc)); + + // Build the copy for an individual element of the array. + StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(), + To, From, CopyingBaseSubobject, + Depth + 1); + if (Copy.isInvalid()) + return StmtError(); + + // Construct the loop that copies all elements of this array. + return S.ActOnForStmt(Loc, Loc, InitStmt, + S.MakeFullExpr(Comparison), + 0, S.MakeFullExpr(Increment), + Loc, Copy.take()); +} + +/// \brief Determine whether the given class has a copy assignment operator +/// that accepts a const-qualified argument. +static bool hasConstCopyAssignment(Sema &S, const CXXRecordDecl *CClass) { + CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(CClass); + + if (!Class->hasDeclaredCopyAssignment()) + S.DeclareImplicitCopyAssignment(Class); + + QualType ClassType = S.Context.getCanonicalType(S.Context.getTypeDeclType(Class)); + DeclarationName OpName + = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); + + DeclContext::lookup_const_iterator Op, OpEnd; + for (llvm::tie(Op, OpEnd) = Class->lookup(OpName); Op != OpEnd; ++Op) { + // C++ [class.copy]p9: + // A user-declared copy assignment operator is a non-static non-template + // member function of class X with exactly one parameter of type X, X&, + // const X&, volatile X& or const volatile X&. + const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op); + if (!Method) + continue; + + if (Method->isStatic()) + continue; + if (Method->getPrimaryTemplate()) + continue; + const FunctionProtoType *FnType = + Method->getType()->getAs<FunctionProtoType>(); + assert(FnType && "Overloaded operator has no prototype."); + // Don't assert on this; an invalid decl might have been left in the AST. + if (FnType->getNumArgs() != 1 || FnType->isVariadic()) + continue; + bool AcceptsConst = true; + QualType ArgType = FnType->getArgType(0); + if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()){ + ArgType = Ref->getPointeeType(); + // Is it a non-const lvalue reference? + if (!ArgType.isConstQualified()) + AcceptsConst = false; + } + if (!S.Context.hasSameUnqualifiedType(ArgType, ClassType)) + continue; + + // We have a single argument of type cv X or cv X&, i.e. we've found the + // copy assignment operator. Return whether it accepts const arguments. + return AcceptsConst; + } + assert(Class->isInvalidDecl() && + "No copy assignment operator declared in valid code."); + return false; +} + +std::pair<Sema::ImplicitExceptionSpecification, bool> +Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst( + CXXRecordDecl *ClassDecl) { + // C++ [class.copy]p10: + // If the class definition does not explicitly declare a copy + // assignment operator, one is declared implicitly. + // The implicitly-defined copy assignment operator for a class X + // will have the form + // + // X& X::operator=(const X&) + // + // if + bool HasConstCopyAssignment = true; + + // -- each direct base class B of X has a copy assignment operator + // whose parameter is of type const B&, const volatile B& or B, + // and + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + HasConstCopyAssignment && Base != BaseEnd; ++Base) { + assert(!Base->getType()->isDependentType() && + "Cannot generate implicit members for class with dependent bases."); + const CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + HasConstCopyAssignment = hasConstCopyAssignment(*this, BaseClassDecl); + } + + // -- for all the nonstatic data members of X that are of a class + // type M (or array thereof), each such class type has a copy + // assignment operator whose parameter is of type const M&, + // const volatile M& or M. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + HasConstCopyAssignment && Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + const CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + HasConstCopyAssignment = hasConstCopyAssignment(*this, FieldClassDecl); + } + } + + // Otherwise, the implicitly declared copy assignment operator will + // have the form + // + // X& X::operator=(X&) + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(Context); + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + if (!BaseClassDecl->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(BaseClassDecl); + + if (CXXMethodDecl *CopyAssign + = BaseClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment)) + ExceptSpec.CalledDecl(CopyAssign); + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + + if (!FieldClassDecl->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(FieldClassDecl); + + if (CXXMethodDecl *CopyAssign + = FieldClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment)) + ExceptSpec.CalledDecl(CopyAssign); + } + } + + return std::make_pair(ExceptSpec, HasConstCopyAssignment); +} + +CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { + // Note: The following rules are largely analoguous to the copy + // constructor rules. Note that virtual bases are not taken into account + // for determining the argument type of the operator. Note also that + // operators taking an object instead of a reference are allowed. + + ImplicitExceptionSpecification Spec(Context); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl); + + QualType ArgType = Context.getTypeDeclType(ClassDecl); + QualType RetType = Context.getLValueReferenceType(ArgType); + if (Const) + ArgType = ArgType.withConst(); + ArgType = Context.getLValueReferenceType(ArgType); + + // An implicitly-declared copy assignment operator is an inline public + // member of its class. + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); + CXXMethodDecl *CopyAssignment + = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(RetType, &ArgType, 1, EPI), + /*TInfo=*/0, /*isStatic=*/false, + /*StorageClassAsWritten=*/SC_None, + /*isInline=*/true, + SourceLocation()); + CopyAssignment->setAccess(AS_public); + CopyAssignment->setDefaulted(); + CopyAssignment->setImplicit(); + CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); + + // Add the parameter to the operator. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, + ClassLoc, ClassLoc, /*Id=*/0, + ArgType, /*TInfo=*/0, + SC_None, + SC_None, 0); + CopyAssignment->setParams(&FromParam, 1); + + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyAssignment, S, false); + ClassDecl->addDecl(CopyAssignment); + + if (ShouldDeleteCopyAssignmentOperator(CopyAssignment)) + CopyAssignment->setDeletedAsWritten(); + + AddOverriddenMethods(ClassDecl, CopyAssignment); + return CopyAssignment; +} + +void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, + CXXMethodDecl *CopyAssignOperator) { + assert((CopyAssignOperator->isDefaulted() && + CopyAssignOperator->isOverloadedOperator() && + CopyAssignOperator->getOverloadedOperator() == OO_Equal && + !CopyAssignOperator->doesThisDeclarationHaveABody()) && + "DefineImplicitCopyAssignment called for wrong function"); + + CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); + + if (ClassDecl->isInvalidDecl() || CopyAssignOperator->isInvalidDecl()) { + CopyAssignOperator->setInvalidDecl(); + return; + } + + CopyAssignOperator->setUsed(); + + ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator); + DiagnosticErrorTrap Trap(Diags); + + // C++0x [class.copy]p30: + // The implicitly-defined or explicitly-defaulted copy assignment operator + // for a non-union class X performs memberwise copy assignment of its + // subobjects. The direct base classes of X are assigned first, in the + // order of their declaration in the base-specifier-list, and then the + // immediate non-static data members of X are assigned, in the order in + // which they were declared in the class definition. + + // The statements that form the synthesized function body. + ASTOwningVector<Stmt*> Statements(*this); + + // The parameter for the "other" object, which we are copying from. + ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0); + Qualifiers OtherQuals = Other->getType().getQualifiers(); + QualType OtherRefType = Other->getType(); + if (const LValueReferenceType *OtherRef + = OtherRefType->getAs<LValueReferenceType>()) { + OtherRefType = OtherRef->getPointeeType(); + OtherQuals = OtherRefType.getQualifiers(); + } + + // Our location for everything implicitly-generated. + SourceLocation Loc = CopyAssignOperator->getLocation(); + + // Construct a reference to the "other" object. We'll be using this + // throughout the generated ASTs. + Expr *OtherRef = BuildDeclRefExpr(Other, OtherRefType, VK_LValue, Loc).take(); + assert(OtherRef && "Reference to parameter cannot fail!"); + + // Construct the "this" pointer. We'll be using this throughout the generated + // ASTs. + Expr *This = ActOnCXXThis(Loc).takeAs<Expr>(); + assert(This && "Reference to this cannot fail!"); + + // Assign base classes. + bool Invalid = false; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { + // Form the assignment: + // static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other)); + QualType BaseType = Base->getType().getUnqualifiedType(); + if (!BaseType->isRecordType()) { + Invalid = true; + continue; + } + + CXXCastPath BasePath; + BasePath.push_back(Base); + + // Construct the "from" expression, which is an implicit cast to the + // appropriately-qualified base type. + Expr *From = OtherRef; + From = ImpCastExprToType(From, Context.getQualifiedType(BaseType, OtherQuals), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath).take(); + + // Dereference "this". + ExprResult To = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + + // Implicitly cast "this" to the appropriately-qualified base type. + To = ImpCastExprToType(To.take(), + Context.getCVRQualifiedType(BaseType, + CopyAssignOperator->getTypeQualifiers()), + CK_UncheckedDerivedToBase, + VK_LValue, &BasePath); + + // Build the copy. + StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, + To.get(), From, + /*CopyingBaseSubobject=*/true); + if (Copy.isInvalid()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + CopyAssignOperator->setInvalidDecl(); + return; + } + + // Success! Record the copy. + Statements.push_back(Copy.takeAs<Expr>()); + } + + // \brief Reference to the __builtin_memcpy function. + Expr *BuiltinMemCpyRef = 0; + // \brief Reference to the __builtin_objc_memmove_collectable function. + Expr *CollectableMemCpyRef = 0; + + // Assign non-static members. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { + // Check for members of reference type; we can't copy those. + if (Field->getType()->isReferenceType()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + continue; + } + + // Check for members of const-qualified, non-class type. + QualType BaseType = Context.getBaseElementType(Field->getType()); + if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) { + Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) + << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); + Diag(Field->getLocation(), diag::note_declared_at); + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + continue; + } + + QualType FieldType = Field->getType().getNonReferenceType(); + if (FieldType->isIncompleteArrayType()) { + assert(ClassDecl->hasFlexibleArrayMember() && + "Incomplete array type is not valid"); + continue; + } + + // Build references to the field in the object we're copying from and to. + CXXScopeSpec SS; // Intentionally empty + LookupResult MemberLookup(*this, Field->getDeclName(), Loc, + LookupMemberName); + MemberLookup.addDecl(*Field); + MemberLookup.resolveKind(); + ExprResult From = BuildMemberReferenceExpr(OtherRef, OtherRefType, + Loc, /*IsArrow=*/false, + SS, 0, MemberLookup, 0); + ExprResult To = BuildMemberReferenceExpr(This, This->getType(), + Loc, /*IsArrow=*/true, + SS, 0, MemberLookup, 0); + assert(!From.isInvalid() && "Implicit field reference cannot fail"); + assert(!To.isInvalid() && "Implicit field reference cannot fail"); + + // If the field should be copied with __builtin_memcpy rather than via + // explicit assignments, do so. This optimization only applies for arrays + // of scalars and arrays of class type with trivial copy-assignment + // operators. + if (FieldType->isArrayType() && + (!BaseType->isRecordType() || + cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()) + ->hasTrivialCopyAssignment())) { + // Compute the size of the memory buffer to be copied. + QualType SizeType = Context.getSizeType(); + llvm::APInt Size(Context.getTypeSize(SizeType), + Context.getTypeSizeInChars(BaseType).getQuantity()); + for (const ConstantArrayType *Array + = Context.getAsConstantArrayType(FieldType); + Array; + Array = Context.getAsConstantArrayType(Array->getElementType())) { + llvm::APInt ArraySize + = Array->getSize().zextOrTrunc(Size.getBitWidth()); + Size *= ArraySize; + } + + // Take the address of the field references for "from" and "to". + From = CreateBuiltinUnaryOp(Loc, UO_AddrOf, From.get()); + To = CreateBuiltinUnaryOp(Loc, UO_AddrOf, To.get()); + + bool NeedsCollectableMemCpy = + (BaseType->isRecordType() && + BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()); + + if (NeedsCollectableMemCpy) { + if (!CollectableMemCpyRef) { + // Create a reference to the __builtin_objc_memmove_collectable function. + LookupResult R(*this, + &Context.Idents.get("__builtin_objc_memmove_collectable"), + Loc, LookupOrdinaryName); + LookupName(R, TUScope, true); + + FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>(); + if (!CollectableMemCpy) { + // Something went horribly wrong earlier, and we will have + // complained about it. + Invalid = true; + continue; + } + + CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, + CollectableMemCpy->getType(), + VK_LValue, Loc, 0).take(); + assert(CollectableMemCpyRef && "Builtin reference cannot fail"); + } + } + // Create a reference to the __builtin_memcpy builtin function. + else if (!BuiltinMemCpyRef) { + LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc, + LookupOrdinaryName); + LookupName(R, TUScope, true); + + FunctionDecl *BuiltinMemCpy = R.getAsSingle<FunctionDecl>(); + if (!BuiltinMemCpy) { + // Something went horribly wrong earlier, and we will have complained + // about it. + Invalid = true; + continue; + } + + BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, + BuiltinMemCpy->getType(), + VK_LValue, Loc, 0).take(); + assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); + } + + ASTOwningVector<Expr*> CallArgs(*this); + CallArgs.push_back(To.takeAs<Expr>()); + CallArgs.push_back(From.takeAs<Expr>()); + CallArgs.push_back(IntegerLiteral::Create(Context, Size, SizeType, Loc)); + ExprResult Call = ExprError(); + if (NeedsCollectableMemCpy) + Call = ActOnCallExpr(/*Scope=*/0, + CollectableMemCpyRef, + Loc, move_arg(CallArgs), + Loc); + else + Call = ActOnCallExpr(/*Scope=*/0, + BuiltinMemCpyRef, + Loc, move_arg(CallArgs), + Loc); + + assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); + Statements.push_back(Call.takeAs<Expr>()); + continue; + } + + // Build the copy of this field. + StmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, + To.get(), From.get(), + /*CopyingBaseSubobject=*/false); + if (Copy.isInvalid()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + CopyAssignOperator->setInvalidDecl(); + return; + } + + // Success! Record the copy. + Statements.push_back(Copy.takeAs<Stmt>()); + } + + if (!Invalid) { + // Add a "return *this;" + ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This); + + StmtResult Return = ActOnReturnStmt(Loc, ThisObj.get()); + if (Return.isInvalid()) + Invalid = true; + else { + Statements.push_back(Return.takeAs<Stmt>()); + + if (Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + Invalid = true; + } + } + } + + if (Invalid) { + CopyAssignOperator->setInvalidDecl(); + return; + } + + StmtResult Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + /*isStmtExpr=*/false); + assert(!Body.isInvalid() && "Compound statement creation cannot fail"); + CopyAssignOperator->setBody(Body.takeAs<Stmt>()); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyAssignOperator); + } +} + +std::pair<Sema::ImplicitExceptionSpecification, bool> +Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) { + // C++ [class.copy]p5: + // The implicitly-declared copy constructor for a class X will + // have the form + // + // X::X(const X&) + // + // if + // FIXME: It ought to be possible to store this on the record. + bool HasConstCopyConstructor = true; + + // -- each direct or virtual base class B of X has a copy + // constructor whose first parameter is of type const B& or + // const volatile B&, and + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + HasConstCopyConstructor && Base != BaseEnd; + ++Base) { + // Virtual bases are handled below. + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + LookupCopyConstructor(BaseClassDecl, Qualifiers::Const, + &HasConstCopyConstructor); + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + HasConstCopyConstructor && Base != BaseEnd; + ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + LookupCopyConstructor(BaseClassDecl, Qualifiers::Const, + &HasConstCopyConstructor); + } + + // -- for all the nonstatic data members of X that are of a + // class type M (or array thereof), each such class type + // has a copy constructor whose first parameter is of type + // const M& or const volatile M&. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + HasConstCopyConstructor && Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + LookupCopyConstructor(FieldClassDecl, Qualifiers::Const, + &HasConstCopyConstructor); + } + } + // Otherwise, the implicitly declared copy constructor will have + // the form + // + // X::X(X&) + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(Context); + unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; + ++Base) { + // Virtual bases are handled below. + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (CXXConstructorDecl *CopyConstructor = + LookupCopyConstructor(BaseClassDecl, Quals)) + ExceptSpec.CalledDecl(CopyConstructor); + } + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; + ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (CXXConstructorDecl *CopyConstructor = + LookupCopyConstructor(BaseClassDecl, Quals)) + ExceptSpec.CalledDecl(CopyConstructor); + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { + if (CXXConstructorDecl *CopyConstructor = + LookupCopyConstructor(FieldClassDecl, Quals)) + ExceptSpec.CalledDecl(CopyConstructor); + } + } + + return std::make_pair(ExceptSpec, HasConstCopyConstructor); +} + +CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( + CXXRecordDecl *ClassDecl) { + // C++ [class.copy]p4: + // If the class definition does not explicitly declare a copy + // constructor, one is declared implicitly. + + ImplicitExceptionSpecification Spec(Context); + bool Const; + llvm::tie(Spec, Const) = + ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl); + + QualType ClassType = Context.getTypeDeclType(ClassDecl); + QualType ArgType = ClassType; + if (Const) + ArgType = ArgType.withConst(); + ArgType = Context.getLValueReferenceType(ArgType); + + FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI(); + + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(ClassType)); + SourceLocation ClassLoc = ClassDecl->getLocation(); + DeclarationNameInfo NameInfo(Name, ClassLoc); + + // An implicitly-declared copy constructor is an inline public + // member of its class. + CXXConstructorDecl *CopyConstructor + = CXXConstructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, + Context.getFunctionType(Context.VoidTy, + &ArgType, 1, EPI), + /*TInfo=*/0, + /*isExplicit=*/false, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); + CopyConstructor->setAccess(AS_public); + CopyConstructor->setDefaulted(); + CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); + + // Note that we have declared this constructor. + ++ASTContext::NumImplicitCopyConstructorsDeclared; + + // Add the parameter to the constructor. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, + ClassLoc, ClassLoc, + /*IdentifierInfo=*/0, + ArgType, /*TInfo=*/0, + SC_None, + SC_None, 0); + CopyConstructor->setParams(&FromParam, 1); + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyConstructor, S, false); + ClassDecl->addDecl(CopyConstructor); + + if (ShouldDeleteCopyConstructor(CopyConstructor)) + CopyConstructor->setDeletedAsWritten(); + + return CopyConstructor; +} + +void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *CopyConstructor) { + assert((CopyConstructor->isDefaulted() && + CopyConstructor->isCopyConstructor() && + !CopyConstructor->doesThisDeclarationHaveABody()) && + "DefineImplicitCopyConstructor - call it for implicit copy ctor"); + + CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); + assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); + + ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor); + DiagnosticErrorTrap Trap(Diags); + + if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyConstructor << Context.getTagDeclType(ClassDecl); + CopyConstructor->setInvalidDecl(); + } else { + CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(), + CopyConstructor->getLocation(), + MultiStmtArg(*this, 0, 0), + /*isStmtExpr=*/false) + .takeAs<Stmt>()); + } + + CopyConstructor->setUsed(); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(CopyConstructor); + } +} + +ExprResult +Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, + MultiExprArg ExprArgs, + bool RequiresZeroInit, + unsigned ConstructKind, + SourceRange ParenRange) { + bool Elidable = false; + + // C++0x [class.copy]p34: + // When certain criteria are met, an implementation is allowed to + // omit the copy/move construction of a class object, even if the + // copy/move constructor and/or destructor for the object have + // side effects. [...] + // - when a temporary class object that has not been bound to a + // reference (12.2) would be copied/moved to a class object + // with the same cv-unqualified type, the copy/move operation + // can be omitted by constructing the temporary object + // directly into the target of the omitted copy/move + if (ConstructKind == CXXConstructExpr::CK_Complete && + Constructor->isCopyOrMoveConstructor() && ExprArgs.size() >= 1) { + Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; + Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); + } + + return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, + Elidable, move(ExprArgs), RequiresZeroInit, + ConstructKind, ParenRange); +} + +/// BuildCXXConstructExpr - Creates a complete call to a constructor, +/// including handling of its default argument expressions. +ExprResult +Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, + CXXConstructorDecl *Constructor, bool Elidable, + MultiExprArg ExprArgs, + bool RequiresZeroInit, + unsigned ConstructKind, + SourceRange ParenRange) { + unsigned NumExprs = ExprArgs.size(); + Expr **Exprs = (Expr **)ExprArgs.release(); + + for (specific_attr_iterator<NonNullAttr> + i = Constructor->specific_attr_begin<NonNullAttr>(), + e = Constructor->specific_attr_end<NonNullAttr>(); i != e; ++i) { + const NonNullAttr *NonNull = *i; + CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc); + } + + MarkDeclarationReferenced(ConstructLoc, Constructor); + return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, + Constructor, Elidable, Exprs, NumExprs, + RequiresZeroInit, + static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), + ParenRange)); +} + +bool Sema::InitializeVarWithConstructor(VarDecl *VD, + CXXConstructorDecl *Constructor, + MultiExprArg Exprs) { + // FIXME: Provide the correct paren SourceRange when available. + ExprResult TempResult = + BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, + move(Exprs), false, CXXConstructExpr::CK_Complete, + SourceRange()); + if (TempResult.isInvalid()) + return true; + + Expr *Temp = TempResult.takeAs<Expr>(); + CheckImplicitConversions(Temp, VD->getLocation()); + MarkDeclarationReferenced(VD->getLocation(), Constructor); + Temp = MaybeCreateExprWithCleanups(Temp); + VD->setInit(Temp); + + return false; +} + +void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { + if (VD->isInvalidDecl()) return; + + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); + if (ClassDecl->isInvalidDecl()) return; + if (ClassDecl->hasTrivialDestructor()) return; + if (ClassDecl->isDependentContext()) return; + + CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); + MarkDeclarationReferenced(VD->getLocation(), Destructor); + CheckDestructorAccess(VD->getLocation(), Destructor, + PDiag(diag::err_access_dtor_var) + << VD->getDeclName() + << VD->getType()); + + if (!VD->hasGlobalStorage()) return; + + // Emit warning for non-trivial dtor in global scope (a real global, + // class-static, function-static). + Diag(VD->getLocation(), diag::warn_exit_time_destructor); + + // TODO: this should be re-enabled for static locals by !CXAAtExit + if (!VD->isStaticLocal()) + Diag(VD->getLocation(), diag::warn_global_destructor); +} + +/// AddCXXDirectInitializerToDecl - This action is called immediately after +/// ActOnDeclarator, when a C++ direct initializer is present. +/// e.g: "int x(1);" +void Sema::AddCXXDirectInitializerToDecl(Decl *RealDecl, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation RParenLoc, + bool TypeMayContainAuto) { + assert(Exprs.size() != 0 && Exprs.get() && "missing expressions"); + + // If there is no declaration, there was an error parsing it. Just ignore + // the initializer. + if (RealDecl == 0) + return; + + VarDecl *VDecl = dyn_cast<VarDecl>(RealDecl); + if (!VDecl) { + Diag(RealDecl->getLocation(), diag::err_illegal_initializer); + RealDecl->setInvalidDecl(); + return; + } + + // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { + // FIXME: n3225 doesn't actually seem to indicate this is ill-formed + if (Exprs.size() > 1) { + Diag(Exprs.get()[1]->getSourceRange().getBegin(), + diag::err_auto_var_init_multiple_expressions) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); + RealDecl->setInvalidDecl(); + return; + } + + Expr *Init = Exprs.get()[0]; + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType)) + Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure) + << VDecl->getDeclName() << VDecl->getType() << Init->getType() + << Init->getSourceRange(); + if (!DeducedType) { + RealDecl->setInvalidDecl(); + return; + } + VDecl->setTypeSourceInfo(DeducedType); + VDecl->setType(DeducedType->getType()); + + // If this is a redeclaration, check that the type we just deduced matches + // the previously declared type. + if (VarDecl *Old = VDecl->getPreviousDeclaration()) + MergeVarDeclTypes(VDecl, Old); + } + + // We will represent direct-initialization similarly to copy-initialization: + // int x(1); -as-> int x = 1; + // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); + // + // Clients that want to distinguish between the two forms, can check for + // direct initializer using VarDecl::hasCXXDirectInitializer(). + // A major benefit is that clients that don't particularly care about which + // exactly form was it (like the CodeGen) can handle both cases without + // special case code. + + // C++ 8.5p11: + // The form of initialization (using parentheses or '=') is generally + // insignificant, but does matter when the entity being initialized has a + // class type. + + if (!VDecl->getType()->isDependentType() && + RequireCompleteType(VDecl->getLocation(), VDecl->getType(), + diag::err_typecheck_decl_incomplete_type)) { + VDecl->setInvalidDecl(); + return; + } + + // The variable can not have an abstract class type. + if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), + diag::err_abstract_type_in_decl, + AbstractVariableType)) + VDecl->setInvalidDecl(); + + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { + Diag(VDecl->getLocation(), diag::err_redefinition) + << VDecl->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + VDecl->setInvalidDecl(); + return; + } + + // C++ [class.static.data]p4 + // If a static data member is of const integral or const + // enumeration type, its declaration in the class definition can + // specify a constant-initializer which shall be an integral + // constant expression (5.19). In that case, the member can appear + // in integral constant expressions. The member shall still be + // defined in a namespace scope if it is used in the program and the + // namespace scope definition shall not contain an initializer. + // + // We already performed a redefinition check above, but for static + // data members we also need to check whether there was an in-class + // declaration with an initializer. + const VarDecl* PrevInit = 0; + if (VDecl->isStaticDataMember() && VDecl->getAnyInitializer(PrevInit)) { + Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); + Diag(PrevInit->getLocation(), diag::note_previous_definition); + return; + } + + bool IsDependent = false; + for (unsigned I = 0, N = Exprs.size(); I != N; ++I) { + if (DiagnoseUnexpandedParameterPack(Exprs.get()[I], UPPC_Expression)) { + VDecl->setInvalidDecl(); + return; + } + + if (Exprs.get()[I]->isTypeDependent()) + IsDependent = true; + } + + // If either the declaration has a dependent type or if any of the + // expressions is type-dependent, we represent the initialization + // via a ParenListExpr for later use during template instantiation. + if (VDecl->getType()->isDependentType() || IsDependent) { + // Let clients know that initialization was done with a direct initializer. + VDecl->setCXXDirectInitializer(true); + + // Store the initialization expressions as a ParenListExpr. + unsigned NumExprs = Exprs.size(); + VDecl->setInit(new (Context) ParenListExpr(Context, LParenLoc, + (Expr **)Exprs.release(), + NumExprs, RParenLoc)); + return; + } + + // Capture the variable that is being initialized and the style of + // initialization. + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + + // FIXME: Poor source location information. + InitializationKind Kind + = InitializationKind::CreateDirect(VDecl->getLocation(), + LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, Entity, Kind, + Exprs.get(), Exprs.size()); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(Exprs)); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + + CheckImplicitConversions(Result.get(), LParenLoc); + + Result = MaybeCreateExprWithCleanups(Result); + VDecl->setInit(Result.takeAs<Expr>()); + VDecl->setCXXDirectInitializer(true); + + CheckCompleteVariableDeclaration(VDecl); +} + +/// \brief Given a constructor and the set of arguments provided for the +/// constructor, convert the arguments and add any required default arguments +/// to form a proper call to this constructor. +/// +/// \returns true if an error occurred, false otherwise. +bool +Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, + MultiExprArg ArgsPtr, + SourceLocation Loc, + ASTOwningVector<Expr*> &ConvertedArgs) { + // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. + unsigned NumArgs = ArgsPtr.size(); + Expr **Args = (Expr **)ArgsPtr.get(); + + const FunctionProtoType *Proto + = Constructor->getType()->getAs<FunctionProtoType>(); + assert(Proto && "Constructor without a prototype?"); + unsigned NumArgsInProto = Proto->getNumArgs(); + + // If too few arguments are available, we'll fill in the rest with defaults. + if (NumArgs < NumArgsInProto) + ConvertedArgs.reserve(NumArgsInProto); + else + ConvertedArgs.reserve(NumArgs); + + VariadicCallType CallType = + Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; + llvm::SmallVector<Expr *, 8> AllArgs; + bool Invalid = GatherArgumentsForCall(Loc, Constructor, + Proto, 0, Args, NumArgs, AllArgs, + CallType); + for (unsigned i =0, size = AllArgs.size(); i < size; i++) + ConvertedArgs.push_back(AllArgs[i]); + return Invalid; +} + +static inline bool +CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, + const FunctionDecl *FnDecl) { + const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext(); + if (isa<NamespaceDecl>(DC)) { + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_declared_in_namespace) + << FnDecl->getDeclName(); + } + + if (isa<TranslationUnitDecl>(DC) && + FnDecl->getStorageClass() == SC_Static) { + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_declared_static) + << FnDecl->getDeclName(); + } + + return false; +} + +static inline bool +CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, + CanQualType ExpectedResultType, + CanQualType ExpectedFirstParamType, + unsigned DependentParamTypeDiag, + unsigned InvalidParamTypeDiag) { + QualType ResultType = + FnDecl->getType()->getAs<FunctionType>()->getResultType(); + + // Check that the result type is not dependent. + if (ResultType->isDependentType()) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_dependent_result_type) + << FnDecl->getDeclName() << ExpectedResultType; + + // Check that the result type is what we expect. + if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_invalid_result_type) + << FnDecl->getDeclName() << ExpectedResultType; + + // A function template must have at least 2 parameters. + if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_template_too_few_parameters) + << FnDecl->getDeclName(); + + // The function decl must have at least 1 parameter. + if (FnDecl->getNumParams() == 0) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_delete_too_few_parameters) + << FnDecl->getDeclName(); + + // Check the the first parameter type is not dependent. + QualType FirstParamType = FnDecl->getParamDecl(0)->getType(); + if (FirstParamType->isDependentType()) + return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag) + << FnDecl->getDeclName() << ExpectedFirstParamType; + + // Check that the first parameter type is what we expect. + if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != + ExpectedFirstParamType) + return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) + << FnDecl->getDeclName() << ExpectedFirstParamType; + + return false; +} + +static bool +CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { + // C++ [basic.stc.dynamic.allocation]p1: + // A program is ill-formed if an allocation function is declared in a + // namespace scope other than global scope or declared static in global + // scope. + if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) + return true; + + CanQualType SizeTy = + SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType()); + + // C++ [basic.stc.dynamic.allocation]p1: + // The return type shall be void*. The first parameter shall have type + // std::size_t. + if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, + SizeTy, + diag::err_operator_new_dependent_param_type, + diag::err_operator_new_param_type)) + return true; + + // C++ [basic.stc.dynamic.allocation]p1: + // The first parameter shall not have an associated default argument. + if (FnDecl->getParamDecl(0)->hasDefaultArg()) + return SemaRef.Diag(FnDecl->getLocation(), + diag::err_operator_new_default_arg) + << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange(); + + return false; +} + +static bool +CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { + // C++ [basic.stc.dynamic.deallocation]p1: + // A program is ill-formed if deallocation functions are declared in a + // namespace scope other than global scope or declared static in global + // scope. + if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) + return true; + + // C++ [basic.stc.dynamic.deallocation]p2: + // Each deallocation function shall return void and its first parameter + // shall be void*. + if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, + SemaRef.Context.VoidPtrTy, + diag::err_operator_delete_dependent_param_type, + diag::err_operator_delete_param_type)) + return true; + + return false; +} + +/// CheckOverloadedOperatorDeclaration - Check whether the declaration +/// of this overloaded operator is well-formed. If so, returns false; +/// otherwise, emits appropriate diagnostics and returns true. +bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { + assert(FnDecl && FnDecl->isOverloadedOperator() && + "Expected an overloaded operator declaration"); + + OverloadedOperatorKind Op = FnDecl->getOverloadedOperator(); + + // C++ [over.oper]p5: + // The allocation and deallocation functions, operator new, + // operator new[], operator delete and operator delete[], are + // described completely in 3.7.3. The attributes and restrictions + // found in the rest of this subclause do not apply to them unless + // explicitly stated in 3.7.3. + if (Op == OO_Delete || Op == OO_Array_Delete) + return CheckOperatorDeleteDeclaration(*this, FnDecl); + + if (Op == OO_New || Op == OO_Array_New) + return CheckOperatorNewDeclaration(*this, FnDecl); + + // C++ [over.oper]p6: + // An operator function shall either be a non-static member + // function or be a non-member function and have at least one + // parameter whose type is a class, a reference to a class, an + // enumeration, or a reference to an enumeration. + if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) { + if (MethodDecl->isStatic()) + return Diag(FnDecl->getLocation(), + diag::err_operator_overload_static) << FnDecl->getDeclName(); + } else { + bool ClassOrEnumParam = false; + for (FunctionDecl::param_iterator Param = FnDecl->param_begin(), + ParamEnd = FnDecl->param_end(); + Param != ParamEnd; ++Param) { + QualType ParamType = (*Param)->getType().getNonReferenceType(); + if (ParamType->isDependentType() || ParamType->isRecordType() || + ParamType->isEnumeralType()) { + ClassOrEnumParam = true; + break; + } + } + + if (!ClassOrEnumParam) + return Diag(FnDecl->getLocation(), + diag::err_operator_overload_needs_class_or_enum) + << FnDecl->getDeclName(); + } + + // C++ [over.oper]p8: + // An operator function cannot have default arguments (8.3.6), + // except where explicitly stated below. + // + // Only the function-call operator allows default arguments + // (C++ [over.call]p1). + if (Op != OO_Call) { + for (FunctionDecl::param_iterator Param = FnDecl->param_begin(); + Param != FnDecl->param_end(); ++Param) { + if ((*Param)->hasDefaultArg()) + return Diag((*Param)->getLocation(), + diag::err_operator_overload_default_arg) + << FnDecl->getDeclName() << (*Param)->getDefaultArgRange(); + } + } + + static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = { + { false, false, false } +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + , { Unary, Binary, MemberOnly } +#include "clang/Basic/OperatorKinds.def" + }; + + bool CanBeUnaryOperator = OperatorUses[Op][0]; + bool CanBeBinaryOperator = OperatorUses[Op][1]; + bool MustBeMemberOperator = OperatorUses[Op][2]; + + // C++ [over.oper]p8: + // [...] Operator functions cannot have more or fewer parameters + // than the number required for the corresponding operator, as + // described in the rest of this subclause. + unsigned NumParams = FnDecl->getNumParams() + + (isa<CXXMethodDecl>(FnDecl)? 1 : 0); + if (Op != OO_Call && + ((NumParams == 1 && !CanBeUnaryOperator) || + (NumParams == 2 && !CanBeBinaryOperator) || + (NumParams < 1) || (NumParams > 2))) { + // We have the wrong number of parameters. + unsigned ErrorKind; + if (CanBeUnaryOperator && CanBeBinaryOperator) { + ErrorKind = 2; // 2 -> unary or binary. + } else if (CanBeUnaryOperator) { + ErrorKind = 0; // 0 -> unary + } else { + assert(CanBeBinaryOperator && + "All non-call overloaded operators are unary or binary!"); + ErrorKind = 1; // 1 -> binary + } + + return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be) + << FnDecl->getDeclName() << NumParams << ErrorKind; + } + + // Overloaded operators other than operator() cannot be variadic. + if (Op != OO_Call && + FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) { + return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic) + << FnDecl->getDeclName(); + } + + // Some operators must be non-static member functions. + if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) { + return Diag(FnDecl->getLocation(), + diag::err_operator_overload_must_be_member) + << FnDecl->getDeclName(); + } + + // C++ [over.inc]p1: + // The user-defined function called operator++ implements the + // prefix and postfix ++ operator. If this function is a member + // function with no parameters, or a non-member function with one + // parameter of class or enumeration type, it defines the prefix + // increment operator ++ for objects of that type. If the function + // is a member function with one parameter (which shall be of type + // int) or a non-member function with two parameters (the second + // of which shall be of type int), it defines the postfix + // increment operator ++ for objects of that type. + if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) { + ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1); + bool ParamIsInt = false; + if (const BuiltinType *BT = LastParam->getType()->getAs<BuiltinType>()) + ParamIsInt = BT->getKind() == BuiltinType::Int; + + if (!ParamIsInt) + return Diag(LastParam->getLocation(), + diag::err_operator_overload_post_incdec_must_be_int) + << LastParam->getType() << (Op == OO_MinusMinus); + } + + return false; +} + +/// CheckLiteralOperatorDeclaration - Check whether the declaration +/// of this literal operator function is well-formed. If so, returns +/// false; otherwise, emits appropriate diagnostics and returns true. +bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { + DeclContext *DC = FnDecl->getDeclContext(); + Decl::Kind Kind = DC->getDeclKind(); + if (Kind != Decl::TranslationUnit && Kind != Decl::Namespace && + Kind != Decl::LinkageSpec) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) + << FnDecl->getDeclName(); + return true; + } + + bool Valid = false; + + // template <char...> type operator "" name() is the only valid template + // signature, and the only valid signature with no parameters. + if (FnDecl->param_size() == 0) { + if (FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate()) { + // Must have only one template parameter + TemplateParameterList *Params = TpDecl->getTemplateParameters(); + if (Params->size() == 1) { + NonTypeTemplateParmDecl *PmDecl = + cast<NonTypeTemplateParmDecl>(Params->getParam(0)); + + // The template parameter must be a char parameter pack. + if (PmDecl && PmDecl->isTemplateParameterPack() && + Context.hasSameType(PmDecl->getType(), Context.CharTy)) + Valid = true; + } + } + } else { + // Check the first parameter + FunctionDecl::param_iterator Param = FnDecl->param_begin(); + + QualType T = (*Param)->getType(); + + // unsigned long long int, long double, and any character type are allowed + // as the only parameters. + if (Context.hasSameType(T, Context.UnsignedLongLongTy) || + Context.hasSameType(T, Context.LongDoubleTy) || + Context.hasSameType(T, Context.CharTy) || + Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.Char16Ty) || + Context.hasSameType(T, Context.Char32Ty)) { + if (++Param == FnDecl->param_end()) + Valid = true; + goto FinishedParams; + } + + // Otherwise it must be a pointer to const; let's strip those qualifiers. + const PointerType *PT = T->getAs<PointerType>(); + if (!PT) + goto FinishedParams; + T = PT->getPointeeType(); + if (!T.isConstQualified()) + goto FinishedParams; + T = T.getUnqualifiedType(); + + // Move on to the second parameter; + ++Param; + + // If there is no second parameter, the first must be a const char * + if (Param == FnDecl->param_end()) { + if (Context.hasSameType(T, Context.CharTy)) + Valid = true; + goto FinishedParams; + } + + // const char *, const wchar_t*, const char16_t*, and const char32_t* + // are allowed as the first parameter to a two-parameter function + if (!(Context.hasSameType(T, Context.CharTy) || + Context.hasSameType(T, Context.WCharTy) || + Context.hasSameType(T, Context.Char16Ty) || + Context.hasSameType(T, Context.Char32Ty))) + goto FinishedParams; + + // The second and final parameter must be an std::size_t + T = (*Param)->getType().getUnqualifiedType(); + if (Context.hasSameType(T, Context.getSizeType()) && + ++Param == FnDecl->param_end()) + Valid = true; + } + + // FIXME: This diagnostic is absolutely terrible. +FinishedParams: + if (!Valid) { + Diag(FnDecl->getLocation(), diag::err_literal_operator_params) + << FnDecl->getDeclName(); + return true; + } + + return false; +} + +/// ActOnStartLinkageSpecification - Parsed the beginning of a C++ +/// linkage specification, including the language and (if present) +/// the '{'. ExternLoc is the location of the 'extern', LangLoc is +/// the location of the language string literal, which is provided +/// by Lang/StrSize. LBraceLoc, if valid, provides the location of +/// the '{' brace. Otherwise, this linkage specification does not +/// have any braces. +Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, + SourceLocation LangLoc, + llvm::StringRef Lang, + SourceLocation LBraceLoc) { + LinkageSpecDecl::LanguageIDs Language; + if (Lang == "\"C\"") + Language = LinkageSpecDecl::lang_c; + else if (Lang == "\"C++\"") + Language = LinkageSpecDecl::lang_cxx; + else { + Diag(LangLoc, diag::err_bad_language); + return 0; + } + + // FIXME: Add all the various semantics of linkage specifications + + LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, + ExternLoc, LangLoc, Language); + CurContext->addDecl(D); + PushDeclContext(S, D); + return D; +} + +/// ActOnFinishLinkageSpecification - Complete the definition of +/// the C++ linkage specification LinkageSpec. If RBraceLoc is +/// valid, it's the position of the closing '}' brace in a linkage +/// specification that uses braces. +Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, + Decl *LinkageSpec, + SourceLocation RBraceLoc) { + if (LinkageSpec) { + if (RBraceLoc.isValid()) { + LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec); + LSDecl->setRBraceLoc(RBraceLoc); + } + PopDeclContext(); + } + return LinkageSpec; +} + +/// \brief Perform semantic analysis for the variable declaration that +/// occurs within a C++ catch clause, returning the newly-created +/// variable. +VarDecl *Sema::BuildExceptionDeclaration(Scope *S, + TypeSourceInfo *TInfo, + SourceLocation StartLoc, + SourceLocation Loc, + IdentifierInfo *Name) { + bool Invalid = false; + QualType ExDeclType = TInfo->getType(); + + // Arrays and functions decay. + if (ExDeclType->isArrayType()) + ExDeclType = Context.getArrayDecayedType(ExDeclType); + else if (ExDeclType->isFunctionType()) + ExDeclType = Context.getPointerType(ExDeclType); + + // C++ 15.3p1: The exception-declaration shall not denote an incomplete type. + // The exception-declaration shall not denote a pointer or reference to an + // incomplete type, other than [cv] void*. + // N2844 forbids rvalue references. + if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) { + Diag(Loc, diag::err_catch_rvalue_ref); + Invalid = true; + } + + // GCC allows catching pointers and references to incomplete types + // as an extension; so do we, but we warn by default. + + QualType BaseType = ExDeclType; + int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference + unsigned DK = diag::err_catch_incomplete; + bool IncompleteCatchIsInvalid = true; + if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { + BaseType = Ptr->getPointeeType(); + Mode = 1; + DK = diag::ext_catch_incomplete_ptr; + IncompleteCatchIsInvalid = false; + } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) { + // For the purpose of error recovery, we treat rvalue refs like lvalue refs. + BaseType = Ref->getPointeeType(); + Mode = 2; + DK = diag::ext_catch_incomplete_ref; + IncompleteCatchIsInvalid = false; + } + if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) && + !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK) && + IncompleteCatchIsInvalid) + Invalid = true; + + if (!Invalid && !ExDeclType->isDependentType() && + RequireNonAbstractType(Loc, ExDeclType, + diag::err_abstract_type_in_decl, + AbstractVariableType)) + Invalid = true; + + // Only the non-fragile NeXT runtime currently supports C++ catches + // of ObjC types, and no runtime supports catching ObjC types by value. + if (!Invalid && getLangOptions().ObjC1) { + QualType T = ExDeclType; + if (const ReferenceType *RT = T->getAs<ReferenceType>()) + T = RT->getPointeeType(); + + if (T->isObjCObjectType()) { + Diag(Loc, diag::err_objc_object_catch); + Invalid = true; + } else if (T->isObjCObjectPointerType()) { + if (!getLangOptions().ObjCNonFragileABI) { + Diag(Loc, diag::err_objc_pointer_cxx_catch_fragile); + Invalid = true; + } + } + } + + VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, + ExDeclType, TInfo, SC_None, SC_None); + ExDecl->setExceptionVariable(true); + + if (!Invalid) { + if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) { + // C++ [except.handle]p16: + // The object declared in an exception-declaration or, if the + // exception-declaration does not specify a name, a temporary (12.2) is + // copy-initialized (8.5) from the exception object. [...] + // The object is destroyed when the handler exits, after the destruction + // of any automatic objects initialized within the handler. + // + // We just pretend to initialize the object with itself, then make sure + // it can be destroyed later. + QualType initType = ExDeclType; + + InitializedEntity entity = + InitializedEntity::InitializeVariable(ExDecl); + InitializationKind initKind = + InitializationKind::CreateCopy(Loc, SourceLocation()); + + Expr *opaqueValue = + new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary); + InitializationSequence sequence(*this, entity, initKind, &opaqueValue, 1); + ExprResult result = sequence.Perform(*this, entity, initKind, + MultiExprArg(&opaqueValue, 1)); + if (result.isInvalid()) + Invalid = true; + else { + // If the constructor used was non-trivial, set this as the + // "initializer". + CXXConstructExpr *construct = cast<CXXConstructExpr>(result.take()); + if (!construct->getConstructor()->isTrivial()) { + Expr *init = MaybeCreateExprWithCleanups(construct); + ExDecl->setInit(init); + } + + // And make sure it's destructable. + FinalizeVarWithDestructor(ExDecl, recordType); + } + } + } + + if (Invalid) + ExDecl->setInvalidDecl(); + + return ExDecl; +} + +/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch +/// handler. +Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + bool Invalid = D.isInvalidType(); + + // Check for unexpanded parameter packs. + if (TInfo && DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_ExceptionType)) { + TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, + D.getIdentifierLoc()); + Invalid = true; + } + + IdentifierInfo *II = D.getIdentifier(); + if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(), + LookupOrdinaryName, + ForRedeclaration)) { + // The scope should be freshly made just for us. There is just no way + // it contains any previous declaration. + assert(!S->isDeclScope(PrevDecl)); + if (PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + } + } + + if (D.getCXXScopeSpec().isSet() && !Invalid) { + Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator) + << D.getCXXScopeSpec().getRange(); + Invalid = true; + } + + VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier()); + if (Invalid) + ExDecl->setInvalidDecl(); + + // Add the exception declaration into this scope. + if (II) + PushOnScopeChains(ExDecl, S); + else + CurContext->addDecl(ExDecl); + + ProcessDeclAttributes(S, ExDecl, D); + return ExDecl; +} + +Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, + Expr *AssertExpr, + Expr *AssertMessageExpr_, + SourceLocation RParenLoc) { + StringLiteral *AssertMessage = cast<StringLiteral>(AssertMessageExpr_); + + if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent()) { + llvm::APSInt Value(32); + if (!AssertExpr->isIntegerConstantExpr(Value, Context)) { + Diag(StaticAssertLoc, + diag::err_static_assert_expression_is_not_constant) << + AssertExpr->getSourceRange(); + return 0; + } + + if (Value == 0) { + Diag(StaticAssertLoc, diag::err_static_assert_failed) + << AssertMessage->getString() << AssertExpr->getSourceRange(); + } + } + + if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression)) + return 0; + + Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, + AssertExpr, AssertMessage, RParenLoc); + + CurContext->addDecl(Decl); + return Decl; +} + +/// \brief Perform semantic analysis of the given friend type declaration. +/// +/// \returns A friend declaration that. +FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation FriendLoc, + TypeSourceInfo *TSInfo) { + assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); + + QualType T = TSInfo->getType(); + SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange(); + + if (!getLangOptions().CPlusPlus0x) { + // C++03 [class.friend]p2: + // An elaborated-type-specifier shall be used in a friend declaration + // for a class.* + // + // * The class-key of the elaborated-type-specifier is required. + if (!ActiveTemplateInstantiations.empty()) { + // Do not complain about the form of friend template types during + // template instantiation; we will already have complained when the + // template was declared. + } else if (!T->isElaboratedTypeSpecifier()) { + // If we evaluated the type to a record type, suggest putting + // a tag in front. + if (const RecordType *RT = T->getAs<RecordType>()) { + RecordDecl *RD = RT->getDecl(); + + std::string InsertionText = std::string(" ") + RD->getKindName(); + + Diag(TypeRange.getBegin(), diag::ext_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + InsertionText); + } else { + Diag(FriendLoc, diag::ext_nonclass_type_friend) + << T + << SourceRange(FriendLoc, TypeRange.getEnd()); + } + } else if (T->getAs<EnumType>()) { + Diag(FriendLoc, diag::ext_enum_friend) + << T + << SourceRange(FriendLoc, TypeRange.getEnd()); + } + } + + // C++0x [class.friend]p3: + // If the type specifier in a friend declaration designates a (possibly + // cv-qualified) class type, that class is declared as a friend; otherwise, + // the friend declaration is ignored. + + // FIXME: C++0x has some syntactic restrictions on friend type declarations + // in [class.friend]p3 that we do not implement. + + return FriendDecl::Create(Context, CurContext, FriendLoc, TSInfo, FriendLoc); +} + +/// Handle a friend tag declaration where the scope specifier was +/// templated. +Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, + unsigned TagSpec, SourceLocation TagLoc, + CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, + MultiTemplateParamsArg TempParamLists) { + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + + bool isExplicitSpecialization = false; + bool Invalid = false; + + if (TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS, + TempParamLists.get(), + TempParamLists.size(), + /*friend*/ true, + isExplicitSpecialization, + Invalid)) { + if (TemplateParams->size() > 0) { + // This is a declaration of a class template. + if (Invalid) + return 0; + + return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, + SS, Name, NameLoc, Attr, + TemplateParams, AS_public, + TempParamLists.size() - 1, + (TemplateParameterList**) TempParamLists.release()).take(); + } else { + // The "template<>" header is extraneous. + Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) + << TypeWithKeyword::getTagTypeKindName(Kind) << Name; + isExplicitSpecialization = true; + } + } + + if (Invalid) return 0; + + assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); + + bool isAllExplicitSpecializations = true; + for (unsigned I = TempParamLists.size(); I-- > 0; ) { + if (TempParamLists.get()[I]->size()) { + isAllExplicitSpecializations = false; + break; + } + } + + // FIXME: don't ignore attributes. + + // If it's explicit specializations all the way down, just forget + // about the template header and build an appropriate non-templated + // friend. TODO: for source fidelity, remember the headers. + if (isAllExplicitSpecializations) { + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTagTypeKind(Kind); + QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, + *Name, NameLoc); + if (T.isNull()) + return 0; + + TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); + if (isa<DependentNameType>(T)) { + DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + TL.setKeywordLoc(TagLoc); + TL.setQualifierLoc(QualifierLoc); + TL.setNameLoc(NameLoc); + } else { + ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); + TL.setKeywordLoc(TagLoc); + TL.setQualifierLoc(QualifierLoc); + cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc); + } + + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, + TSI, FriendLoc); + Friend->setAccess(AS_public); + CurContext->addDecl(Friend); + return Friend; + } + + // Handle the case of a templated-scope friend class. e.g. + // template <class T> class A<T>::B; + // FIXME: we don't support these right now. + ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); + QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); + TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); + DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + TL.setKeywordLoc(TagLoc); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameLoc); + + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, + TSI, FriendLoc); + Friend->setAccess(AS_public); + Friend->setUnsupportedFriend(true); + CurContext->addDecl(Friend); + return Friend; +} + + +/// Handle a friend type declaration. This works in tandem with +/// ActOnTag. +/// +/// Notes on friend class templates: +/// +/// We generally treat friend class declarations as if they were +/// declaring a class. So, for example, the elaborated type specifier +/// in a friend declaration is required to obey the restrictions of a +/// class-head (i.e. no typedefs in the scope chain), template +/// parameters are required to match up with simple template-ids, &c. +/// However, unlike when declaring a template specialization, it's +/// okay to refer to a template specialization without an empty +/// template parameter declaration, e.g. +/// friend class A<T>::B<unsigned>; +/// We permit this as a special case; if there are any template +/// parameters present at all, require proper matching, i.e. +/// template <> template <class T> friend class A<int>::B; +Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, + MultiTemplateParamsArg TempParams) { + SourceLocation Loc = DS.getSourceRange().getBegin(); + + assert(DS.isFriendSpecified()); + assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); + + // Try to convert the decl specifier to a type. This works for + // friend templates because ActOnTag never produces a ClassTemplateDecl + // for a TUK_Friend. + Declarator TheDeclarator(DS, Declarator::MemberContext); + TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); + QualType T = TSI->getType(); + if (TheDeclarator.isInvalidType()) + return 0; + + if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration)) + return 0; + + // This is definitely an error in C++98. It's probably meant to + // be forbidden in C++0x, too, but the specification is just + // poorly written. + // + // The problem is with declarations like the following: + // template <T> friend A<T>::foo; + // where deciding whether a class C is a friend or not now hinges + // on whether there exists an instantiation of A that causes + // 'foo' to equal C. There are restrictions on class-heads + // (which we declare (by fiat) elaborated friend declarations to + // be) that makes this tractable. + // + // FIXME: handle "template <> friend class A<T>;", which + // is possibly well-formed? Who even knows? + if (TempParams.size() && !T->isElaboratedTypeSpecifier()) { + Diag(Loc, diag::err_tagless_friend_type_template) + << DS.getSourceRange(); + return 0; + } + + // C++98 [class.friend]p1: A friend of a class is a function + // or class that is not a member of the class . . . + // This is fixed in DR77, which just barely didn't make the C++03 + // deadline. It's also a very silly restriction that seriously + // affects inner classes and which nobody else seems to implement; + // thus we never diagnose it, not even in -pedantic. + // + // But note that we could warn about it: it's always useless to + // friend one of your own members (it's not, however, worthless to + // friend a member of an arbitrary specialization of your template). + + Decl *D; + if (unsigned NumTempParamLists = TempParams.size()) + D = FriendTemplateDecl::Create(Context, CurContext, Loc, + NumTempParamLists, + TempParams.release(), + TSI, + DS.getFriendSpecLoc()); + else + D = CheckFriendTypeDecl(DS.getFriendSpecLoc(), TSI); + + if (!D) + return 0; + + D->setAccess(AS_public); + CurContext->addDecl(D); + + return D; +} + +Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, + MultiTemplateParamsArg TemplateParams) { + const DeclSpec &DS = D.getDeclSpec(); + + assert(DS.isFriendSpecified()); + assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); + + SourceLocation Loc = D.getIdentifierLoc(); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + + // C++ [class.friend]p1 + // A friend of a class is a function or class.... + // Note that this sees through typedefs, which is intended. + // It *doesn't* see through dependent types, which is correct + // according to [temp.arg.type]p3: + // If a declaration acquires a function type through a + // type dependent on a template-parameter and this causes + // a declaration that does not use the syntactic form of a + // function declarator to have a function type, the program + // is ill-formed. + if (!T->isFunctionType()) { + Diag(Loc, diag::err_unexpected_friend); + + // It might be worthwhile to try to recover by creating an + // appropriate declaration. + return 0; + } + + // C++ [namespace.memdef]p3 + // - If a friend declaration in a non-local class first declares a + // class or function, the friend class or function is a member + // of the innermost enclosing namespace. + // - The name of the friend is not found by simple name lookup + // until a matching declaration is provided in that namespace + // scope (either before or after the class declaration granting + // friendship). + // - If a friend function is called, its name may be found by the + // name lookup that considers functions from namespaces and + // classes associated with the types of the function arguments. + // - When looking for a prior declaration of a class or a function + // declared as a friend, scopes outside the innermost enclosing + // namespace scope are not considered. + + CXXScopeSpec &SS = D.getCXXScopeSpec(); + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + assert(Name); + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) || + DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) || + DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration)) + return 0; + + // The context we found the declaration in, or in which we should + // create the declaration. + DeclContext *DC; + Scope *DCScope = S; + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, + ForRedeclaration); + + // FIXME: there are different rules in local classes + + // There are four cases here. + // - There's no scope specifier, in which case we just go to the + // appropriate scope and look for a function or function template + // there as appropriate. + // Recover from invalid scope qualifiers as if they just weren't there. + if (SS.isInvalid() || !SS.isSet()) { + // C++0x [namespace.memdef]p3: + // If the name in a friend declaration is neither qualified nor + // a template-id and the declaration is a function or an + // elaborated-type-specifier, the lookup to determine whether + // the entity has been previously declared shall not consider + // any scopes outside the innermost enclosing namespace. + // C++0x [class.friend]p11: + // If a friend declaration appears in a local class and the name + // specified is an unqualified name, a prior declaration is + // looked up without considering scopes that are outside the + // innermost enclosing non-class scope. For a friend function + // declaration, if there is no prior declaration, the program is + // ill-formed. + bool isLocal = cast<CXXRecordDecl>(CurContext)->isLocalClass(); + bool isTemplateId = D.getName().getKind() == UnqualifiedId::IK_TemplateId; + + // Find the appropriate context according to the above. + DC = CurContext; + while (true) { + // Skip class contexts. If someone can cite chapter and verse + // for this behavior, that would be nice --- it's what GCC and + // EDG do, and it seems like a reasonable intent, but the spec + // really only says that checks for unqualified existing + // declarations should stop at the nearest enclosing namespace, + // not that they should only consider the nearest enclosing + // namespace. + while (DC->isRecord()) + DC = DC->getParent(); + + LookupQualifiedName(Previous, DC); + + // TODO: decide what we think about using declarations. + if (isLocal || !Previous.empty()) + break; + + if (isTemplateId) { + if (isa<TranslationUnitDecl>(DC)) break; + } else { + if (DC->isFileContext()) break; + } + DC = DC->getParent(); + } + + // C++ [class.friend]p1: A friend of a class is a function or + // class that is not a member of the class . . . + // C++0x changes this for both friend types and functions. + // Most C++ 98 compilers do seem to give an error here, so + // we do, too. + if (!Previous.empty() && DC->Equals(CurContext) + && !getLangOptions().CPlusPlus0x) + Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + + DCScope = getScopeForDeclContext(S, DC); + + // - There's a non-dependent scope specifier, in which case we + // compute it and do a previous lookup there for a function + // or function template. + } else if (!SS.getScopeRep()->isDependent()) { + DC = computeDeclContext(SS); + if (!DC) return 0; + + if (RequireCompleteDeclContext(SS, DC)) return 0; + + LookupQualifiedName(Previous, DC); + + // Ignore things found implicitly in the wrong scope. + // TODO: better diagnostics for this case. Suggesting the right + // qualified scope would be nice... + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (!DC->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) + F.erase(); + } + F.done(); + + if (Previous.empty()) { + D.setInvalidType(); + Diag(Loc, diag::err_qualified_friend_not_found) << Name << T; + return 0; + } + + // C++ [class.friend]p1: A friend of a class is a function or + // class that is not a member of the class . . . + if (DC->Equals(CurContext)) + Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member); + + // - There's a scope specifier that does not match any template + // parameter lists, in which case we use some arbitrary context, + // create a method or method template, and wait for instantiation. + // - There's a scope specifier that does match some template + // parameter lists, which we don't handle right now. + } else { + DC = CurContext; + assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?"); + } + + if (!DC->isRecord()) { + // This implies that it has to be an operator or function. + if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || + D.getName().getKind() == UnqualifiedId::IK_DestructorName || + D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) { + Diag(Loc, diag::err_introducing_special_friend) << + (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 : + D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2); + return 0; + } + } + + bool Redeclaration = false; + NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, T, TInfo, Previous, + move(TemplateParams), + IsDefinition, + Redeclaration); + if (!ND) return 0; + + assert(ND->getDeclContext() == DC); + assert(ND->getLexicalDeclContext() == CurContext); + + // Add the function declaration to the appropriate lookup tables, + // adjusting the redeclarations list as necessary. We don't + // want to do this yet if the friending class is dependent. + // + // Also update the scope-based lookup if the target context's + // lookup context is in lexical scope. + if (!CurContext->isDependentContext()) { + DC = DC->getRedeclContext(); + DC->makeDeclVisibleInContext(ND, /* Recoverable=*/ false); + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); + } + + FriendDecl *FrD = FriendDecl::Create(Context, CurContext, + D.getIdentifierLoc(), ND, + DS.getFriendSpecLoc()); + FrD->setAccess(AS_public); + CurContext->addDecl(FrD); + + if (ND->isInvalidDecl()) + FrD->setInvalidDecl(); + else { + FunctionDecl *FD; + if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + FD = FTD->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(ND); + + // Mark templated-scope function declarations as unsupported. + if (FD->getNumTemplateParameterLists()) + FrD->setUnsupportedFriend(true); + } + + return ND; +} + +void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { + AdjustDeclIfTemplate(Dcl); + + FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl); + if (!Fn) { + Diag(DelLoc, diag::err_deleted_non_function); + return; + } + if (const FunctionDecl *Prev = Fn->getPreviousDeclaration()) { + Diag(DelLoc, diag::err_deleted_decl_not_first); + Diag(Prev->getLocation(), diag::note_previous_declaration); + // If the declaration wasn't the first, we delete the function anyway for + // recovery. + } + Fn->setDeletedAsWritten(); +} + +void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); + + if (MD) { + if (MD->getParent()->isDependentType()) { + MD->setDefaulted(); + MD->setExplicitlyDefaulted(); + return; + } + + CXXSpecialMember Member = getSpecialMember(MD); + if (Member == CXXInvalid) { + Diag(DefaultLoc, diag::err_default_special_members); + return; + } + + MD->setDefaulted(); + MD->setExplicitlyDefaulted(); + + // If this definition appears within the record, do the checking when + // the record is complete. + const FunctionDecl *Primary = MD; + if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + // Find the uninstantiated declaration that actually had the '= default' + // on it. + MD->getTemplateInstantiationPattern()->isDefined(Primary); + + if (Primary == Primary->getCanonicalDecl()) + return; + + switch (Member) { + case CXXDefaultConstructor: { + CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); + CheckExplicitlyDefaultedDefaultConstructor(CD); + if (!CD->isInvalidDecl()) + DefineImplicitDefaultConstructor(DefaultLoc, CD); + break; + } + + case CXXCopyConstructor: { + CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); + CheckExplicitlyDefaultedCopyConstructor(CD); + if (!CD->isInvalidDecl()) + DefineImplicitCopyConstructor(DefaultLoc, CD); + break; + } + + case CXXCopyAssignment: { + CheckExplicitlyDefaultedCopyAssignment(MD); + if (!MD->isInvalidDecl()) + DefineImplicitCopyAssignment(DefaultLoc, MD); + break; + } + + case CXXDestructor: { + CXXDestructorDecl *DD = cast<CXXDestructorDecl>(MD); + CheckExplicitlyDefaultedDestructor(DD); + if (!DD->isInvalidDecl()) + DefineImplicitDestructor(DefaultLoc, DD); + break; + } + + case CXXMoveConstructor: + case CXXMoveAssignment: + Diag(Dcl->getLocation(), diag::err_defaulted_move_unsupported); + break; + + default: + // FIXME: Do the rest once we have move functions + break; + } + } else { + Diag(DefaultLoc, diag::err_default_special_members); + } +} + +static void SearchForReturnInStmt(Sema &Self, Stmt *S) { + for (Stmt::child_range CI = S->children(); CI; ++CI) { + Stmt *SubStmt = *CI; + if (!SubStmt) + continue; + if (isa<ReturnStmt>(SubStmt)) + Self.Diag(SubStmt->getSourceRange().getBegin(), + diag::err_return_in_constructor_handler); + if (!isa<Expr>(SubStmt)) + SearchForReturnInStmt(Self, SubStmt); + } +} + +void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { + for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) { + CXXCatchStmt *Handler = TryBlock->getHandler(I); + SearchForReturnInStmt(*this, Handler); + } +} + +bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType(); + QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType(); + + if (Context.hasSameType(NewTy, OldTy) || + NewTy->isDependentType() || OldTy->isDependentType()) + return false; + + // Check if the return types are covariant + QualType NewClassTy, OldClassTy; + + /// Both types must be pointers or references to classes. + if (const PointerType *NewPT = NewTy->getAs<PointerType>()) { + if (const PointerType *OldPT = OldTy->getAs<PointerType>()) { + NewClassTy = NewPT->getPointeeType(); + OldClassTy = OldPT->getPointeeType(); + } + } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) { + if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) { + if (NewRT->getTypeClass() == OldRT->getTypeClass()) { + NewClassTy = NewRT->getPointeeType(); + OldClassTy = OldRT->getPointeeType(); + } + } + } + + // The return types aren't either both pointers or references to a class type. + if (NewClassTy.isNull()) { + Diag(New->getLocation(), + diag::err_different_return_type_for_overriding_virtual_function) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + + return true; + } + + // C++ [class.virtual]p6: + // If the return type of D::f differs from the return type of B::f, the + // class type in the return type of D::f shall be complete at the point of + // declaration of D::f or shall be the class type D. + if (const RecordType *RT = NewClassTy->getAs<RecordType>()) { + if (!RT->isBeingDefined() && + RequireCompleteType(New->getLocation(), NewClassTy, + PDiag(diag::err_covariant_return_incomplete) + << New->getDeclName())) + return true; + } + + if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { + // Check if the new class derives from the old class. + if (!IsDerivedFrom(NewClassTy, OldClassTy)) { + Diag(New->getLocation(), + diag::err_covariant_return_not_derived) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + } + + // Check if we the conversion from derived to base is valid. + if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, + diag::err_covariant_return_inaccessible_base, + diag::err_covariant_return_ambiguous_derived_to_base_conv, + // FIXME: Should this point to the return type? + New->getLocation(), SourceRange(), New->getDeclName(), 0)) { + // FIXME: this note won't trigger for delayed access control + // diagnostics, and it's impossible to get an undelayed error + // here from access control during the original parse because + // the ParsingDeclSpec/ParsingDeclarator are still in scope. + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + } + } + + // The qualifiers of the return types must be the same. + if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) { + Diag(New->getLocation(), + diag::err_covariant_return_type_different_qualifications) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + }; + + + // The new class type must have the same or less qualifiers as the old type. + if (NewClassTy.isMoreQualifiedThan(OldClassTy)) { + Diag(New->getLocation(), + diag::err_covariant_return_type_class_type_more_qualified) + << New->getDeclName() << NewTy << OldTy; + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + }; + + return false; +} + +/// \brief Mark the given method pure. +/// +/// \param Method the method to be marked pure. +/// +/// \param InitRange the source range that covers the "0" initializer. +bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { + SourceLocation EndLoc = InitRange.getEnd(); + if (EndLoc.isValid()) + Method->setRangeEnd(EndLoc); + + if (Method->isVirtual() || Method->getParent()->isDependentContext()) { + Method->setPure(); + return false; + } + + if (!Method->isInvalidDecl()) + Diag(Method->getLocation(), diag::err_non_virtual_pure) + << Method->getDeclName() << InitRange; + return true; +} + +/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse +/// an initializer for the out-of-line declaration 'Dcl'. The scope +/// is a fresh scope pushed for just this purpose. +/// +/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a +/// static data member of class X, names should be looked up in the scope of +/// class X. +void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { + // If there is no declaration, there was an error parsing it. + if (D == 0 || D->isInvalidDecl()) return; + + // We should only get called for declarations with scope specifiers, like: + // int foo::bar; + assert(D->isOutOfLine()); + EnterDeclaratorContext(S, D->getDeclContext()); +} + +/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an +/// initializer for the out-of-line declaration 'D'. +void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { + // If there is no declaration, there was an error parsing it. + if (D == 0 || D->isInvalidDecl()) return; + + assert(D->isOutOfLine()); + ExitDeclaratorContext(S); +} + +/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a +/// C++ if/switch/while/for statement. +/// e.g: "if (int x = f()) {...}" +DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { + // C++ 6.4p2: + // The declarator shall not specify a function or an array. + // The type-specifier-seq shall not contain typedef and shall not declare a + // new class or enumeration. + assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + "Parser allowed 'typedef' as storage class of condition decl."); + + TagDecl *OwnedTag = 0; + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag); + QualType Ty = TInfo->getType(); + + if (Ty->isFunctionType()) { // The declarator shall not specify a function... + // We exit without creating a CXXConditionDeclExpr because a FunctionDecl + // would be created and CXXConditionDeclExpr wants a VarDecl. + Diag(D.getIdentifierLoc(), diag::err_invalid_use_of_function_type) + << D.getSourceRange(); + return DeclResult(); + } else if (OwnedTag && OwnedTag->isDefinition()) { + // The type-specifier-seq shall not declare a new class or enumeration. + Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition); + } + + Decl *Dcl = ActOnDeclarator(S, D); + if (!Dcl) + return DeclResult(); + + return Dcl; +} + +void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, + bool DefinitionRequired) { + // Ignore any vtable uses in unevaluated operands or for classes that do + // not have a vtable. + if (!Class->isDynamicClass() || Class->isDependentContext() || + CurContext->isDependentContext() || + ExprEvalContexts.back().Context == Unevaluated) + return; + + // Try to insert this class into the map. + Class = cast<CXXRecordDecl>(Class->getCanonicalDecl()); + std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool> + Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired)); + if (!Pos.second) { + // If we already had an entry, check to see if we are promoting this vtable + // to required a definition. If so, we need to reappend to the VTableUses + // list, since we may have already processed the first entry. + if (DefinitionRequired && !Pos.first->second) { + Pos.first->second = true; + } else { + // Otherwise, we can early exit. + return; + } + } + + // Local classes need to have their virtual members marked + // immediately. For all other classes, we mark their virtual members + // at the end of the translation unit. + if (Class->isLocalClass()) + MarkVirtualMembersReferenced(Loc, Class); + else + VTableUses.push_back(std::make_pair(Class, Loc)); +} + +bool Sema::DefineUsedVTables() { + if (VTableUses.empty()) + return false; + + // Note: The VTableUses vector could grow as a result of marking + // the members of a class as "used", so we check the size each + // time through the loop and prefer indices (with are stable) to + // iterators (which are not). + bool DefinedAnything = false; + for (unsigned I = 0; I != VTableUses.size(); ++I) { + CXXRecordDecl *Class = VTableUses[I].first->getDefinition(); + if (!Class) + continue; + + SourceLocation Loc = VTableUses[I].second; + + // If this class has a key function, but that key function is + // defined in another translation unit, we don't need to emit the + // vtable even though we're using it. + const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class); + if (KeyFunction && !KeyFunction->hasBody()) { + switch (KeyFunction->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + // The key function is in another translation unit. + continue; + + case TSK_ExplicitInstantiationDefinition: + case TSK_ImplicitInstantiation: + // We will be instantiating the key function. + break; + } + } else if (!KeyFunction) { + // If we have a class with no key function that is the subject + // of an explicit instantiation declaration, suppress the + // vtable; it will live with the explicit instantiation + // definition. + bool IsExplicitInstantiationDeclaration + = Class->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDeclaration; + for (TagDecl::redecl_iterator R = Class->redecls_begin(), + REnd = Class->redecls_end(); + R != REnd; ++R) { + TemplateSpecializationKind TSK + = cast<CXXRecordDecl>(*R)->getTemplateSpecializationKind(); + if (TSK == TSK_ExplicitInstantiationDeclaration) + IsExplicitInstantiationDeclaration = true; + else if (TSK == TSK_ExplicitInstantiationDefinition) { + IsExplicitInstantiationDeclaration = false; + break; + } + } + + if (IsExplicitInstantiationDeclaration) + continue; + } + + // Mark all of the virtual members of this class as referenced, so + // that we can build a vtable. Then, tell the AST consumer that a + // vtable for this class is required. + DefinedAnything = true; + MarkVirtualMembersReferenced(Loc, Class); + CXXRecordDecl *Canonical = cast<CXXRecordDecl>(Class->getCanonicalDecl()); + Consumer.HandleVTable(Class, VTablesUsed[Canonical]); + + // Optionally warn if we're emitting a weak vtable. + if (Class->getLinkage() == ExternalLinkage && + Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { + if (!KeyFunction || (KeyFunction->hasBody() && KeyFunction->isInlined())) + Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; + } + } + VTableUses.clear(); + + return DefinedAnything; +} + +void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, + const CXXRecordDecl *RD) { + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); i != e; ++i) { + CXXMethodDecl *MD = *i; + + // C++ [basic.def.odr]p2: + // [...] A virtual member function is used if it is not pure. [...] + if (MD->isVirtual() && !MD->isPure()) + MarkDeclarationReferenced(Loc, MD); + } + + // Only classes that have virtual bases need a VTT. + if (RD->getNumVBases() == 0) + return; + + for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), + e = RD->bases_end(); i != e; ++i) { + const CXXRecordDecl *Base = + cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); + if (Base->getNumVBases() == 0) + continue; + MarkVirtualMembersReferenced(Loc, Base); + } +} + +/// SetIvarInitializers - This routine builds initialization ASTs for the +/// Objective-C implementation whose ivars need be initialized. +void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { + if (!getLangOptions().CPlusPlus) + return; + if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { + llvm::SmallVector<ObjCIvarDecl*, 8> ivars; + CollectIvarsToConstructOrDestruct(OID, ivars); + if (ivars.empty()) + return; + llvm::SmallVector<CXXCtorInitializer*, 32> AllToInit; + for (unsigned i = 0; i < ivars.size(); i++) { + FieldDecl *Field = ivars[i]; + if (Field->isInvalidDecl()) + continue; + + CXXCtorInitializer *Member; + InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); + InitializationKind InitKind = + InitializationKind::CreateDefault(ObjCImplementation->getLocation()); + + InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0); + ExprResult MemberInit = + InitSeq.Perform(*this, InitEntity, InitKind, MultiExprArg()); + MemberInit = MaybeCreateExprWithCleanups(MemberInit); + // Note, MemberInit could actually come back empty if no initialization + // is required (e.g., because it would call a trivial default constructor) + if (!MemberInit.get() || MemberInit.isInvalid()) + continue; + + Member = + new (Context) CXXCtorInitializer(Context, Field, SourceLocation(), + SourceLocation(), + MemberInit.takeAs<Expr>(), + SourceLocation()); + AllToInit.push_back(Member); + + // Be sure that the destructor is accessible and is marked as referenced. + if (const RecordType *RecordTy + = Context.getBaseElementType(Field->getType()) + ->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); + if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { + MarkDeclarationReferenced(Field->getLocation(), Destructor); + CheckDestructorAccess(Field->getLocation(), Destructor, + PDiag(diag::err_access_dtor_ivar) + << Context.getBaseElementType(Field->getType())); + } + } + } + ObjCImplementation->setIvarInitializers(Context, + AllToInit.data(), AllToInit.size()); + } +} + +static +void DelegatingCycleHelper(CXXConstructorDecl* Ctor, + llvm::SmallSet<CXXConstructorDecl*, 4> &Valid, + llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid, + llvm::SmallSet<CXXConstructorDecl*, 4> &Current, + Sema &S) { + llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(), + CE = Current.end(); + if (Ctor->isInvalidDecl()) + return; + + const FunctionDecl *FNTarget = 0; + CXXConstructorDecl *Target; + + // We ignore the result here since if we don't have a body, Target will be + // null below. + (void)Ctor->getTargetConstructor()->hasBody(FNTarget); + Target += const_cast<CXXConstructorDecl*>(cast_or_null<CXXConstructorDecl>(FNTarget)); + + CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(), + // Avoid dereferencing a null pointer here. + *TCanonical = Target ? Target->getCanonicalDecl() : 0; + + if (!Current.insert(Canonical)) + return; + + // We know that beyond here, we aren't chaining into a cycle. + if (!Target || !Target->isDelegatingConstructor() || + Target->isInvalidDecl() || Valid.count(TCanonical)) { + for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) + Valid.insert(*CI); + Current.clear(); + // We've hit a cycle. + } else if (TCanonical == Canonical || Invalid.count(TCanonical) || + Current.count(TCanonical)) { + // If we haven't diagnosed this cycle yet, do so now. + if (!Invalid.count(TCanonical)) { + S.Diag((*Ctor->init_begin())->getSourceLocation(), + diag::warn_delegating_ctor_cycle) + << Ctor; + + // Don't add a note for a function delegating directo to itself. + if (TCanonical != Canonical) + S.Diag(Target->getLocation(), diag::note_it_delegates_to); + + CXXConstructorDecl *C = Target; + while (C->getCanonicalDecl() != Canonical) { + (void)C->getTargetConstructor()->hasBody(FNTarget); + assert(FNTarget && "Ctor cycle through bodiless function"); + + C + = const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget)); + S.Diag(C->getLocation(), diag::note_which_delegates_to); + } + } + + for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI) + Invalid.insert(*CI); + Current.clear(); + } else { + DelegatingCycleHelper(Target, Valid, Invalid, Current, S); + } +} + + +void Sema::CheckDelegatingCtorCycles() { + llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current; + + llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(), + CE = Current.end(); + + for (llvm::SmallVector<CXXConstructorDecl*, 4>::iterator + I = DelegatingCtorDecls.begin(), + E = DelegatingCtorDecls.end(); + I != E; ++I) { + DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); + } + + for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) + (*CI)->setInvalidDecl(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp new file mode 100644 index 0000000..de9097e --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -0,0 +1,2333 @@ +//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for Objective C declarations. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#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" +#include "clang/Sema/DeclSpec.h" +#include "llvm/ADT/DenseSet.h" + +using namespace clang; + +bool Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, + const ObjCMethodDecl *Overridden, + bool IsImplementation) { + if (Overridden->hasRelatedResultType() && + !NewMethod->hasRelatedResultType()) { + // This can only happen when the method follows a naming convention that + // implies a related result type, and the original (overridden) method has + // a suitable return type, but the new (overriding) method does not have + // a suitable return type. + QualType ResultType = NewMethod->getResultType(); + SourceRange ResultTypeRange; + if (const TypeSourceInfo *ResultTypeInfo + = NewMethod->getResultTypeSourceInfo()) + ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange(); + + // Figure out which class this method is part of, if any. + ObjCInterfaceDecl *CurrentClass + = dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext()); + if (!CurrentClass) { + DeclContext *DC = NewMethod->getDeclContext(); + if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(DC)) + CurrentClass = Cat->getClassInterface(); + else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(DC)) + CurrentClass = Impl->getClassInterface(); + else if (ObjCCategoryImplDecl *CatImpl + = dyn_cast<ObjCCategoryImplDecl>(DC)) + CurrentClass = CatImpl->getClassInterface(); + } + + if (CurrentClass) { + Diag(NewMethod->getLocation(), + diag::warn_related_result_type_compatibility_class) + << Context.getObjCInterfaceType(CurrentClass) + << ResultType + << ResultTypeRange; + } else { + Diag(NewMethod->getLocation(), + diag::warn_related_result_type_compatibility_protocol) + << ResultType + << ResultTypeRange; + } + + Diag(Overridden->getLocation(), diag::note_related_result_type_overridden) + << Overridden->getMethodFamily(); + } + + return false; +} + + +static bool CheckObjCMethodOverrides(Sema &S, ObjCMethodDecl *NewMethod, + DeclContext *DC, + bool SkipCurrent = true) { + if (!DC) + return false; + + if (!SkipCurrent) { + // Look for this method. If we find it, we're done. + Selector Sel = NewMethod->getSelector(); + bool IsInstance = NewMethod->isInstanceMethod(); + DeclContext::lookup_const_iterator Meth, MethEnd; + for (llvm::tie(Meth, MethEnd) = DC->lookup(Sel); Meth != MethEnd; ++Meth) { + ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); + if (MD && MD->isInstanceMethod() == IsInstance) + return S.CheckObjCMethodOverride(NewMethod, MD, false); + } + } + + if (ObjCInterfaceDecl *Class = llvm::dyn_cast<ObjCInterfaceDecl>(DC)) { + // Look through categories. + for (ObjCCategoryDecl *Category = Class->getCategoryList(); + Category; Category = Category->getNextClassCategory()) { + if (CheckObjCMethodOverrides(S, NewMethod, Category, false)) + return true; + } + + // Look through protocols. + for (ObjCList<ObjCProtocolDecl>::iterator I = Class->protocol_begin(), + IEnd = Class->protocol_end(); + I != IEnd; ++I) + if (CheckObjCMethodOverrides(S, NewMethod, *I, false)) + return true; + + // Look in our superclass. + return CheckObjCMethodOverrides(S, NewMethod, Class->getSuperClass(), + false); + } + + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(DC)) { + // Look through protocols. + for (ObjCList<ObjCProtocolDecl>::iterator I = Category->protocol_begin(), + IEnd = Category->protocol_end(); + I != IEnd; ++I) + if (CheckObjCMethodOverrides(S, NewMethod, *I, false)) + return true; + + return false; + } + + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(DC)) { + // Look through protocols. + for (ObjCList<ObjCProtocolDecl>::iterator I = Protocol->protocol_begin(), + IEnd = Protocol->protocol_end(); + I != IEnd; ++I) + if (CheckObjCMethodOverrides(S, NewMethod, *I, false)) + return true; + + return false; + } + + return false; +} + +bool Sema::CheckObjCMethodOverrides(ObjCMethodDecl *NewMethod, + DeclContext *DC) { + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(DC)) + return ::CheckObjCMethodOverrides(*this, NewMethod, Class); + + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(DC)) + return ::CheckObjCMethodOverrides(*this, NewMethod, Category); + + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(DC)) + return ::CheckObjCMethodOverrides(*this, NewMethod, Protocol); + + if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(DC)) + return ::CheckObjCMethodOverrides(*this, NewMethod, + Impl->getClassInterface()); + + if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(DC)) + return ::CheckObjCMethodOverrides(*this, NewMethod, + CatImpl->getClassInterface()); + + return ::CheckObjCMethodOverrides(*this, NewMethod, CurContext); +} + +static void DiagnoseObjCImplementedDeprecations(Sema &S, + NamedDecl *ND, + SourceLocation ImplLoc, + int select) { + if (ND && ND->isDeprecated()) { + S.Diag(ImplLoc, diag::warn_deprecated_def) << select; + if (select == 0) + S.Diag(ND->getLocation(), diag::note_method_declared_at); + else + S.Diag(ND->getLocation(), diag::note_previous_decl) << "class"; + } +} + +/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible +/// and user declared, in the method definition's AST. +void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { + assert(getCurMethodDecl() == 0 && "Method parsing confused"); + ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D); + + // If we don't have a valid method decl, simply return. + if (!MDecl) + return; + + // Allow the rest of sema to find private method decl implementations. + if (MDecl->isInstanceMethod()) + AddInstanceMethodToGlobalPool(MDecl, true); + else + AddFactoryMethodToGlobalPool(MDecl, true); + + // Allow all of Sema to see that we are entering a method definition. + PushDeclContext(FnBodyScope, MDecl); + PushFunctionScope(); + + // Create Decl objects for each parameter, entrring them in the scope for + // binding to their use. + + // Insert the invisible arguments, self and _cmd! + MDecl->createImplicitParams(Context, MDecl->getClassInterface()); + + PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); + PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); + + // Introduce all of the other parameters into this scope. + for (ObjCMethodDecl::param_iterator PI = MDecl->param_begin(), + E = MDecl->param_end(); PI != E; ++PI) { + ParmVarDecl *Param = (*PI); + if (!Param->isInvalidDecl() && + RequireCompleteType(Param->getLocation(), Param->getType(), + diag::err_typecheck_decl_incomplete_type)) + Param->setInvalidDecl(); + if ((*PI)->getIdentifier()) + PushOnScopeChains(*PI, FnBodyScope); + } + // Warn on implementating deprecated methods under + // -Wdeprecated-implementations flag. + if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) + if (ObjCMethodDecl *IMD = + IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod())) + DiagnoseObjCImplementedDeprecations(*this, + dyn_cast<NamedDecl>(IMD), + MDecl->getLocation(), 0); +} + +Decl *Sema:: +ActOnStartClassInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + Decl * const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, AttributeList *AttrList) { + assert(ClassName && "Missing class identifier"); + + // Check for another declaration kind with the same name. + NamedDecl *PrevDecl = LookupSingleName(TUScope, ClassName, ClassLoc, + LookupOrdinaryName, ForRedeclaration); + + if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { + Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } + + ObjCInterfaceDecl* IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + if (IDecl) { + // Class already seen. Is it a forward declaration? + if (!IDecl->isForwardDecl()) { + IDecl->setInvalidDecl(); + Diag(AtInterfaceLoc, diag::err_duplicate_class_def)<<IDecl->getDeclName(); + Diag(IDecl->getLocation(), diag::note_previous_definition); + + // Return the previous class interface. + // FIXME: don't leak the objects passed in! + return IDecl; + } else { + IDecl->setLocation(AtInterfaceLoc); + IDecl->setForwardDecl(false); + IDecl->setClassLoc(ClassLoc); + // If the forward decl was in a PCH, we need to write it again in a + // dependent AST file. + IDecl->setChangedSinceDeserialization(true); + + // Since this ObjCInterfaceDecl was created by a forward declaration, + // we now add it to the DeclContext since it wasn't added before + // (see ActOnForwardClassDeclaration). + IDecl->setLexicalDeclContext(CurContext); + CurContext->addDecl(IDecl); + + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); + } + } else { + IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassName, ClassLoc); + if (AttrList) + ProcessDeclAttributeList(TUScope, IDecl, AttrList); + + PushOnScopeChains(IDecl, TUScope); + } + + if (SuperName) { + // Check if a different kind of symbol declared in this scope. + PrevDecl = LookupSingleName(TUScope, SuperName, SuperLoc, + LookupOrdinaryName); + + if (!PrevDecl) { + // Try to correct for a typo in the superclass name. + LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName); + if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && + (PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) { + Diag(SuperLoc, diag::err_undef_superclass_suggest) + << SuperName << ClassName << PrevDecl->getDeclName(); + Diag(PrevDecl->getLocation(), diag::note_previous_decl) + << PrevDecl->getDeclName(); + } + } + + if (PrevDecl == IDecl) { + Diag(SuperLoc, diag::err_recursive_superclass) + << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); + IDecl->setLocEnd(ClassLoc); + } else { + ObjCInterfaceDecl *SuperClassDecl = + dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + + // Diagnose classes that inherit from deprecated classes. + if (SuperClassDecl) + (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); + + if (PrevDecl && SuperClassDecl == 0) { + // The previous declaration was not a class decl. Check if we have a + // typedef. If we do, get the underlying class type. + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { + QualType T = TDecl->getUnderlyingType(); + if (T->isObjCObjectType()) { + if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) + SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl); + } + } + + // This handles the following case: + // + // typedef int SuperClass; + // @interface MyClass : SuperClass {} @end + // + if (!SuperClassDecl) { + Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } + } + + if (!dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { + if (!SuperClassDecl) + Diag(SuperLoc, diag::err_undef_superclass) + << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); + else if (SuperClassDecl->isForwardDecl()) + Diag(SuperLoc, diag::err_undef_superclass) + << SuperClassDecl->getDeclName() << ClassName + << SourceRange(AtInterfaceLoc, ClassLoc); + } + IDecl->setSuperClass(SuperClassDecl); + IDecl->setSuperClassLoc(SuperLoc); + IDecl->setLocEnd(SuperLoc); + } + } else { // we have a root class. + IDecl->setLocEnd(ClassLoc); + } + + // Check then save referenced protocols. + if (NumProtoRefs) { + IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + ProtoLocs, Context); + IDecl->setLocEnd(EndProtoLoc); + } + + CheckObjCDeclScope(IDecl); + return IDecl; +} + +/// ActOnCompatiblityAlias - this action is called after complete parsing of +/// @compatibility_alias declaration. It sets up the alias relationships. +Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, + IdentifierInfo *AliasName, + SourceLocation AliasLocation, + IdentifierInfo *ClassName, + SourceLocation ClassLocation) { + // Look for previous declaration of alias name + NamedDecl *ADecl = LookupSingleName(TUScope, AliasName, AliasLocation, + LookupOrdinaryName, ForRedeclaration); + if (ADecl) { + if (isa<ObjCCompatibleAliasDecl>(ADecl)) + Diag(AliasLocation, diag::warn_previous_alias_decl); + else + Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; + Diag(ADecl->getLocation(), diag::note_previous_declaration); + return 0; + } + // Check for class declaration + NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, + LookupOrdinaryName, ForRedeclaration); + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null<TypedefNameDecl>(CDeclU)) { + QualType T = TDecl->getUnderlyingType(); + if (T->isObjCObjectType()) { + if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) { + ClassName = IDecl->getIdentifier(); + CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, + LookupOrdinaryName, ForRedeclaration); + } + } + } + ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU); + if (CDecl == 0) { + Diag(ClassLocation, diag::warn_undef_interface) << ClassName; + if (CDeclU) + Diag(CDeclU->getLocation(), diag::note_previous_declaration); + return 0; + } + + // Everything checked out, instantiate a new alias declaration AST. + ObjCCompatibleAliasDecl *AliasDecl = + ObjCCompatibleAliasDecl::Create(Context, CurContext, AtLoc, AliasName, CDecl); + + if (!CheckObjCDeclScope(AliasDecl)) + PushOnScopeChains(AliasDecl, TUScope); + + return AliasDecl; +} + +bool Sema::CheckForwardProtocolDeclarationForCircularDependency( + IdentifierInfo *PName, + SourceLocation &Ploc, SourceLocation PrevLoc, + const ObjCList<ObjCProtocolDecl> &PList) { + + bool res = false; + for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(), + E = PList.end(); I != E; ++I) { + if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), + Ploc)) { + if (PDecl->getIdentifier() == PName) { + Diag(Ploc, diag::err_protocol_has_circular_dependency); + Diag(PrevLoc, diag::note_previous_definition); + res = true; + } + if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, + PDecl->getLocation(), PDecl->getReferencedProtocols())) + res = true; + } + } + return res; +} + +Decl * +Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, + IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, + Decl * const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, + AttributeList *AttrList) { + bool err = false; + // FIXME: Deal with AttrList. + assert(ProtocolName && "Missing protocol identifier"); + ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolName, ProtocolLoc); + if (PDecl) { + // Protocol already seen. Better be a forward protocol declaration + if (!PDecl->isForwardDecl()) { + Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; + Diag(PDecl->getLocation(), diag::note_previous_definition); + // Just return the protocol we already had. + // FIXME: don't leak the objects passed in! + return PDecl; + } + ObjCList<ObjCProtocolDecl> PList; + PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); + err = CheckForwardProtocolDeclarationForCircularDependency( + ProtocolName, ProtocolLoc, PDecl->getLocation(), PList); + + // Make sure the cached decl gets a valid start location. + PDecl->setLocation(AtProtoInterfaceLoc); + PDecl->setForwardDecl(false); + CurContext->addDecl(PDecl); + // Repeat in dependent AST files. + PDecl->setChangedSinceDeserialization(true); + } else { + PDecl = ObjCProtocolDecl::Create(Context, CurContext, + AtProtoInterfaceLoc,ProtocolName); + PushOnScopeChains(PDecl, TUScope); + PDecl->setForwardDecl(false); + } + if (AttrList) + ProcessDeclAttributeList(TUScope, PDecl, AttrList); + if (!err && NumProtoRefs ) { + /// Check then save referenced protocols. + PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + ProtoLocs, Context); + PDecl->setLocEnd(EndProtoLoc); + } + + CheckObjCDeclScope(PDecl); + return PDecl; +} + +/// FindProtocolDeclaration - This routine looks up protocols and +/// issues an error if they are not declared. It returns list of +/// protocol declarations in its 'Protocols' argument. +void +Sema::FindProtocolDeclaration(bool WarnOnDeclarations, + const IdentifierLocPair *ProtocolId, + unsigned NumProtocols, + llvm::SmallVectorImpl<Decl *> &Protocols) { + for (unsigned i = 0; i != NumProtocols; ++i) { + ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first, + ProtocolId[i].second); + if (!PDecl) { + LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second, + LookupObjCProtocolName); + if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && + (PDecl = R.getAsSingle<ObjCProtocolDecl>())) { + Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) + << ProtocolId[i].first << R.getLookupName(); + Diag(PDecl->getLocation(), diag::note_previous_decl) + << PDecl->getDeclName(); + } + } + + if (!PDecl) { + Diag(ProtocolId[i].second, diag::err_undeclared_protocol) + << ProtocolId[i].first; + continue; + } + + (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); + + // If this is a forward declaration and we are supposed to warn in this + // case, do it. + if (WarnOnDeclarations && PDecl->isForwardDecl()) + Diag(ProtocolId[i].second, diag::warn_undef_protocolref) + << ProtocolId[i].first; + Protocols.push_back(PDecl); + } +} + +/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of +/// a class method in its extension. +/// +void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, + ObjCInterfaceDecl *ID) { + if (!ID) + return; // Possibly due to previous error + + llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap; + for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(), + e = ID->meth_end(); i != e; ++i) { + ObjCMethodDecl *MD = *i; + MethodMap[MD->getSelector()] = MD; + } + + if (MethodMap.empty()) + return; + for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(), + e = CAT->meth_end(); i != e; ++i) { + ObjCMethodDecl *Method = *i; + const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()]; + if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) { + Diag(Method->getLocation(), diag::err_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } + } +} + +/// ActOnForwardProtocolDeclaration - Handle @protocol foo; +Decl * +Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, + const IdentifierLocPair *IdentList, + unsigned NumElts, + AttributeList *attrList) { + llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols; + llvm::SmallVector<SourceLocation, 8> ProtoLocs; + + for (unsigned i = 0; i != NumElts; ++i) { + IdentifierInfo *Ident = IdentList[i].first; + ObjCProtocolDecl *PDecl = LookupProtocol(Ident, IdentList[i].second); + bool isNew = false; + if (PDecl == 0) { // Not already seen? + PDecl = ObjCProtocolDecl::Create(Context, CurContext, + IdentList[i].second, Ident); + PushOnScopeChains(PDecl, TUScope, false); + isNew = true; + } + if (attrList) { + ProcessDeclAttributeList(TUScope, PDecl, attrList); + if (!isNew) + PDecl->setChangedSinceDeserialization(true); + } + Protocols.push_back(PDecl); + ProtoLocs.push_back(IdentList[i].second); + } + + ObjCForwardProtocolDecl *PDecl = + ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc, + Protocols.data(), Protocols.size(), + ProtoLocs.data()); + CurContext->addDecl(PDecl); + CheckObjCDeclScope(PDecl); + return PDecl; +} + +Decl *Sema:: +ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *CategoryName, + SourceLocation CategoryLoc, + Decl * const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc) { + ObjCCategoryDecl *CDecl; + ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); + + /// Check that class of this category is already completely declared. + if (!IDecl || IDecl->isForwardDecl()) { + // Create an invalid ObjCCategoryDecl to serve as context for + // the enclosing method declarations. We mark the decl invalid + // to make it clear that this isn't a valid AST. + CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassLoc, CategoryLoc, CategoryName); + CDecl->setInvalidDecl(); + Diag(ClassLoc, diag::err_undef_interface) << ClassName; + return CDecl; + } + + if (!CategoryName && IDecl->getImplementation()) { + Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName; + Diag(IDecl->getImplementation()->getLocation(), + diag::note_implementation_declared); + } + + CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassLoc, CategoryLoc, CategoryName); + // FIXME: PushOnScopeChains? + CurContext->addDecl(CDecl); + + CDecl->setClassInterface(IDecl); + // Insert class extension to the list of class's categories. + if (!CategoryName) + CDecl->insertNextClassCategory(); + + // If the interface is deprecated, warn about it. + (void)DiagnoseUseOfDecl(IDecl, ClassLoc); + + if (CategoryName) { + /// Check for duplicate interface declaration for this category + ObjCCategoryDecl *CDeclChain; + for (CDeclChain = IDecl->getCategoryList(); CDeclChain; + CDeclChain = CDeclChain->getNextClassCategory()) { + if (CDeclChain->getIdentifier() == CategoryName) { + // Class extensions can be declared multiple times. + Diag(CategoryLoc, diag::warn_dup_category_def) + << ClassName << CategoryName; + Diag(CDeclChain->getLocation(), diag::note_previous_definition); + break; + } + } + if (!CDeclChain) + CDecl->insertNextClassCategory(); + } + + if (NumProtoRefs) { + CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + ProtoLocs, Context); + // Protocols in the class extension belong to the class. + if (CDecl->IsClassExtension()) + IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, + NumProtoRefs, Context); + } + + CheckObjCDeclScope(CDecl); + return CDecl; +} + +/// ActOnStartCategoryImplementation - Perform semantic checks on the +/// category implementation declaration and build an ObjCCategoryImplDecl +/// object. +Decl *Sema::ActOnStartCategoryImplementation( + SourceLocation AtCatImplLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *CatName, SourceLocation CatLoc) { + ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); + ObjCCategoryDecl *CatIDecl = 0; + if (IDecl) { + CatIDecl = IDecl->FindCategoryDeclaration(CatName); + if (!CatIDecl) { + // Category @implementation with no corresponding @interface. + // Create and install one. + CatIDecl = ObjCCategoryDecl::Create(Context, CurContext, SourceLocation(), + SourceLocation(), SourceLocation(), + CatName); + CatIDecl->setClassInterface(IDecl); + CatIDecl->insertNextClassCategory(); + } + } + + ObjCCategoryImplDecl *CDecl = + ObjCCategoryImplDecl::Create(Context, CurContext, AtCatImplLoc, CatName, + IDecl); + /// Check that class of this category is already completely declared. + if (!IDecl || IDecl->isForwardDecl()) + Diag(ClassLoc, diag::err_undef_interface) << ClassName; + + // FIXME: PushOnScopeChains? + CurContext->addDecl(CDecl); + + /// Check that CatName, category name, is not used in another implementation. + if (CatIDecl) { + if (CatIDecl->getImplementation()) { + Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName + << CatName; + Diag(CatIDecl->getImplementation()->getLocation(), + diag::note_previous_definition); + } else { + CatIDecl->setImplementation(CDecl); + // Warn on implementating category of deprecated class under + // -Wdeprecated-implementations flag. + DiagnoseObjCImplementedDeprecations(*this, + dyn_cast<NamedDecl>(IDecl), + CDecl->getLocation(), 2); + } + } + + CheckObjCDeclScope(CDecl); + return CDecl; +} + +Decl *Sema::ActOnStartClassImplementation( + SourceLocation AtClassImplLoc, + IdentifierInfo *ClassName, SourceLocation ClassLoc, + IdentifierInfo *SuperClassname, + SourceLocation SuperClassLoc) { + ObjCInterfaceDecl* IDecl = 0; + // Check for another declaration kind with the same name. + NamedDecl *PrevDecl + = LookupSingleName(TUScope, ClassName, ClassLoc, LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { + Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { + // If this is a forward declaration of an interface, warn. + if (IDecl->isForwardDecl()) { + Diag(ClassLoc, diag::warn_undef_interface) << ClassName; + IDecl = 0; + } + } else { + // We did not find anything with the name ClassName; try to correct for + // typos in the class name. + LookupResult R(*this, ClassName, ClassLoc, LookupOrdinaryName); + if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && + (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { + // Suggest the (potentially) correct interface name. However, put the + // fix-it hint itself in a separate note, since changing the name in + // the warning would make the fix-it change semantics.However, don't + // provide a code-modification hint or use the typo name for recovery, + // because this is just a warning. The program may actually be correct. + Diag(ClassLoc, diag::warn_undef_interface_suggest) + << ClassName << R.getLookupName(); + Diag(IDecl->getLocation(), diag::note_previous_decl) + << R.getLookupName() + << FixItHint::CreateReplacement(ClassLoc, + R.getLookupName().getAsString()); + IDecl = 0; + } else { + Diag(ClassLoc, diag::warn_undef_interface) << ClassName; + } + } + + // Check that super class name is valid class name + ObjCInterfaceDecl* SDecl = 0; + if (SuperClassname) { + // Check if a different kind of symbol declared in this scope. + PrevDecl = LookupSingleName(TUScope, SuperClassname, SuperClassLoc, + LookupOrdinaryName); + if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { + Diag(SuperClassLoc, diag::err_redefinition_different_kind) + << SuperClassname; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } else { + SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + if (!SDecl) + Diag(SuperClassLoc, diag::err_undef_superclass) + << SuperClassname << ClassName; + else if (IDecl && IDecl->getSuperClass() != SDecl) { + // This implementation and its interface do not have the same + // super class. + Diag(SuperClassLoc, diag::err_conflicting_super_class) + << SDecl->getDeclName(); + Diag(SDecl->getLocation(), diag::note_previous_definition); + } + } + } + + if (!IDecl) { + // Legacy case of @implementation with no corresponding @interface. + // Build, chain & install the interface decl into the identifier. + + // FIXME: Do we support attributes on the @implementation? If so we should + // copy them over. + IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassImplLoc, + ClassName, ClassLoc, false, true); + IDecl->setSuperClass(SDecl); + IDecl->setLocEnd(ClassLoc); + + PushOnScopeChains(IDecl, TUScope); + } else { + // Mark the interface as being completed, even if it was just as + // @class ....; + // declaration; the user cannot reopen it. + IDecl->setForwardDecl(false); + } + + ObjCImplementationDecl* IMPDecl = + ObjCImplementationDecl::Create(Context, CurContext, AtClassImplLoc, + IDecl, SDecl); + + if (CheckObjCDeclScope(IMPDecl)) + return IMPDecl; + + // Check that there is no duplicate implementation of this class. + if (IDecl->getImplementation()) { + // FIXME: Don't leak everything! + Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName; + Diag(IDecl->getImplementation()->getLocation(), + diag::note_previous_definition); + } else { // add it to the list. + IDecl->setImplementation(IMPDecl); + PushOnScopeChains(IMPDecl, TUScope); + // Warn on implementating deprecated class under + // -Wdeprecated-implementations flag. + DiagnoseObjCImplementedDeprecations(*this, + dyn_cast<NamedDecl>(IDecl), + IMPDecl->getLocation(), 1); + } + return IMPDecl; +} + +void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, + ObjCIvarDecl **ivars, unsigned numIvars, + SourceLocation RBrace) { + assert(ImpDecl && "missing implementation decl"); + ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface(); + if (!IDecl) + return; + /// Check case of non-existing @interface decl. + /// (legacy objective-c @implementation decl without an @interface decl). + /// Add implementations's ivar to the synthesize class's ivar list. + if (IDecl->isImplicitInterfaceDecl()) { + IDecl->setLocEnd(RBrace); + // Add ivar's to class's DeclContext. + for (unsigned i = 0, e = numIvars; i != e; ++i) { + ivars[i]->setLexicalDeclContext(ImpDecl); + IDecl->makeDeclVisibleInContext(ivars[i], false); + ImpDecl->addDecl(ivars[i]); + } + + return; + } + // If implementation has empty ivar list, just return. + if (numIvars == 0) + return; + + assert(ivars && "missing @implementation ivars"); + if (LangOpts.ObjCNonFragileABI2) { + if (ImpDecl->getSuperClass()) + Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use); + for (unsigned i = 0; i < numIvars; i++) { + ObjCIvarDecl* ImplIvar = ivars[i]; + if (const ObjCIvarDecl *ClsIvar = + IDecl->getIvarDecl(ImplIvar->getIdentifier())) { + Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + continue; + } + // Instance ivar to Implementation's DeclContext. + ImplIvar->setLexicalDeclContext(ImpDecl); + IDecl->makeDeclVisibleInContext(ImplIvar, false); + ImpDecl->addDecl(ImplIvar); + } + return; + } + // Check interface's Ivar list against those in the implementation. + // names and types must match. + // + unsigned j = 0; + ObjCInterfaceDecl::ivar_iterator + IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end(); + for (; numIvars > 0 && IVI != IVE; ++IVI) { + ObjCIvarDecl* ImplIvar = ivars[j++]; + ObjCIvarDecl* ClsIvar = *IVI; + assert (ImplIvar && "missing implementation ivar"); + assert (ClsIvar && "missing class ivar"); + + // First, make sure the types match. + if (Context.getCanonicalType(ImplIvar->getType()) != + Context.getCanonicalType(ClsIvar->getType())) { + Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type) + << ImplIvar->getIdentifier() + << ImplIvar->getType() << ClsIvar->getType(); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + } else if (ImplIvar->isBitField() && ClsIvar->isBitField()) { + Expr *ImplBitWidth = ImplIvar->getBitWidth(); + Expr *ClsBitWidth = ClsIvar->getBitWidth(); + if (ImplBitWidth->EvaluateAsInt(Context).getZExtValue() != + ClsBitWidth->EvaluateAsInt(Context).getZExtValue()) { + Diag(ImplBitWidth->getLocStart(), diag::err_conflicting_ivar_bitwidth) + << ImplIvar->getIdentifier(); + Diag(ClsBitWidth->getLocStart(), diag::note_previous_definition); + } + } + // Make sure the names are identical. + if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) { + Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name) + << ImplIvar->getIdentifier() << ClsIvar->getIdentifier(); + Diag(ClsIvar->getLocation(), diag::note_previous_definition); + } + --numIvars; + } + + if (numIvars > 0) + Diag(ivars[j]->getLocation(), diag::err_inconsistant_ivar_count); + else if (IVI != IVE) + Diag((*IVI)->getLocation(), diag::err_inconsistant_ivar_count); +} + +void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, + bool &IncompleteImpl, unsigned DiagID) { + if (!IncompleteImpl) { + Diag(ImpLoc, diag::warn_incomplete_impl); + IncompleteImpl = true; + } + if (DiagID == diag::warn_unimplemented_protocol_method) + Diag(ImpLoc, DiagID) << method->getDeclName(); + else + Diag(method->getLocation(), DiagID) << method->getDeclName(); +} + +/// Determines if type B can be substituted for type A. Returns true if we can +/// guarantee that anything that the user will do to an object of type A can +/// also be done to an object of type B. This is trivially true if the two +/// types are the same, or if B is a subclass of A. It becomes more complex +/// in cases where protocols are involved. +/// +/// Object types in Objective-C describe the minimum requirements for an +/// object, rather than providing a complete description of a type. For +/// example, if A is a subclass of B, then B* may refer to an instance of A. +/// The principle of substitutability means that we may use an instance of A +/// anywhere that we may use an instance of B - it will implement all of the +/// ivars of B and all of the methods of B. +/// +/// This substitutability is important when type checking methods, because +/// the implementation may have stricter type definitions than the interface. +/// The interface specifies minimum requirements, but the implementation may +/// have more accurate ones. For example, a method may privately accept +/// instances of B, but only publish that it accepts instances of A. Any +/// object passed to it will be type checked against B, and so will implicitly +/// by a valid A*. Similarly, a method may return a subclass of the class that +/// it is declared as returning. +/// +/// This is most important when considering subclassing. A method in a +/// subclass must accept any object as an argument that its superclass's +/// implementation accepts. It may, however, accept a more general type +/// without breaking substitutability (i.e. you can still use the subclass +/// anywhere that you can use the superclass, but not vice versa). The +/// converse requirement applies to return types: the return type for a +/// subclass method must be a valid object of the kind that the superclass +/// advertises, but it may be specified more accurately. This avoids the need +/// for explicit down-casting by callers. +/// +/// Note: This is a stricter requirement than for assignment. +static bool isObjCTypeSubstitutable(ASTContext &Context, + const ObjCObjectPointerType *A, + const ObjCObjectPointerType *B, + bool rejectId) { + // Reject a protocol-unqualified id. + if (rejectId && B->isObjCIdType()) return false; + + // If B is a qualified id, then A must also be a qualified id and it must + // implement all of the protocols in B. It may not be a qualified class. + // For example, MyClass<A> can be assigned to id<A>, but MyClass<A> is a + // stricter definition so it is not substitutable for id<A>. + if (B->isObjCQualifiedIdType()) { + return A->isObjCQualifiedIdType() && + Context.ObjCQualifiedIdTypesAreCompatible(QualType(A, 0), + QualType(B,0), + false); + } + + /* + // id is a special type that bypasses type checking completely. We want a + // warning when it is used in one place but not another. + if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false; + + + // If B is a qualified id, then A must also be a qualified id (which it isn't + // if we've got this far) + if (B->isObjCQualifiedIdType()) return false; + */ + + // Now we know that A and B are (potentially-qualified) class types. The + // normal rules for assignment apply. + return Context.canAssignObjCInterfaces(A, B); +} + +static SourceRange getTypeRange(TypeSourceInfo *TSI) { + return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange()); +} + +static void CheckMethodOverrideReturn(Sema &S, + ObjCMethodDecl *MethodImpl, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + if (IsProtocolMethodDecl && + (MethodDecl->getObjCDeclQualifier() != + MethodImpl->getObjCDeclQualifier())) { + S.Diag(MethodImpl->getLocation(), + diag::warn_conflicting_ret_type_modifiers) + << MethodImpl->getDeclName() + << getTypeRange(MethodImpl->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); + } + + if (S.Context.hasSameUnqualifiedType(MethodImpl->getResultType(), + MethodDecl->getResultType())) + return; + + unsigned DiagID = diag::warn_conflicting_ret_types; + + // Mismatches between ObjC pointers go into a different warning + // category, and sometimes they're even completely whitelisted. + if (const ObjCObjectPointerType *ImplPtrTy = + MethodImpl->getResultType()->getAs<ObjCObjectPointerType>()) { + if (const ObjCObjectPointerType *IfacePtrTy = + MethodDecl->getResultType()->getAs<ObjCObjectPointerType>()) { + // Allow non-matching return types as long as they don't violate + // the principle of substitutability. Specifically, we permit + // return types that are subclasses of the declared return type, + // or that are more-qualified versions of the declared type. + if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false)) + return; + + DiagID = diag::warn_non_covariant_ret_types; + } + } + + S.Diag(MethodImpl->getLocation(), DiagID) + << MethodImpl->getDeclName() + << MethodDecl->getResultType() + << MethodImpl->getResultType() + << getTypeRange(MethodImpl->getResultTypeSourceInfo()); + S.Diag(MethodDecl->getLocation(), diag::note_previous_definition) + << getTypeRange(MethodDecl->getResultTypeSourceInfo()); +} + +static void CheckMethodOverrideParam(Sema &S, + ObjCMethodDecl *MethodImpl, + ObjCMethodDecl *MethodDecl, + ParmVarDecl *ImplVar, + ParmVarDecl *IfaceVar, + bool IsProtocolMethodDecl) { + if (IsProtocolMethodDecl && + (ImplVar->getObjCDeclQualifier() != + IfaceVar->getObjCDeclQualifier())) { + S.Diag(ImplVar->getLocation(), + diag::warn_conflicting_param_modifiers) + << getTypeRange(ImplVar->getTypeSourceInfo()) + << MethodImpl->getDeclName(); + S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration) + << getTypeRange(IfaceVar->getTypeSourceInfo()); + } + + QualType ImplTy = ImplVar->getType(); + QualType IfaceTy = IfaceVar->getType(); + + if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy)) + return; + + unsigned DiagID = diag::warn_conflicting_param_types; + + // Mismatches between ObjC pointers go into a different warning + // category, and sometimes they're even completely whitelisted. + if (const ObjCObjectPointerType *ImplPtrTy = + ImplTy->getAs<ObjCObjectPointerType>()) { + if (const ObjCObjectPointerType *IfacePtrTy = + IfaceTy->getAs<ObjCObjectPointerType>()) { + // Allow non-matching argument types as long as they don't + // violate the principle of substitutability. Specifically, the + // implementation must accept any objects that the superclass + // accepts, however it may also accept others. + if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true)) + return; + + DiagID = diag::warn_non_contravariant_param_types; + } + } + + S.Diag(ImplVar->getLocation(), DiagID) + << getTypeRange(ImplVar->getTypeSourceInfo()) + << MethodImpl->getDeclName() << IfaceTy << ImplTy; + S.Diag(IfaceVar->getLocation(), diag::note_previous_definition) + << getTypeRange(IfaceVar->getTypeSourceInfo()); +} + + +void Sema::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, + ObjCMethodDecl *MethodDecl, + bool IsProtocolMethodDecl) { + CheckMethodOverrideReturn(*this, ImpMethodDecl, MethodDecl, + IsProtocolMethodDecl); + + for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), + IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(); + IM != EM; ++IM, ++IF) + CheckMethodOverrideParam(*this, ImpMethodDecl, MethodDecl, *IM, *IF, + IsProtocolMethodDecl); + + if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) { + Diag(ImpMethodDecl->getLocation(), diag::warn_conflicting_variadic); + Diag(MethodDecl->getLocation(), diag::note_previous_declaration); + } +} + +/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely +/// improve the efficiency of selector lookups and type checking by associating +/// with each protocol / interface / category the flattened instance tables. If +/// we used an immutable set to keep the table then it wouldn't add significant +/// memory cost and it would be handy for lookups. + +/// CheckProtocolMethodDefs - This routine checks unimplemented methods +/// Declared in protocol, and those referenced by it. +void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, + ObjCProtocolDecl *PDecl, + bool& IncompleteImpl, + const llvm::DenseSet<Selector> &InsMap, + const llvm::DenseSet<Selector> &ClsMap, + ObjCContainerDecl *CDecl) { + ObjCInterfaceDecl *IDecl; + if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) + IDecl = C->getClassInterface(); + else + IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); + assert (IDecl && "CheckProtocolMethodDefs - IDecl is null"); + + ObjCInterfaceDecl *Super = IDecl->getSuperClass(); + ObjCInterfaceDecl *NSIDecl = 0; + if (getLangOptions().NeXTRuntime) { + // check to see if class implements forwardInvocation method and objects + // of this class are derived from 'NSProxy' so that to forward requests + // from one object to another. + // Under such conditions, which means that every method possible is + // implemented in the class, we should not issue "Method definition not + // found" warnings. + // FIXME: Use a general GetUnarySelector method for this. + IdentifierInfo* II = &Context.Idents.get("forwardInvocation"); + Selector fISelector = Context.Selectors.getSelector(1, &II); + if (InsMap.count(fISelector)) + // Is IDecl derived from 'NSProxy'? If so, no instance methods + // need be implemented in the implementation. + NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy")); + } + + // If a method lookup fails locally we still need to look and see if + // the method was implemented by a base class or an inherited + // protocol. This lookup is slow, but occurs rarely in correct code + // and otherwise would terminate in a warning. + + // check unimplemented instance methods. + if (!NSIDecl) + for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), + E = PDecl->instmeth_end(); I != E; ++I) { + ObjCMethodDecl *method = *I; + if (method->getImplementationControl() != ObjCMethodDecl::Optional && + !method->isSynthesized() && !InsMap.count(method->getSelector()) && + (!Super || + !Super->lookupInstanceMethod(method->getSelector()))) { + // Ugly, but necessary. Method declared in protcol might have + // have been synthesized due to a property declared in the class which + // uses the protocol. + ObjCMethodDecl *MethodInClass = + IDecl->lookupInstanceMethod(method->getSelector()); + if (!MethodInClass || !MethodInClass->isSynthesized()) { + unsigned DIAG = diag::warn_unimplemented_protocol_method; + if (Diags.getDiagnosticLevel(DIAG, ImpLoc) + != Diagnostic::Ignored) { + WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); + Diag(method->getLocation(), diag::note_method_declared_at); + Diag(CDecl->getLocation(), diag::note_required_for_protocol_at) + << PDecl->getDeclName(); + } + } + } + } + // check unimplemented class methods + for (ObjCProtocolDecl::classmeth_iterator + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); + I != E; ++I) { + ObjCMethodDecl *method = *I; + if (method->getImplementationControl() != ObjCMethodDecl::Optional && + !ClsMap.count(method->getSelector()) && + (!Super || !Super->lookupClassMethod(method->getSelector()))) { + unsigned DIAG = diag::warn_unimplemented_protocol_method; + if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != Diagnostic::Ignored) { + WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); + Diag(method->getLocation(), diag::note_method_declared_at); + Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) << + PDecl->getDeclName(); + } + } + } + // Check on this protocols's referenced protocols, recursively. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + CheckProtocolMethodDefs(ImpLoc, *PI, IncompleteImpl, InsMap, ClsMap, IDecl); +} + +/// MatchAllMethodDeclarations - Check methods declaraed in interface or +/// or protocol against those declared in their implementations. +/// +void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, + const llvm::DenseSet<Selector> &ClsMap, + llvm::DenseSet<Selector> &InsMapSeen, + llvm::DenseSet<Selector> &ClsMapSeen, + ObjCImplDecl* IMPDecl, + ObjCContainerDecl* CDecl, + bool &IncompleteImpl, + bool ImmediateClass) { + // Check and see if instance methods in class interface have been + // implemented in the implementation class. If so, their types match. + for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), + E = CDecl->instmeth_end(); I != E; ++I) { + if (InsMapSeen.count((*I)->getSelector())) + continue; + InsMapSeen.insert((*I)->getSelector()); + if (!(*I)->isSynthesized() && + !InsMap.count((*I)->getSelector())) { + if (ImmediateClass) + WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, + diag::note_undef_method_impl); + continue; + } else { + ObjCMethodDecl *ImpMethodDecl = + IMPDecl->getInstanceMethod((*I)->getSelector()); + ObjCMethodDecl *MethodDecl = + CDecl->getInstanceMethod((*I)->getSelector()); + assert(MethodDecl && + "MethodDecl is null in ImplMethodsVsClassMethods"); + // ImpMethodDecl may be null as in a @dynamic property. + if (ImpMethodDecl) + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa<ObjCProtocolDecl>(CDecl)); + } + } + + // Check and see if class methods in class interface have been + // implemented in the implementation class. If so, their types match. + for (ObjCInterfaceDecl::classmeth_iterator + I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) { + if (ClsMapSeen.count((*I)->getSelector())) + continue; + ClsMapSeen.insert((*I)->getSelector()); + if (!ClsMap.count((*I)->getSelector())) { + if (ImmediateClass) + WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, + diag::note_undef_method_impl); + } else { + ObjCMethodDecl *ImpMethodDecl = + IMPDecl->getClassMethod((*I)->getSelector()); + ObjCMethodDecl *MethodDecl = + CDecl->getClassMethod((*I)->getSelector()); + WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, + isa<ObjCProtocolDecl>(CDecl)); + } + } + + if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { + // Also methods in class extensions need be looked at next. + for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, + const_cast<ObjCCategoryDecl *>(ClsExtDecl), + IncompleteImpl, false); + + // Check for any implementation of a methods declared in protocol. + for (ObjCInterfaceDecl::all_protocol_iterator + PI = I->all_referenced_protocol_begin(), + E = I->all_referenced_protocol_end(); PI != E; ++PI) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, + (*PI), IncompleteImpl, false); + if (I->getSuperClass()) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, + I->getSuperClass(), IncompleteImpl, false); + } +} + +void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, + ObjCContainerDecl* CDecl, + bool IncompleteImpl) { + llvm::DenseSet<Selector> InsMap; + // Check and see if instance methods in class interface have been + // implemented in the implementation class. + for (ObjCImplementationDecl::instmeth_iterator + I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I) + InsMap.insert((*I)->getSelector()); + + // Check and see if properties declared in the interface have either 1) + // an implementation or 2) there is a @synthesize/@dynamic implementation + // of the property in the @implementation. + if (isa<ObjCInterfaceDecl>(CDecl) && + !(LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCNonFragileABI2)) + DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap); + + llvm::DenseSet<Selector> ClsMap; + for (ObjCImplementationDecl::classmeth_iterator + I = IMPDecl->classmeth_begin(), + E = IMPDecl->classmeth_end(); I != E; ++I) + ClsMap.insert((*I)->getSelector()); + + // Check for type conflict of methods declared in a class/protocol and + // its implementation; if any. + llvm::DenseSet<Selector> InsMapSeen, ClsMapSeen; + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, CDecl, + IncompleteImpl, true); + + // Check the protocol list for unimplemented methods in the @implementation + // class. + // Check and see if class methods in class interface have been + // implemented in the implementation class. + + if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { + for (ObjCInterfaceDecl::all_protocol_iterator + PI = I->all_referenced_protocol_begin(), + E = I->all_referenced_protocol_end(); PI != E; ++PI) + CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, + InsMap, ClsMap, I); + // Check class extensions (unnamed categories) + for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension(); + Categories; Categories = Categories->getNextClassExtension()) + ImplMethodsVsClassMethods(S, IMPDecl, + const_cast<ObjCCategoryDecl*>(Categories), + IncompleteImpl); + } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { + // For extended class, unimplemented methods in its protocols will + // be reported in the primary class. + if (!C->IsClassExtension()) { + for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(), + E = C->protocol_end(); PI != E; ++PI) + CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, + InsMap, ClsMap, CDecl); + // Report unimplemented properties in the category as well. + // When reporting on missing setter/getters, do not report when + // setter/getter is implemented in category's primary class + // implementation. + if (ObjCInterfaceDecl *ID = C->getClassInterface()) + if (ObjCImplDecl *IMP = ID->getImplementation()) { + for (ObjCImplementationDecl::instmeth_iterator + I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I) + InsMap.insert((*I)->getSelector()); + } + DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, InsMap); + } + } else + assert(false && "invalid ObjCContainerDecl type."); +} + +/// ActOnForwardClassDeclaration - +Decl * +Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + SourceLocation *IdentLocs, + unsigned NumElts) { + llvm::SmallVector<ObjCInterfaceDecl*, 32> Interfaces; + + for (unsigned i = 0; i != NumElts; ++i) { + // Check for another declaration kind with the same name. + NamedDecl *PrevDecl + = LookupSingleName(TUScope, IdentList[i], IdentLocs[i], + LookupOrdinaryName, ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + + if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { + // GCC apparently allows the following idiom: + // + // typedef NSObject < XCElementTogglerP > XCElementToggler; + // @class XCElementToggler; + // + // FIXME: Make an extension? + TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl); + if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { + Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + } else { + // a forward class declaration matching a typedef name of a class refers + // to the underlying class. + if (const ObjCObjectType *OI = + TDD->getUnderlyingType()->getAs<ObjCObjectType>()) + PrevDecl = OI->getInterface(); + } + } + ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + if (!IDecl) { // Not already seen? Make a forward decl. + IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtClassLoc, + IdentList[i], IdentLocs[i], true); + + // Push the ObjCInterfaceDecl on the scope chain but do *not* add it to + // the current DeclContext. This prevents clients that walk DeclContext + // from seeing the imaginary ObjCInterfaceDecl until it is actually + // declared later (if at all). We also take care to explicitly make + // sure this declaration is visible for name lookup. + PushOnScopeChains(IDecl, TUScope, false); + CurContext->makeDeclVisibleInContext(IDecl, true); + } + + Interfaces.push_back(IDecl); + } + + assert(Interfaces.size() == NumElts); + ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc, + Interfaces.data(), IdentLocs, + Interfaces.size()); + CurContext->addDecl(CDecl); + CheckObjCDeclScope(CDecl); + return CDecl; +} + + +/// MatchTwoMethodDeclarations - Checks that two methods have matching type and +/// returns true, or false, accordingly. +/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons +bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *Method, + const ObjCMethodDecl *PrevMethod, + bool matchBasedOnSizeAndAlignment, + bool matchBasedOnStrictEqulity) { + QualType T1 = Context.getCanonicalType(Method->getResultType()); + QualType T2 = Context.getCanonicalType(PrevMethod->getResultType()); + + if (T1 != T2) { + // The result types are different. + if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity) + return false; + // Incomplete types don't have a size and alignment. + if (T1->isIncompleteType() || T2->isIncompleteType()) + return false; + // Check is based on size and alignment. + if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2)) + return false; + } + + ObjCMethodDecl::param_iterator ParamI = Method->param_begin(), + E = Method->param_end(); + ObjCMethodDecl::param_iterator PrevI = PrevMethod->param_begin(); + + for (; ParamI != E; ++ParamI, ++PrevI) { + assert(PrevI != PrevMethod->param_end() && "Param mismatch"); + T1 = Context.getCanonicalType((*ParamI)->getType()); + T2 = Context.getCanonicalType((*PrevI)->getType()); + if (T1 != T2) { + // The result types are different. + if (!matchBasedOnSizeAndAlignment || matchBasedOnStrictEqulity) + return false; + // Incomplete types don't have a size and alignment. + if (T1->isIncompleteType() || T2->isIncompleteType()) + return false; + // Check is based on size and alignment. + if (Context.getTypeInfo(T1) != Context.getTypeInfo(T2)) + return false; + } + } + return true; +} + +/// \brief Read the contents of the method pool for a given selector from +/// external storage. +/// +/// This routine should only be called once, when the method pool has no entry +/// for this selector. +Sema::GlobalMethodPool::iterator Sema::ReadMethodPool(Selector Sel) { + assert(ExternalSource && "We need an external AST source"); + assert(MethodPool.find(Sel) == MethodPool.end() && + "Selector data already loaded into the method pool"); + + // Read the method list from the external source. + GlobalMethods Methods = ExternalSource->ReadMethodPool(Sel); + + return MethodPool.insert(std::make_pair(Sel, Methods)).first; +} + +void Sema::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, + bool instance) { + GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); + if (Pos == MethodPool.end()) { + if (ExternalSource) + Pos = ReadMethodPool(Method->getSelector()); + else + Pos = MethodPool.insert(std::make_pair(Method->getSelector(), + GlobalMethods())).first; + } + Method->setDefined(impl); + ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; + if (Entry.Method == 0) { + // Haven't seen a method with this selector name yet - add it. + Entry.Method = Method; + Entry.Next = 0; + return; + } + + // We've seen a method with this name, see if we have already seen this type + // signature. + for (ObjCMethodList *List = &Entry; List; List = List->Next) + if (MatchTwoMethodDeclarations(Method, List->Method)) { + ObjCMethodDecl *PrevObjCMethod = List->Method; + PrevObjCMethod->setDefined(impl); + // If a method is deprecated, push it in the global pool. + // This is used for better diagnostics. + if (Method->isDeprecated()) { + if (!PrevObjCMethod->isDeprecated()) + List->Method = Method; + } + // If new method is unavailable, push it into global pool + // unless previous one is deprecated. + if (Method->isUnavailable()) { + if (PrevObjCMethod->getAvailability() < AR_Deprecated) + List->Method = Method; + } + return; + } + + // We have a new signature for an existing method - add it. + // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". + ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>(); + Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next); +} + +ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, + bool receiverIdOrClass, + bool warn, bool instance) { + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) { + if (ExternalSource) + Pos = ReadMethodPool(Sel); + else + return 0; + } + + ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; + + bool strictSelectorMatch = receiverIdOrClass && warn && + (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl, + R.getBegin()) != + Diagnostic::Ignored); + if (warn && MethList.Method && MethList.Next) { + bool issueWarning = false; + if (strictSelectorMatch) + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { + // This checks if the methods differ in type mismatch. + if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, false, true)) + issueWarning = true; + } + + if (!issueWarning) + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { + // This checks if the methods differ by size & alignment. + if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true)) + issueWarning = true; + } + + if (issueWarning) { + if (strictSelectorMatch) + Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R; + else + Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; + Diag(MethList.Method->getLocStart(), diag::note_using) + << MethList.Method->getSourceRange(); + for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) + Diag(Next->Method->getLocStart(), diag::note_also_found) + << Next->Method->getSourceRange(); + } + } + return MethList.Method; +} + +ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { + GlobalMethodPool::iterator Pos = MethodPool.find(Sel); + if (Pos == MethodPool.end()) + return 0; + + GlobalMethods &Methods = Pos->second; + + if (Methods.first.Method && Methods.first.Method->isDefined()) + return Methods.first.Method; + if (Methods.second.Method && Methods.second.Method->isDefined()) + return Methods.second.Method; + return 0; +} + +/// CompareMethodParamsInBaseAndSuper - This routine compares methods with +/// identical selector names in current and its super classes and issues +/// a warning if any of their argument types are incompatible. +void Sema::CompareMethodParamsInBaseAndSuper(Decl *ClassDecl, + ObjCMethodDecl *Method, + bool IsInstance) { + ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ClassDecl); + if (ID == 0) return; + + while (ObjCInterfaceDecl *SD = ID->getSuperClass()) { + ObjCMethodDecl *SuperMethodDecl = + SD->lookupMethod(Method->getSelector(), IsInstance); + if (SuperMethodDecl == 0) { + ID = SD; + continue; + } + ObjCMethodDecl::param_iterator ParamI = Method->param_begin(), + E = Method->param_end(); + ObjCMethodDecl::param_iterator PrevI = SuperMethodDecl->param_begin(); + for (; ParamI != E; ++ParamI, ++PrevI) { + // Number of parameters are the same and is guaranteed by selector match. + assert(PrevI != SuperMethodDecl->param_end() && "Param mismatch"); + QualType T1 = Context.getCanonicalType((*ParamI)->getType()); + QualType T2 = Context.getCanonicalType((*PrevI)->getType()); + // If type of argument of method in this class does not match its + // respective argument type in the super class method, issue warning; + if (!Context.typesAreCompatible(T1, T2)) { + Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super) + << T1 << T2; + Diag(SuperMethodDecl->getLocation(), diag::note_previous_declaration); + return; + } + } + ID = SD; + } +} + +/// DiagnoseDuplicateIvars - +/// Check for duplicate ivars in the entire class at the start of +/// @implementation. This becomes necesssary because class extension can +/// add ivars to a class in random order which will not be known until +/// class's @implementation is seen. +void Sema::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, + ObjCInterfaceDecl *SID) { + for (ObjCInterfaceDecl::ivar_iterator IVI = ID->ivar_begin(), + IVE = ID->ivar_end(); IVI != IVE; ++IVI) { + ObjCIvarDecl* Ivar = (*IVI); + if (Ivar->isInvalidDecl()) + continue; + if (IdentifierInfo *II = Ivar->getIdentifier()) { + ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II); + if (prevIvar) { + Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; + Diag(prevIvar->getLocation(), diag::note_previous_declaration); + Ivar->setInvalidDecl(); + } + } + } +} + +// Note: For class/category implemenations, allMethods/allProperties is +// always null. +void Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, + Decl *ClassDecl, + Decl **allMethods, unsigned allNum, + Decl **allProperties, unsigned pNum, + DeclGroupPtrTy *allTUVars, unsigned tuvNum) { + // FIXME: If we don't have a ClassDecl, we have an error. We should consider + // always passing in a decl. If the decl has an error, isInvalidDecl() + // should be true. + if (!ClassDecl) + return; + + bool isInterfaceDeclKind = + isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl) + || isa<ObjCProtocolDecl>(ClassDecl); + bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl); + + if (!isInterfaceDeclKind && AtEnd.isInvalid()) { + // FIXME: This is wrong. We shouldn't be pretending that there is + // an '@end' in the declaration. + SourceLocation L = ClassDecl->getLocation(); + AtEnd.setBegin(L); + AtEnd.setEnd(L); + Diag(L, diag::err_missing_atend); + } + + // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. + llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap; + llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap; + + for (unsigned i = 0; i < allNum; i++ ) { + ObjCMethodDecl *Method = + cast_or_null<ObjCMethodDecl>(allMethods[i]); + + if (!Method) continue; // Already issued a diagnostic. + if (Method->isInstanceMethod()) { + /// Check for instance method of the same name with incompatible types + const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()]; + bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) + : false; + if ((isInterfaceDeclKind && PrevMethod && !match) + || (checkIdenticalMethods && match)) { + Diag(Method->getLocation(), diag::err_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + Method->setInvalidDecl(); + } else { + InsMap[Method->getSelector()] = Method; + /// The following allows us to typecheck messages to "id". + AddInstanceMethodToGlobalPool(Method); + // verify that the instance method conforms to the same definition of + // parent methods if it shadows one. + CompareMethodParamsInBaseAndSuper(ClassDecl, Method, true); + } + } else { + /// Check for class method of the same name with incompatible types + const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()]; + bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) + : false; + if ((isInterfaceDeclKind && PrevMethod && !match) + || (checkIdenticalMethods && match)) { + Diag(Method->getLocation(), diag::err_duplicate_method_decl) + << Method->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + Method->setInvalidDecl(); + } else { + ClsMap[Method->getSelector()] = Method; + /// The following allows us to typecheck messages to "Class". + AddFactoryMethodToGlobalPool(Method); + // verify that the class method conforms to the same definition of + // parent methods if it shadows one. + CompareMethodParamsInBaseAndSuper(ClassDecl, Method, false); + } + } + } + if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { + // Compares properties declared in this class to those of its + // super class. + ComparePropertiesInBaseAndSuper(I); + CompareProperties(I, I); + } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { + // Categories are used to extend the class by declaring new methods. + // By the same token, they are also used to add new properties. No + // need to compare the added property to those in the class. + + // Compare protocol properties with those in category + CompareProperties(C, C); + if (C->IsClassExtension()) { + ObjCInterfaceDecl *CCPrimary = C->getClassInterface(); + DiagnoseClassExtensionDupMethods(C, CCPrimary); + } + } + if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) { + if (CDecl->getIdentifier()) + // ProcessPropertyDecl is responsible for diagnosing conflicts with any + // user-defined setter/getter. It also synthesizes setter/getter methods + // and adds them to the DeclContext and global method pools. + for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), + E = CDecl->prop_end(); + I != E; ++I) + ProcessPropertyDecl(*I, CDecl); + CDecl->setAtEndRange(AtEnd); + } + if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) { + IC->setAtEndRange(AtEnd); + if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) { + // Any property declared in a class extension might have user + // declared setter or getter in current class extension or one + // of the other class extensions. Mark them as synthesized as + // property will be synthesized when property with same name is + // seen in the @implementation. + for (const ObjCCategoryDecl *ClsExtDecl = + IDecl->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + for (ObjCContainerDecl::prop_iterator I = ClsExtDecl->prop_begin(), + E = ClsExtDecl->prop_end(); I != E; ++I) { + ObjCPropertyDecl *Property = (*I); + // Skip over properties declared @dynamic + if (const ObjCPropertyImplDecl *PIDecl + = IC->FindPropertyImplDecl(Property->getIdentifier())) + if (PIDecl->getPropertyImplementation() + == ObjCPropertyImplDecl::Dynamic) + continue; + + for (const ObjCCategoryDecl *CExtDecl = + IDecl->getFirstClassExtension(); + CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) { + if (ObjCMethodDecl *GetterMethod = + CExtDecl->getInstanceMethod(Property->getGetterName())) + GetterMethod->setSynthesized(true); + if (!Property->isReadOnly()) + if (ObjCMethodDecl *SetterMethod = + CExtDecl->getInstanceMethod(Property->getSetterName())) + SetterMethod->setSynthesized(true); + } + } + } + + if (LangOpts.ObjCDefaultSynthProperties && + LangOpts.ObjCNonFragileABI2) + DefaultSynthesizeProperties(S, IC, IDecl); + ImplMethodsVsClassMethods(S, IC, IDecl); + AtomicPropertySetterGetterRules(IC, IDecl); + + if (LangOpts.ObjCNonFragileABI2) + while (IDecl->getSuperClass()) { + DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); + IDecl = IDecl->getSuperClass(); + } + } + SetIvarInitializers(IC); + } else if (ObjCCategoryImplDecl* CatImplClass = + dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { + CatImplClass->setAtEndRange(AtEnd); + + // Find category interface decl and then check that all methods declared + // in this interface are implemented in the category @implementation. + if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) { + for (ObjCCategoryDecl *Categories = IDecl->getCategoryList(); + Categories; Categories = Categories->getNextClassCategory()) { + if (Categories->getIdentifier() == CatImplClass->getIdentifier()) { + ImplMethodsVsClassMethods(S, CatImplClass, Categories); + break; + } + } + } + } + if (isInterfaceDeclKind) { + // Reject invalid vardecls. + for (unsigned i = 0; i != tuvNum; i++) { + DeclGroupRef DG = allTUVars[i].getAsVal<DeclGroupRef>(); + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) { + if (!VDecl->hasExternalStorage()) + Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass); + } + } + } +} + + +/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for +/// objective-c's type qualifier from the parser version of the same info. +static Decl::ObjCDeclQualifier +CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { + return (Decl::ObjCDeclQualifier) (unsigned) PQTVal; +} + +static inline +bool containsInvalidMethodImplAttribute(const AttrVec &A) { + // The 'ibaction' attribute is allowed on method definitions because of + // how the IBAction macro is used on both method declarations and definitions. + // If the method definitions contains any other attributes, return true. + for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) + if ((*i)->getKind() != attr::IBAction) + return true; + return false; +} + +/// \brief Check whether the declared result type of the given Objective-C +/// method declaration is compatible with the method's class. +/// +static bool +CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method, + ObjCInterfaceDecl *CurrentClass) { + QualType ResultType = Method->getResultType(); + SourceRange ResultTypeRange; + if (const TypeSourceInfo *ResultTypeInfo = Method->getResultTypeSourceInfo()) + ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange(); + + // If an Objective-C method inherits its related result type, then its + // declared result type must be compatible with its own class type. The + // declared result type is compatible if: + if (const ObjCObjectPointerType *ResultObjectType + = ResultType->getAs<ObjCObjectPointerType>()) { + // - it is id or qualified id, or + if (ResultObjectType->isObjCIdType() || + ResultObjectType->isObjCQualifiedIdType()) + return false; + + if (CurrentClass) { + if (ObjCInterfaceDecl *ResultClass + = ResultObjectType->getInterfaceDecl()) { + // - it is the same as the method's class type, or + if (CurrentClass == ResultClass) + return false; + + // - it is a superclass of the method's class type + if (ResultClass->isSuperClassOf(CurrentClass)) + return false; + } + } + } + + return true; +} + +/// \brief Determine if any method in the global method pool has an inferred +/// result type. +static bool +anyMethodInfersRelatedResultType(Sema &S, Selector Sel, bool IsInstance) { + Sema::GlobalMethodPool::iterator Pos = S.MethodPool.find(Sel); + if (Pos == S.MethodPool.end()) { + if (S.ExternalSource) + Pos = S.ReadMethodPool(Sel); + else + return 0; + } + + ObjCMethodList &List = IsInstance ? Pos->second.first : Pos->second.second; + for (ObjCMethodList *M = &List; M; M = M->Next) { + if (M->Method && M->Method->hasRelatedResultType()) + return true; + } + + return false; +} + +Decl *Sema::ActOnMethodDeclaration( + Scope *S, + SourceLocation MethodLoc, SourceLocation EndLoc, + tok::TokenKind MethodType, Decl *ClassDecl, + ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + SourceLocation SelectorStartLoc, + Selector Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + ObjCArgInfo *ArgInfo, + DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args + AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, + bool isVariadic, bool MethodDefinition) { + // Make sure we can establish a context for the method. + if (!ClassDecl) { + Diag(MethodLoc, diag::error_missing_method_context); + return 0; + } + QualType resultDeclType; + + TypeSourceInfo *ResultTInfo = 0; + if (ReturnType) { + resultDeclType = GetTypeFromParser(ReturnType, &ResultTInfo); + + // Methods cannot return interface types. All ObjC objects are + // passed by reference. + if (resultDeclType->isObjCObjectType()) { + Diag(MethodLoc, diag::err_object_cannot_be_passed_returned_by_value) + << 0 << resultDeclType; + return 0; + } + } else // get the type for "id". + resultDeclType = Context.getObjCIdType(); + + ObjCMethodDecl* ObjCMethod = + ObjCMethodDecl::Create(Context, MethodLoc, EndLoc, Sel, resultDeclType, + ResultTInfo, + cast<DeclContext>(ClassDecl), + MethodType == tok::minus, isVariadic, + false, false, + MethodDeclKind == tok::objc_optional + ? ObjCMethodDecl::Optional + : ObjCMethodDecl::Required, + false); + + llvm::SmallVector<ParmVarDecl*, 16> Params; + + for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) { + QualType ArgType; + TypeSourceInfo *DI; + + if (ArgInfo[i].Type == 0) { + ArgType = Context.getObjCIdType(); + DI = 0; + } else { + ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI); + // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). + ArgType = adjustParameterType(ArgType); + } + + LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc, + LookupOrdinaryName, ForRedeclaration); + LookupName(R, S); + if (R.isSingleResult()) { + NamedDecl *PrevDecl = R.getFoundDecl(); + if (S->isDeclScope(PrevDecl)) { + Diag(ArgInfo[i].NameLoc, + (MethodDefinition ? diag::warn_method_param_redefinition + : diag::warn_method_param_declaration)) + << ArgInfo[i].Name; + Diag(PrevDecl->getLocation(), + diag::note_previous_declaration); + } + } + + SourceLocation StartLoc = DI + ? DI->getTypeLoc().getBeginLoc() + : ArgInfo[i].NameLoc; + + ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc, + ArgInfo[i].NameLoc, ArgInfo[i].Name, + ArgType, DI, SC_None, SC_None); + + Param->setObjCMethodScopeInfo(i); + + Param->setObjCDeclQualifier( + CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); + + // Apply the attributes to the parameter. + ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); + + S->AddDecl(Param); + IdResolver.AddDecl(Param); + + Params.push_back(Param); + } + + for (unsigned i = 0, e = CNumArgs; i != e; ++i) { + ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param); + QualType ArgType = Param->getType(); + if (ArgType.isNull()) + ArgType = Context.getObjCIdType(); + else + // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). + ArgType = adjustParameterType(ArgType); + if (ArgType->isObjCObjectType()) { + Diag(Param->getLocation(), + diag::err_object_cannot_be_passed_returned_by_value) + << 1 << ArgType; + Param->setInvalidDecl(); + } + Param->setDeclContext(ObjCMethod); + + Params.push_back(Param); + } + + ObjCMethod->setMethodParams(Context, Params.data(), Params.size(), + Sel.getNumArgs()); + ObjCMethod->setObjCDeclQualifier( + CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); + const ObjCMethodDecl *PrevMethod = 0; + + if (AttrList) + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + + const ObjCMethodDecl *InterfaceMD = 0; + + // Add the method now. + if (ObjCImplementationDecl *ImpDecl = + dyn_cast<ObjCImplementationDecl>(ClassDecl)) { + if (MethodType == tok::minus) { + PrevMethod = ImpDecl->getInstanceMethod(Sel); + ImpDecl->addInstanceMethod(ObjCMethod); + } else { + PrevMethod = ImpDecl->getClassMethod(Sel); + ImpDecl->addClassMethod(ObjCMethod); + } + InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel, + MethodType == tok::minus); + + if (ObjCMethod->hasAttrs() && + containsInvalidMethodImplAttribute(ObjCMethod->getAttrs())) + Diag(EndLoc, diag::warn_attribute_method_def); + } else if (ObjCCategoryImplDecl *CatImpDecl = + dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { + if (MethodType == tok::minus) { + PrevMethod = CatImpDecl->getInstanceMethod(Sel); + CatImpDecl->addInstanceMethod(ObjCMethod); + } else { + PrevMethod = CatImpDecl->getClassMethod(Sel); + CatImpDecl->addClassMethod(ObjCMethod); + } + + if (ObjCCategoryDecl *Cat = CatImpDecl->getCategoryDecl()) + InterfaceMD = Cat->getMethod(Sel, MethodType == tok::minus); + + if (ObjCMethod->hasAttrs() && + containsInvalidMethodImplAttribute(ObjCMethod->getAttrs())) + Diag(EndLoc, diag::warn_attribute_method_def); + } else { + cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod); + } + if (PrevMethod) { + // You can never have two method definitions with the same name. + Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl) + << ObjCMethod->getDeclName(); + Diag(PrevMethod->getLocation(), diag::note_previous_declaration); + } + + // If this Objective-C method does not have a related result type, but we + // are allowed to infer related result types, try to do so based on the + // method family. + ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(ClassDecl); + if (!CurrentClass) { + if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) + CurrentClass = Cat->getClassInterface(); + else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(ClassDecl)) + CurrentClass = Impl->getClassInterface(); + else if (ObjCCategoryImplDecl *CatImpl + = dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) + CurrentClass = CatImpl->getClassInterface(); + } + + // Merge information down from the interface declaration if we have one. + if (InterfaceMD) { + // Inherit the related result type, if we can. + if (InterfaceMD->hasRelatedResultType() && + !CheckRelatedResultTypeCompatibility(*this, ObjCMethod, CurrentClass)) + ObjCMethod->SetRelatedResultType(); + + mergeObjCMethodDecls(ObjCMethod, InterfaceMD); + } + + if (!ObjCMethod->hasRelatedResultType() && + getLangOptions().ObjCInferRelatedResultType) { + bool InferRelatedResultType = false; + switch (ObjCMethod->getMethodFamily()) { + case OMF_None: + case OMF_copy: + case OMF_dealloc: + case OMF_mutableCopy: + case OMF_release: + case OMF_retainCount: + break; + + case OMF_alloc: + case OMF_new: + InferRelatedResultType = ObjCMethod->isClassMethod(); + break; + + case OMF_init: + case OMF_autorelease: + case OMF_retain: + case OMF_self: + InferRelatedResultType = ObjCMethod->isInstanceMethod(); + break; + } + + if (InferRelatedResultType && + !CheckRelatedResultTypeCompatibility(*this, ObjCMethod, CurrentClass)) + ObjCMethod->SetRelatedResultType(); + + if (!InterfaceMD && + anyMethodInfersRelatedResultType(*this, ObjCMethod->getSelector(), + ObjCMethod->isInstanceMethod())) + CheckObjCMethodOverrides(ObjCMethod, cast<DeclContext>(ClassDecl)); + } + + return ObjCMethod; +} + +bool Sema::CheckObjCDeclScope(Decl *D) { + if (isa<TranslationUnitDecl>(CurContext->getRedeclContext())) + return false; + + Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); + D->setInvalidDecl(); + + return true; +} + +/// Called whenever @defs(ClassName) is encountered in the source. Inserts the +/// instance variables of ClassName into Decls. +void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, + IdentifierInfo *ClassName, + llvm::SmallVectorImpl<Decl*> &Decls) { + // Check that ClassName is a valid class + ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart); + if (!Class) { + Diag(DeclStart, diag::err_undef_interface) << ClassName; + return; + } + if (LangOpts.ObjCNonFragileABI) { + Diag(DeclStart, diag::err_atdef_nonfragile_interface); + return; + } + + // Collect the instance variables + llvm::SmallVector<ObjCIvarDecl*, 32> Ivars; + Context.DeepCollectObjCIvars(Class, true, Ivars); + // For each ivar, create a fresh ObjCAtDefsFieldDecl. + for (unsigned i = 0; i < Ivars.size(); i++) { + FieldDecl* ID = cast<FieldDecl>(Ivars[i]); + RecordDecl *Record = dyn_cast<RecordDecl>(TagD); + Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, + /*FIXME: StartL=*/ID->getLocation(), + ID->getLocation(), + ID->getIdentifier(), ID->getType(), + ID->getBitWidth()); + Decls.push_back(FD); + } + + // Introduce all of these fields into the appropriate scope. + for (llvm::SmallVectorImpl<Decl*>::iterator D = Decls.begin(); + D != Decls.end(); ++D) { + FieldDecl *FD = cast<FieldDecl>(*D); + if (getLangOptions().CPlusPlus) + PushOnScopeChains(cast<FieldDecl>(FD), S); + else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD)) + Record->addDecl(FD); + } +} + +/// \brief Build a type-check a new Objective-C exception variable declaration. +VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id, + bool Invalid) { + // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage + // duration shall not be qualified by an address-space qualifier." + // Since all parameters have automatic store duration, they can not have + // an address space. + if (T.getAddressSpace() != 0) { + Diag(IdLoc, diag::err_arg_with_address_space); + Invalid = true; + } + + // An @catch parameter must be an unqualified object pointer type; + // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"? + if (Invalid) { + // Don't do any further checking. + } else if (T->isDependentType()) { + // Okay: we don't know what this type will instantiate to. + } else if (!T->isObjCObjectPointerType()) { + Invalid = true; + Diag(IdLoc ,diag::err_catch_param_not_objc_type); + } else if (T->isObjCQualifiedIdType()) { + Invalid = true; + Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm); + } + + VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id, + T, TInfo, SC_None, SC_None); + New->setExceptionVariable(true); + + if (Invalid) + New->setInvalidDecl(); + return New; +} + +Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { + const DeclSpec &DS = D.getDeclSpec(); + + // We allow the "register" storage class on exception variables because + // GCC did, but we drop it completely. Any other storage class is an error. + if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { + Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm) + << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc())); + } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { + Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm) + << DS.getStorageClassSpec(); + } + if (D.getDeclSpec().isThreadSpecified()) + Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + D.getMutableDeclSpec().ClearStorageClassSpecs(); + + DiagnoseFunctionSpecifiers(D); + + // Check that there are no default arguments inside the type of this + // exception object (C++ only). + if (getLangOptions().CPlusPlus) + CheckExtraCXXDefaultArguments(D); + + TagDecl *OwnedDecl = 0; + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl); + QualType ExceptionType = TInfo->getType(); + + if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) { + // Objective-C++: Types shall not be defined in exception types. + Diag(OwnedDecl->getLocation(), diag::err_type_defined_in_param_type) + << Context.getTypeDeclType(OwnedDecl); + } + + VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + D.getIdentifier(), + D.isInvalidType()); + + // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). + if (D.getCXXScopeSpec().isSet()) { + Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm) + << D.getCXXScopeSpec().getRange(); + New->setInvalidDecl(); + } + + // Add the parameter declaration into this scope. + S->AddDecl(New); + if (D.getIdentifier()) + IdResolver.AddDecl(New); + + ProcessDeclAttributes(S, New, D); + + if (New->hasAttr<BlocksAttr>()) + Diag(New->getLocation(), diag::err_block_on_nonlocal); + return New; +} + +/// CollectIvarsToConstructOrDestruct - Collect those ivars which require +/// initialization. +void Sema::CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, + llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { + for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; + Iv= Iv->getNextIvar()) { + QualType QT = Context.getBaseElementType(Iv->getType()); + if (QT->isRecordType()) + Ivars.push_back(Iv); + } +} + +void ObjCImplementationDecl::setIvarInitializers(ASTContext &C, + CXXCtorInitializer ** initializers, + unsigned numInitializers) { + if (numInitializers > 0) { + NumIvarInitializers = numInitializers; + CXXCtorInitializer **ivarInitializers = + new (C) CXXCtorInitializer*[NumIvarInitializers]; + memcpy(ivarInitializers, initializers, + numInitializers * sizeof(CXXCtorInitializer*)); + IvarInitializers = ivarInitializers; + } +} + +void Sema::DiagnoseUseOfUnimplementedSelectors() { + // Warning will be issued only when selector table is + // generated (which means there is at lease one implementation + // in the TU). This is to match gcc's behavior. + if (ReferencedSelectors.empty() || + !Context.AnyObjCImplementation()) + return; + for (llvm::DenseMap<Selector, SourceLocation>::iterator S = + ReferencedSelectors.begin(), + E = ReferencedSelectors.end(); S != E; ++S) { + Selector Sel = (*S).first; + if (!LookupImplementedMethodInGlobalPool(Sel)) + Diag((*S).second, diag::warn_unimplemented_selector) << Sel; + } + return; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp new file mode 100644 index 0000000..7bcec31 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -0,0 +1,730 @@ +//===--- SemaExceptionSpec.cpp - C++ Exception Specifications ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sema routines for C++ exception specification testing. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallPtrSet.h" + +namespace clang { + +static const FunctionProtoType *GetUnderlyingFunction(QualType T) +{ + if (const PointerType *PtrTy = T->getAs<PointerType>()) + T = PtrTy->getPointeeType(); + else if (const ReferenceType *RefTy = T->getAs<ReferenceType>()) + T = RefTy->getPointeeType(); + else if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) + T = MPTy->getPointeeType(); + return T->getAs<FunctionProtoType>(); +} + +/// CheckSpecifiedExceptionType - Check if the given type is valid in an +/// exception specification. Incomplete types, or pointers to incomplete types +/// other than void are not allowed. +bool Sema::CheckSpecifiedExceptionType(QualType T, const SourceRange &Range) { + + // This check (and the similar one below) deals with issue 437, that changes + // C++ 9.2p2 this way: + // Within the class member-specification, the class is regarded as complete + // within function bodies, default arguments, exception-specifications, and + // constructor ctor-initializers (including such things in nested classes). + if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) + return false; + + // C++ 15.4p2: A type denoted in an exception-specification shall not denote + // an incomplete type. + if (RequireCompleteType(Range.getBegin(), T, + PDiag(diag::err_incomplete_in_exception_spec) << /*direct*/0 << Range)) + return true; + + // C++ 15.4p2: A type denoted in an exception-specification shall not denote + // an incomplete type a pointer or reference to an incomplete type, other + // than (cv) void*. + int kind; + if (const PointerType* IT = T->getAs<PointerType>()) { + T = IT->getPointeeType(); + kind = 1; + } else if (const ReferenceType* IT = T->getAs<ReferenceType>()) { + T = IT->getPointeeType(); + kind = 2; + } else + return false; + + // Again as before + if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) + return false; + + if (!T->isVoidType() && RequireCompleteType(Range.getBegin(), T, + PDiag(diag::err_incomplete_in_exception_spec) << kind << Range)) + return true; + + return false; +} + +/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer +/// to member to a function with an exception specification. This means that +/// it is invalid to add another level of indirection. +bool Sema::CheckDistantExceptionSpec(QualType T) { + if (const PointerType *PT = T->getAs<PointerType>()) + T = PT->getPointeeType(); + else if (const MemberPointerType *PT = T->getAs<MemberPointerType>()) + T = PT->getPointeeType(); + else + return false; + + const FunctionProtoType *FnT = T->getAs<FunctionProtoType>(); + if (!FnT) + return false; + + return FnT->hasExceptionSpec(); +} + +bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { + OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator(); + bool IsOperatorNew = OO == OO_New || OO == OO_Array_New; + bool MissingExceptionSpecification = false; + bool MissingEmptyExceptionSpecification = false; + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOptions().Microsoft) + DiagID = diag::warn_mismatched_exception_spec; + + if (!CheckEquivalentExceptionSpec(PDiag(DiagID), + PDiag(diag::note_previous_declaration), + Old->getType()->getAs<FunctionProtoType>(), + Old->getLocation(), + New->getType()->getAs<FunctionProtoType>(), + New->getLocation(), + &MissingExceptionSpecification, + &MissingEmptyExceptionSpecification, + /*AllowNoexceptAllMatchWithNoSpec=*/true, + IsOperatorNew)) + return false; + + // The failure was something other than an empty exception + // specification; return an error. + if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification) + return true; + + const FunctionProtoType *NewProto + = New->getType()->getAs<FunctionProtoType>(); + + // The new function declaration is only missing an empty exception + // specification "throw()". If the throw() specification came from a + // function in a system header that has C linkage, just add an empty + // exception specification to the "new" declaration. This is an + // egregious workaround for glibc, which adds throw() specifications + // to many libc functions as an optimization. Unfortunately, that + // optimization isn't permitted by the C++ standard, so we're forced + // to work around it here. + if (MissingEmptyExceptionSpecification && NewProto && + (Old->getLocation().isInvalid() || + Context.getSourceManager().isInSystemHeader(Old->getLocation())) && + Old->isExternC()) { + FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); + EPI.ExceptionSpecType = EST_DynamicNone; + QualType NewType = Context.getFunctionType(NewProto->getResultType(), + NewProto->arg_type_begin(), + NewProto->getNumArgs(), + EPI); + New->setType(NewType); + return false; + } + + if (MissingExceptionSpecification && NewProto) { + const FunctionProtoType *OldProto + = Old->getType()->getAs<FunctionProtoType>(); + + FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); + EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = OldProto->getNumExceptions(); + EPI.Exceptions = OldProto->exception_begin(); + } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + // FIXME: We can't just take the expression from the old prototype. It + // likely contains references to the old prototype's parameters. + } + + // Update the type of the function with the appropriate exception + // specification. + QualType NewType = Context.getFunctionType(NewProto->getResultType(), + NewProto->arg_type_begin(), + NewProto->getNumArgs(), + EPI); + New->setType(NewType); + + // If exceptions are disabled, suppress the warning about missing + // exception specifications for new and delete operators. + if (!getLangOptions().CXXExceptions) { + switch (New->getDeclName().getCXXOverloadedOperator()) { + case OO_New: + case OO_Array_New: + case OO_Delete: + case OO_Array_Delete: + if (New->getDeclContext()->isTranslationUnit()) + return false; + break; + + default: + break; + } + } + + // Warn about the lack of exception specification. + llvm::SmallString<128> ExceptionSpecString; + llvm::raw_svector_ostream OS(ExceptionSpecString); + switch (OldProto->getExceptionSpecType()) { + case EST_DynamicNone: + OS << "throw()"; + break; + + case EST_Dynamic: { + OS << "throw("; + bool OnFirstException = true; + for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(), + EEnd = OldProto->exception_end(); + E != EEnd; + ++E) { + if (OnFirstException) + OnFirstException = false; + else + OS << ", "; + + OS << E->getAsString(Context.PrintingPolicy); + } + OS << ")"; + break; + } + + case EST_BasicNoexcept: + OS << "noexcept"; + break; + + case EST_ComputedNoexcept: + OS << "noexcept("; + OldProto->getNoexceptExpr()->printPretty(OS, Context, 0, + Context.PrintingPolicy); + OS << ")"; + break; + + default: + assert(false && "This spec type is compatible with none."); + } + OS.flush(); + + SourceLocation FixItLoc; + if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) { + TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); + if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL)) + FixItLoc = PP.getLocForEndOfToken(FTLoc->getLocalRangeEnd()); + } + + if (FixItLoc.isInvalid()) + Diag(New->getLocation(), diag::warn_missing_exception_specification) + << New << OS.str(); + else { + // FIXME: This will get more complicated with C++0x + // late-specified return types. + Diag(New->getLocation(), diag::warn_missing_exception_specification) + << New << OS.str() + << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); + } + + if (!Old->getLocation().isInvalid()) + Diag(Old->getLocation(), diag::note_previous_declaration); + + return false; + } + + Diag(New->getLocation(), DiagID); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; +} + +/// CheckEquivalentExceptionSpec - Check if the two types have equivalent +/// exception specifications. Exception specifications are equivalent if +/// they allow exactly the same set of exception types. It does not matter how +/// that is achieved. See C++ [except.spec]p2. +bool Sema::CheckEquivalentExceptionSpec( + const FunctionProtoType *Old, SourceLocation OldLoc, + const FunctionProtoType *New, SourceLocation NewLoc) { + unsigned DiagID = diag::err_mismatched_exception_spec; + if (getLangOptions().Microsoft) + DiagID = diag::warn_mismatched_exception_spec; + return CheckEquivalentExceptionSpec( + PDiag(DiagID), + PDiag(diag::note_previous_declaration), + Old, OldLoc, New, NewLoc); +} + +/// CheckEquivalentExceptionSpec - Check if the two types have compatible +/// exception specifications. See C++ [except.spec]p3. +bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, + const PartialDiagnostic & NoteID, + const FunctionProtoType *Old, + SourceLocation OldLoc, + const FunctionProtoType *New, + SourceLocation NewLoc, + bool *MissingExceptionSpecification, + bool*MissingEmptyExceptionSpecification, + bool AllowNoexceptAllMatchWithNoSpec, + bool IsOperatorNew) { + // Just completely ignore this under -fno-exceptions. + if (!getLangOptions().CXXExceptions) + return false; + + if (MissingExceptionSpecification) + *MissingExceptionSpecification = false; + + if (MissingEmptyExceptionSpecification) + *MissingEmptyExceptionSpecification = false; + + // C++0x [except.spec]p3: Two exception-specifications are compatible if: + // - both are non-throwing, regardless of their form, + // - both have the form noexcept(constant-expression) and the constant- + // expressions are equivalent, + // - both are dynamic-exception-specifications that have the same set of + // adjusted types. + // + // C++0x [except.spec]p12: An exception-specifcation is non-throwing if it is + // of the form throw(), noexcept, or noexcept(constant-expression) where the + // constant-expression yields true. + // + // C++0x [except.spec]p4: If any declaration of a function has an exception- + // specifier that is not a noexcept-specification allowing all exceptions, + // all declarations [...] of that function shall have a compatible + // exception-specification. + // + // That last point basically means that noexcept(false) matches no spec. + // It's considered when AllowNoexceptAllMatchWithNoSpec is true. + + ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); + ExceptionSpecificationType NewEST = New->getExceptionSpecType(); + + assert(OldEST != EST_Delayed && NewEST != EST_Delayed && + "Shouldn't see unknown exception specifications here"); + + // Shortcut the case where both have no spec. + if (OldEST == EST_None && NewEST == EST_None) + return false; + + FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context); + FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context); + if (OldNR == FunctionProtoType::NR_BadNoexcept || + NewNR == FunctionProtoType::NR_BadNoexcept) + return false; + + // Dependent noexcept specifiers are compatible with each other, but nothing + // else. + // One noexcept is compatible with another if the argument is the same + if (OldNR == NewNR && + OldNR != FunctionProtoType::NR_NoNoexcept && + NewNR != FunctionProtoType::NR_NoNoexcept) + return false; + if (OldNR != NewNR && + OldNR != FunctionProtoType::NR_NoNoexcept && + NewNR != FunctionProtoType::NR_NoNoexcept) { + Diag(NewLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(OldLoc, NoteID); + return true; + } + + // The MS extension throw(...) is compatible with itself. + if (OldEST == EST_MSAny && NewEST == EST_MSAny) + return false; + + // It's also compatible with no spec. + if ((OldEST == EST_None && NewEST == EST_MSAny) || + (OldEST == EST_MSAny && NewEST == EST_None)) + return false; + + // It's also compatible with noexcept(false). + if (OldEST == EST_MSAny && NewNR == FunctionProtoType::NR_Throw) + return false; + if (NewEST == EST_MSAny && OldNR == FunctionProtoType::NR_Throw) + return false; + + // As described above, noexcept(false) matches no spec only for functions. + if (AllowNoexceptAllMatchWithNoSpec) { + if (OldEST == EST_None && NewNR == FunctionProtoType::NR_Throw) + return false; + if (NewEST == EST_None && OldNR == FunctionProtoType::NR_Throw) + return false; + } + + // Any non-throwing specifications are compatible. + bool OldNonThrowing = OldNR == FunctionProtoType::NR_Nothrow || + OldEST == EST_DynamicNone; + bool NewNonThrowing = NewNR == FunctionProtoType::NR_Nothrow || + NewEST == EST_DynamicNone; + if (OldNonThrowing && NewNonThrowing) + return false; + + // As a special compatibility feature, under C++0x we accept no spec and + // throw(std::bad_alloc) as equivalent for operator new and operator new[]. + // This is because the implicit declaration changed, but old code would break. + if (getLangOptions().CPlusPlus0x && IsOperatorNew) { + const FunctionProtoType *WithExceptions = 0; + if (OldEST == EST_None && NewEST == EST_Dynamic) + WithExceptions = New; + else if (OldEST == EST_Dynamic && NewEST == EST_None) + WithExceptions = Old; + if (WithExceptions && WithExceptions->getNumExceptions() == 1) { + // One has no spec, the other throw(something). If that something is + // std::bad_alloc, all conditions are met. + QualType Exception = *WithExceptions->exception_begin(); + if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { + IdentifierInfo* Name = ExRecord->getIdentifier(); + if (Name && Name->getName() == "bad_alloc") { + // It's called bad_alloc, but is it in std? + DeclContext* DC = ExRecord->getDeclContext(); + DC = DC->getEnclosingNamespaceContext(); + if (NamespaceDecl* NS = dyn_cast<NamespaceDecl>(DC)) { + IdentifierInfo* NSName = NS->getIdentifier(); + DC = DC->getParent(); + if (NSName && NSName->getName() == "std" && + DC->getEnclosingNamespaceContext()->isTranslationUnit()) { + return false; + } + } + } + } + } + } + + // At this point, the only remaining valid case is two matching dynamic + // specifications. We return here unless both specifications are dynamic. + if (OldEST != EST_Dynamic || NewEST != EST_Dynamic) { + if (MissingExceptionSpecification && Old->hasExceptionSpec() && + !New->hasExceptionSpec()) { + // The old type has an exception specification of some sort, but + // the new type does not. + *MissingExceptionSpecification = true; + + if (MissingEmptyExceptionSpecification && OldNonThrowing) { + // The old type has a throw() or noexcept(true) exception specification + // and the new type has no exception specification, and the caller asked + // to handle this itself. + *MissingEmptyExceptionSpecification = true; + } + + return true; + } + + Diag(NewLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(OldLoc, NoteID); + return true; + } + + assert(OldEST == EST_Dynamic && NewEST == EST_Dynamic && + "Exception compatibility logic error: non-dynamic spec slipped through."); + + bool Success = true; + // Both have a dynamic exception spec. Collect the first set, then compare + // to the second. + llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes; + for (FunctionProtoType::exception_iterator I = Old->exception_begin(), + E = Old->exception_end(); I != E; ++I) + OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType()); + + for (FunctionProtoType::exception_iterator I = New->exception_begin(), + E = New->exception_end(); I != E && Success; ++I) { + CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType(); + if(OldTypes.count(TypePtr)) + NewTypes.insert(TypePtr); + else + Success = false; + } + + Success = Success && OldTypes.size() == NewTypes.size(); + + if (Success) { + return false; + } + Diag(NewLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(OldLoc, NoteID); + return true; +} + +/// CheckExceptionSpecSubset - Check whether the second function type's +/// exception specification is a subset (or equivalent) of the first function +/// type. This is used by override and pointer assignment checks. +bool Sema::CheckExceptionSpecSubset( + const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, + const FunctionProtoType *Superset, SourceLocation SuperLoc, + const FunctionProtoType *Subset, SourceLocation SubLoc) { + + // Just auto-succeed under -fno-exceptions. + if (!getLangOptions().CXXExceptions) + return false; + + // FIXME: As usual, we could be more specific in our error messages, but + // that better waits until we've got types with source locations. + + if (!SubLoc.isValid()) + SubLoc = SuperLoc; + + ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType(); + + // If superset contains everything, we're done. + if (SuperEST == EST_None || SuperEST == EST_MSAny) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + // If there are dependent noexcept specs, assume everything is fine. Unlike + // with the equivalency check, this is safe in this case, because we don't + // want to merge declarations. Checks after instantiation will catch any + // omissions we make here. + // We also shortcut checking if a noexcept expression was bad. + + FunctionProtoType::NoexceptResult SuperNR =Superset->getNoexceptSpec(Context); + if (SuperNR == FunctionProtoType::NR_BadNoexcept || + SuperNR == FunctionProtoType::NR_Dependent) + return false; + + // Another case of the superset containing everything. + if (SuperNR == FunctionProtoType::NR_Throw) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); + + assert(SuperEST != EST_Delayed && SubEST != EST_Delayed && + "Shouldn't see unknown exception specifications here"); + + // It does not. If the subset contains everything, we've failed. + if (SubEST == EST_None || SubEST == EST_MSAny) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + FunctionProtoType::NoexceptResult SubNR = Subset->getNoexceptSpec(Context); + if (SubNR == FunctionProtoType::NR_BadNoexcept || + SubNR == FunctionProtoType::NR_Dependent) + return false; + + // Another case of the subset containing everything. + if (SubNR == FunctionProtoType::NR_Throw) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + // If the subset contains nothing, we're done. + if (SubEST == EST_DynamicNone || SubNR == FunctionProtoType::NR_Nothrow) + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); + + // Otherwise, if the superset contains nothing, we've failed. + if (SuperEST == EST_DynamicNone || SuperNR == FunctionProtoType::NR_Nothrow) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + + assert(SuperEST == EST_Dynamic && SubEST == EST_Dynamic && + "Exception spec subset: non-dynamic case slipped through."); + + // Neither contains everything or nothing. Do a proper comparison. + for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(), + SubE = Subset->exception_end(); SubI != SubE; ++SubI) { + // Take one type from the subset. + QualType CanonicalSubT = Context.getCanonicalType(*SubI); + // Unwrap pointers and references so that we can do checks within a class + // hierarchy. Don't unwrap member pointers; they don't have hierarchy + // conversions on the pointee. + bool SubIsPointer = false; + if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>()) + CanonicalSubT = RefTy->getPointeeType(); + if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) { + CanonicalSubT = PtrTy->getPointeeType(); + SubIsPointer = true; + } + bool SubIsClass = CanonicalSubT->isRecordType(); + CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType(); + + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + + bool Contained = false; + // Make sure it's in the superset. + for (FunctionProtoType::exception_iterator SuperI = + Superset->exception_begin(), SuperE = Superset->exception_end(); + SuperI != SuperE; ++SuperI) { + QualType CanonicalSuperT = Context.getCanonicalType(*SuperI); + // SubT must be SuperT or derived from it, or pointer or reference to + // such types. + if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>()) + CanonicalSuperT = RefTy->getPointeeType(); + if (SubIsPointer) { + if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>()) + CanonicalSuperT = PtrTy->getPointeeType(); + else { + continue; + } + } + CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType(); + // If the types are the same, move on to the next type in the subset. + if (CanonicalSubT == CanonicalSuperT) { + Contained = true; + break; + } + + // Otherwise we need to check the inheritance. + if (!SubIsClass || !CanonicalSuperT->isRecordType()) + continue; + + Paths.clear(); + if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths)) + continue; + + if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT))) + continue; + + // Do this check from a context without privileges. + switch (CheckBaseClassAccess(SourceLocation(), + CanonicalSuperT, CanonicalSubT, + Paths.front(), + /*Diagnostic*/ 0, + /*ForceCheck*/ true, + /*ForceUnprivileged*/ true)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: + llvm_unreachable("access check dependent for unprivileged context"); + break; + case AR_delayed: + llvm_unreachable("access check delayed in non-declaration"); + break; + } + + Contained = true; + break; + } + if (!Contained) { + Diag(SubLoc, DiagID); + if (NoteID.getDiagID() != 0) + Diag(SuperLoc, NoteID); + return true; + } + } + // We've run half the gauntlet. + return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc); +} + +static bool CheckSpecForTypesEquivalent(Sema &S, + const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, + QualType Target, SourceLocation TargetLoc, + QualType Source, SourceLocation SourceLoc) +{ + const FunctionProtoType *TFunc = GetUnderlyingFunction(Target); + if (!TFunc) + return false; + const FunctionProtoType *SFunc = GetUnderlyingFunction(Source); + if (!SFunc) + return false; + + return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, + SFunc, SourceLoc); +} + +/// CheckParamExceptionSpec - Check if the parameter and return types of the +/// two functions have equivalent exception specs. This is part of the +/// assignment and override compatibility check. We do not check the parameters +/// of parameter function pointers recursively, as no sane programmer would +/// even be able to write such a function type. +bool Sema::CheckParamExceptionSpec(const PartialDiagnostic & NoteID, + const FunctionProtoType *Target, SourceLocation TargetLoc, + const FunctionProtoType *Source, SourceLocation SourceLoc) +{ + if (CheckSpecForTypesEquivalent(*this, + PDiag(diag::err_deep_exception_specs_differ) << 0, + PDiag(), + Target->getResultType(), TargetLoc, + Source->getResultType(), SourceLoc)) + return true; + + // We shouldn't even be testing this unless the arguments are otherwise + // compatible. + assert(Target->getNumArgs() == Source->getNumArgs() && + "Functions have different argument counts."); + for (unsigned i = 0, E = Target->getNumArgs(); i != E; ++i) { + if (CheckSpecForTypesEquivalent(*this, + PDiag(diag::err_deep_exception_specs_differ) << 1, + PDiag(), + Target->getArgType(i), TargetLoc, + Source->getArgType(i), SourceLoc)) + return true; + } + return false; +} + +bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) +{ + // First we check for applicability. + // Target type must be a function, function pointer or function reference. + const FunctionProtoType *ToFunc = GetUnderlyingFunction(ToType); + if (!ToFunc) + return false; + + // SourceType must be a function or function pointer. + const FunctionProtoType *FromFunc = GetUnderlyingFunction(From->getType()); + if (!FromFunc) + return false; + + // Now we've got the correct types on both sides, check their compatibility. + // This means that the source of the conversion can only throw a subset of + // the exceptions of the target, and any exception specs on arguments or + // return types must be equivalent. + return CheckExceptionSpecSubset(PDiag(diag::err_incompatible_exception_specs), + PDiag(), ToFunc, + From->getSourceRange().getBegin(), + FromFunc, SourceLocation()); +} + +bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + if (getLangOptions().CPlusPlus0x && isa<CXXDestructorDecl>(New)) { + // Don't check uninstantiated template destructors at all. We can only + // synthesize correct specs after the template is instantiated. + if (New->getParent()->isDependentType()) + return false; + if (New->getParent()->isBeingDefined()) { + // The destructor might be updated once the definition is finished. So + // remember it and check later. + DelayedDestructorExceptionSpecChecks.push_back(std::make_pair( + cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old))); + return false; + } + } + unsigned DiagID = diag::err_override_exception_spec; + if (getLangOptions().Microsoft) + DiagID = diag::warn_override_exception_spec; + return CheckExceptionSpecSubset(PDiag(DiagID), + PDiag(diag::note_overridden_virtual_function), + Old->getType()->getAs<FunctionProtoType>(), + Old->getLocation(), + New->getType()->getAs<FunctionProtoType>(), + New->getLocation()); +} + +} // end namespace clang diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp new file mode 100644 index 0000000..0549e94 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -0,0 +1,10954 @@ +//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for expressions. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/AnalysisBasedWarnings.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Lex/LiteralSupport.h" +#include "clang/Lex/Preprocessor.h" +#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 +/// emit any corresponding diagnostics. +/// +/// This routine diagnoses various problems with referencing +/// declarations that can occur when using a declaration. For example, +/// it might warn if a deprecated or unavailable declaration is being +/// used, or produce an error (and return true) if a C++0x deleted +/// function is being used. +/// +/// If IgnoreDeprecated is set to true, this should not warn about deprecated +/// decls. +/// +/// \returns true if there was an error (this declaration cannot be +/// referenced), false otherwise. +/// +bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass) { + if (getLangOptions().CPlusPlus && isa<FunctionDecl>(D)) { + // If there were any diagnostics suppressed by template argument deduction, + // emit them now. + llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator + Pos = SuppressedDiagnostics.find(D->getCanonicalDecl()); + if (Pos != SuppressedDiagnostics.end()) { + llvm::SmallVectorImpl<PartialDiagnosticAt> &Suppressed = Pos->second; + for (unsigned I = 0, N = Suppressed.size(); I != N; ++I) + Diag(Suppressed[I].first, Suppressed[I].second); + + // Clear out the list of suppressed diagnostics, so that we don't emit + // them again for this specialization. However, we don't obsolete this + // entry from the table, because we want to avoid ever emitting these + // diagnostics again. + Suppressed.clear(); + } + } + + // See if this is an auto-typed variable whose initializer we are parsing. + if (ParsingInitForAutoVars.count(D)) { + Diag(Loc, diag::err_auto_variable_cannot_appear_in_own_initializer) + << D->getDeclName(); + return true; + } + + // See if this is a deleted function. + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (FD->isDeleted()) { + Diag(Loc, diag::err_deleted_function_use); + Diag(D->getLocation(), diag::note_unavailable_here) << true; + return true; + } + } + + // See if this declaration is unavailable or deprecated. + std::string Message; + switch (D->getAvailability(&Message)) { + case AR_Available: + case AR_NotYetIntroduced: + break; + + case AR_Deprecated: + EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass); + break; + + case AR_Unavailable: + if (Message.empty()) { + if (!UnknownObjCClass) + Diag(Loc, diag::err_unavailable) << D->getDeclName(); + else + Diag(Loc, diag::warn_unavailable_fwdclass_message) + << D->getDeclName(); + } + else + Diag(Loc, diag::err_unavailable_message) + << D->getDeclName() << Message; + Diag(D->getLocation(), diag::note_unavailable_here) << 0; + break; + } + + // Warn if this is used but marked unused. + if (D->hasAttr<UnusedAttr>()) + Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); + + return false; +} + +/// \brief Retrieve the message suffix that should be added to a +/// diagnostic complaining about the given function being deleted or +/// unavailable. +std::string Sema::getDeletedOrUnavailableSuffix(const FunctionDecl *FD) { + // FIXME: C++0x implicitly-deleted special member functions could be + // detected here so that we could improve diagnostics to say, e.g., + // "base class 'A' had a deleted copy constructor". + if (FD->isDeleted()) + return std::string(); + + std::string Message; + if (FD->getAvailability(&Message)) + return ": " + Message; + + return std::string(); +} + +/// DiagnoseSentinelCalls - This routine checks on method dispatch calls +/// (and other functions in future), which have been declared with sentinel +/// attribute. It warns if call does not have the sentinel argument. +/// +void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, + Expr **Args, unsigned NumArgs) { + const SentinelAttr *attr = D->getAttr<SentinelAttr>(); + if (!attr) + return; + + // FIXME: In C++0x, if any of the arguments are parameter pack + // expansions, we can't check for the sentinel now. + int sentinelPos = attr->getSentinel(); + int nullPos = attr->getNullPos(); + + // FIXME. ObjCMethodDecl and FunctionDecl need be derived from the same common + // base class. Then we won't be needing two versions of the same code. + unsigned int i = 0; + bool warnNotEnoughArgs = false; + int isMethod = 0; + if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { + // skip over named parameters. + ObjCMethodDecl::param_iterator P, E = MD->param_end(); + for (P = MD->param_begin(); (P != E && i < NumArgs); ++P) { + if (nullPos) + --nullPos; + else + ++i; + } + warnNotEnoughArgs = (P != E || i >= NumArgs); + isMethod = 1; + } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // skip over named parameters. + ObjCMethodDecl::param_iterator P, E = FD->param_end(); + for (P = FD->param_begin(); (P != E && i < NumArgs); ++P) { + if (nullPos) + --nullPos; + else + ++i; + } + warnNotEnoughArgs = (P != E || i >= NumArgs); + } else if (VarDecl *V = dyn_cast<VarDecl>(D)) { + // block or function pointer call. + QualType Ty = V->getType(); + if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) { + const FunctionType *FT = Ty->isFunctionPointerType() + ? Ty->getAs<PointerType>()->getPointeeType()->getAs<FunctionType>() + : Ty->getAs<BlockPointerType>()->getPointeeType()->getAs<FunctionType>(); + if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT)) { + unsigned NumArgsInProto = Proto->getNumArgs(); + unsigned k; + for (k = 0; (k != NumArgsInProto && i < NumArgs); k++) { + if (nullPos) + --nullPos; + else + ++i; + } + warnNotEnoughArgs = (k != NumArgsInProto || i >= NumArgs); + } + if (Ty->isBlockPointerType()) + isMethod = 2; + } else + return; + } else + return; + + if (warnNotEnoughArgs) { + Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName(); + Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; + return; + } + int sentinel = i; + while (sentinelPos > 0 && i < NumArgs-1) { + --sentinelPos; + ++i; + } + if (sentinelPos > 0) { + Diag(Loc, diag::warn_not_enough_argument) << D->getDeclName(); + Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; + return; + } + while (i < NumArgs-1) { + ++i; + ++sentinel; + } + Expr *sentinelExpr = Args[sentinel]; + if (!sentinelExpr) return; + if (sentinelExpr->isTypeDependent()) return; + if (sentinelExpr->isValueDependent()) return; + + // nullptr_t is always treated as null. + if (sentinelExpr->getType()->isNullPtrType()) return; + + if (sentinelExpr->getType()->isAnyPointerType() && + sentinelExpr->IgnoreParenCasts()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) + return; + + // Unfortunately, __null has type 'int'. + if (isa<GNUNullExpr>(sentinelExpr)) return; + + Diag(Loc, diag::warn_missing_sentinel) << isMethod; + Diag(D->getLocation(), diag::note_sentinel_here) << isMethod; +} + +SourceRange Sema::getExprRange(ExprTy *E) const { + Expr *Ex = (Expr *)E; + return Ex? Ex->getSourceRange() : SourceRange(); +} + +//===----------------------------------------------------------------------===// +// Standard Promotions and Conversions +//===----------------------------------------------------------------------===// + +/// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). +ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { + QualType Ty = E->getType(); + assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); + + if (Ty->isFunctionType()) + E = ImpCastExprToType(E, Context.getPointerType(Ty), + CK_FunctionToPointerDecay).take(); + else if (Ty->isArrayType()) { + // In C90 mode, arrays only promote to pointers if the array expression is + // an lvalue. The relevant legalese is C90 6.2.2.1p3: "an lvalue that has + // type 'array of type' is converted to an expression that has type 'pointer + // to type'...". In C99 this was changed to: C99 6.3.2.1p3: "an expression + // that has type 'array of type' ...". The relevant change is "an lvalue" + // (C90) to "an expression" (C99). + // + // C++ 4.2p1: + // An lvalue or rvalue of type "array of N T" or "array of unknown bound of + // T" can be converted to an rvalue of type "pointer to T". + // + if (getLangOptions().C99 || getLangOptions().CPlusPlus || E->isLValue()) + E = ImpCastExprToType(E, Context.getArrayDecayedType(Ty), + CK_ArrayToPointerDecay).take(); + } + return Owned(E); +} + +static void CheckForNullPointerDereference(Sema &S, Expr *E) { + // Check to see if we are dereferencing a null pointer. If so, + // and if not volatile-qualified, this is undefined behavior that the + // optimizer will delete, so warn about it. People sometimes try to use this + // to get a deterministic trap and are surprised by clang's behavior. This + // only handles the pattern "*null", which is a very syntactic check. + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts())) + if (UO->getOpcode() == UO_Deref && + UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) && + !UO->getType().isVolatileQualified()) { + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::warn_indirection_through_null) + << UO->getSubExpr()->getSourceRange()); + S.DiagRuntimeBehavior(UO->getOperatorLoc(), UO, + S.PDiag(diag::note_indirection_through_null)); + } +} + +ExprResult Sema::DefaultLvalueConversion(Expr *E) { + // C++ [conv.lval]p1: + // A glvalue of a non-function, non-array type T can be + // converted to a prvalue. + if (!E->isGLValue()) return Owned(E); + + QualType T = E->getType(); + assert(!T.isNull() && "r-value conversion on typeless expression?"); + + // Create a load out of an ObjCProperty l-value, if necessary. + if (E->getObjectKind() == OK_ObjCProperty) { + ExprResult Res = ConvertPropertyForRValue(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + if (!E->isGLValue()) + return Owned(E); + } + + // We don't want to throw lvalue-to-rvalue casts on top of + // expressions of certain types in C++. + if (getLangOptions().CPlusPlus && + (E->getType() == Context.OverloadTy || + T->isDependentType() || + T->isRecordType())) + return Owned(E); + + // The C standard is actually really unclear on this point, and + // DR106 tells us what the result should be but not why. It's + // generally best to say that void types just doesn't undergo + // lvalue-to-rvalue at all. Note that expressions of unqualified + // 'void' type are never l-values, but qualified void can be. + if (T->isVoidType()) + return Owned(E); + + CheckForNullPointerDereference(*this, E); + + // C++ [conv.lval]p1: + // [...] If T is a non-class type, the type of the prvalue is the + // cv-unqualified version of T. Otherwise, the type of the + // rvalue is T. + // + // C99 6.3.2.1p2: + // If the lvalue has qualified type, the value has the unqualified + // version of the type of the lvalue; otherwise, the value has the + // type of the lvalue. + if (T.hasQualifiers()) + T = T.getUnqualifiedType(); + + CheckArrayAccess(E); + + return Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, + E, 0, VK_RValue)); +} + +ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) { + ExprResult Res = DefaultFunctionArrayConversion(E); + if (Res.isInvalid()) + return ExprError(); + Res = DefaultLvalueConversion(Res.take()); + if (Res.isInvalid()) + return ExprError(); + return move(Res); +} + + +/// UsualUnaryConversions - Performs various conversions that are common to most +/// operators (C99 6.3). The conversions of array and function types are +/// sometimes suppressed. For example, the array->pointer conversion doesn't +/// apply if the array is an argument to the sizeof or address (&) operators. +/// In these instances, this routine should *not* be called. +ExprResult Sema::UsualUnaryConversions(Expr *E) { + // First, convert to an r-value. + ExprResult Res = DefaultFunctionArrayLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + + QualType Ty = E->getType(); + assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); + + // Try to perform integral promotions if the object has a theoretically + // promotable type. + if (Ty->isIntegralOrUnscopedEnumerationType()) { + // C99 6.3.1.1p2: + // + // The following may be used in an expression wherever an int or + // unsigned int may be used: + // - an object or expression with an integer type whose integer + // conversion rank is less than or equal to the rank of int + // and unsigned int. + // - A bit-field of type _Bool, int, signed int, or unsigned int. + // + // If an int can represent all values of the original type, the + // value is converted to an int; otherwise, it is converted to an + // unsigned int. These are called the integer promotions. All + // other types are unchanged by the integer promotions. + + QualType PTy = Context.isPromotableBitField(E); + if (!PTy.isNull()) { + E = ImpCastExprToType(E, PTy, CK_IntegralCast).take(); + return Owned(E); + } + if (Ty->isPromotableIntegerType()) { + QualType PT = Context.getPromotedIntegerType(Ty); + E = ImpCastExprToType(E, PT, CK_IntegralCast).take(); + return Owned(E); + } + } + return Owned(E); +} + +/// DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that +/// do not have a prototype. Arguments that have type float are promoted to +/// double. All other argument types are converted by UsualUnaryConversions(). +ExprResult Sema::DefaultArgumentPromotion(Expr *E) { + QualType Ty = E->getType(); + assert(!Ty.isNull() && "DefaultArgumentPromotion - missing type"); + + ExprResult Res = UsualUnaryConversions(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + + // If this is a 'float' (CVR qualified or typedef) promote to double. + if (Ty->isSpecificBuiltinType(BuiltinType::Float)) + E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take(); + + return Owned(E); +} + +/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but +/// will warn if the resulting type is not a POD type, and rejects ObjC +/// interfaces passed by value. +ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, + FunctionDecl *FDecl) { + ExprResult ExprRes = DefaultArgumentPromotion(E); + if (ExprRes.isInvalid()) + return ExprError(); + E = ExprRes.take(); + + // __builtin_va_start takes the second argument as a "varargs" argument, but + // it doesn't actually do anything with it. It doesn't need to be non-pod + // etc. + if (FDecl && FDecl->getBuiltinID() == Builtin::BI__builtin_va_start) + return Owned(E); + + // Don't allow one to pass an Objective-C interface to a vararg. + if (E->getType()->isObjCObjectType() && + DiagRuntimeBehavior(E->getLocStart(), 0, + PDiag(diag::err_cannot_pass_objc_interface_to_vararg) + << E->getType() << CT)) + return ExprError(); + + if (!E->getType()->isPODType()) { + // C++0x [expr.call]p7: + // Passing a potentially-evaluated argument of class type (Clause 9) + // having a non-trivial copy constructor, a non-trivial move constructor, + // or a non-trivial destructor, with no corresponding parameter, + // is conditionally-supported with implementation-defined semantics. + bool TrivialEnough = false; + if (getLangOptions().CPlusPlus0x && !E->getType()->isDependentType()) { + if (CXXRecordDecl *Record = E->getType()->getAsCXXRecordDecl()) { + if (Record->hasTrivialCopyConstructor() && + Record->hasTrivialMoveConstructor() && + Record->hasTrivialDestructor()) + TrivialEnough = true; + } + } + + if (TrivialEnough) { + // Nothing to diagnose. This is okay. + } else if (DiagRuntimeBehavior(E->getLocStart(), 0, + PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) + << getLangOptions().CPlusPlus0x << E->getType() + << CT)) { + // Turn this into a trap. + CXXScopeSpec SS; + UnqualifiedId Name; + Name.setIdentifier(PP.getIdentifierInfo("__builtin_trap"), + E->getLocStart()); + ExprResult TrapFn = ActOnIdExpression(TUScope, SS, Name, true, false); + if (TrapFn.isInvalid()) + return ExprError(); + + ExprResult Call = ActOnCallExpr(TUScope, TrapFn.get(), E->getLocStart(), + MultiExprArg(), E->getLocEnd()); + if (Call.isInvalid()) + return ExprError(); + + ExprResult Comma = ActOnBinOp(TUScope, E->getLocStart(), tok::comma, + Call.get(), E); + if (Comma.isInvalid()) + return ExprError(); + + E = Comma.get(); + } + } + + return Owned(E); +} + +/// UsualArithmeticConversions - Performs various conversions that are common to +/// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this +/// routine returns the first non-arithmetic type found. The client is +/// responsible for emitting appropriate error diagnostics. +/// FIXME: verify the conversion rules for "complex int" are consistent with +/// GCC. +QualType Sema::UsualArithmeticConversions(ExprResult &lhsExpr, ExprResult &rhsExpr, + bool isCompAssign) { + if (!isCompAssign) { + lhsExpr = UsualUnaryConversions(lhsExpr.take()); + if (lhsExpr.isInvalid()) + return QualType(); + } + + rhsExpr = UsualUnaryConversions(rhsExpr.take()); + if (rhsExpr.isInvalid()) + return QualType(); + + // For conversion purposes, we ignore any qualifiers. + // For example, "const float" and "float" are equivalent. + QualType lhs = + Context.getCanonicalType(lhsExpr.get()->getType()).getUnqualifiedType(); + QualType rhs = + Context.getCanonicalType(rhsExpr.get()->getType()).getUnqualifiedType(); + + // If both types are identical, no conversion is needed. + if (lhs == rhs) + return lhs; + + // If either side is a non-arithmetic type (e.g. a pointer), we are done. + // The caller can deal with this (e.g. pointer + int). + if (!lhs->isArithmeticType() || !rhs->isArithmeticType()) + return lhs; + + // Apply unary and bitfield promotions to the LHS's type. + QualType lhs_unpromoted = lhs; + if (lhs->isPromotableIntegerType()) + lhs = Context.getPromotedIntegerType(lhs); + QualType LHSBitfieldPromoteTy = Context.isPromotableBitField(lhsExpr.get()); + if (!LHSBitfieldPromoteTy.isNull()) + lhs = LHSBitfieldPromoteTy; + if (lhs != lhs_unpromoted && !isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), lhs, CK_IntegralCast); + + // If both types are identical, no conversion is needed. + if (lhs == rhs) + return lhs; + + // At this point, we have two different arithmetic types. + + // Handle complex types first (C99 6.3.1.8p1). + bool LHSComplexFloat = lhs->isComplexType(); + bool RHSComplexFloat = rhs->isComplexType(); + if (LHSComplexFloat || RHSComplexFloat) { + // if we have an integer operand, the result is the complex type. + + if (!RHSComplexFloat && !rhs->isRealFloatingType()) { + if (rhs->isIntegerType()) { + QualType fp = cast<ComplexType>(lhs)->getElementType(); + rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_IntegralToFloating); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex); + } else { + assert(rhs->isComplexIntegerType()); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexToFloatingComplex); + } + return lhs; + } + + if (!LHSComplexFloat && !lhs->isRealFloatingType()) { + if (!isCompAssign) { + // int -> float -> _Complex float + if (lhs->isIntegerType()) { + QualType fp = cast<ComplexType>(rhs)->getElementType(); + lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_IntegralToFloating); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex); + } else { + assert(lhs->isComplexIntegerType()); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexToFloatingComplex); + } + } + return rhs; + } + + // This handles complex/complex, complex/float, or float/complex. + // When both operands are complex, the shorter operand is converted to the + // type of the longer, and that is the type of the result. This corresponds + // to what is done when combining two real floating-point operands. + // The fun begins when size promotion occur across type domains. + // From H&S 6.3.4: When one operand is complex and the other is a real + // floating-point type, the less precise type is converted, within it's + // real or complex domain, to the precision of the other type. For example, + // when combining a "long double" with a "double _Complex", the + // "double _Complex" is promoted to "long double _Complex". + int order = Context.getFloatingTypeOrder(lhs, rhs); + + // If both are complex, just cast to the more precise type. + if (LHSComplexFloat && RHSComplexFloat) { + if (order > 0) { + // _Complex float -> _Complex double + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingComplexCast); + return lhs; + + } else if (order < 0) { + // _Complex float -> _Complex double + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingComplexCast); + return rhs; + } + return lhs; + } + + // If just the LHS is complex, the RHS needs to be converted, + // and the LHS might need to be promoted. + if (LHSComplexFloat) { + if (order > 0) { // LHS is wider + // float -> _Complex double + QualType fp = cast<ComplexType>(lhs)->getElementType(); + rhsExpr = ImpCastExprToType(rhsExpr.take(), fp, CK_FloatingCast); + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingRealToComplex); + return lhs; + } + + // RHS is at least as wide. Find its corresponding complex type. + QualType result = (order == 0 ? lhs : Context.getComplexType(rhs)); + + // double -> _Complex double + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex); + + // _Complex float -> _Complex double + if (!isCompAssign && order < 0) + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingComplexCast); + + return result; + } + + // Just the RHS is complex, so the LHS needs to be converted + // and the RHS might need to be promoted. + assert(RHSComplexFloat); + + if (order < 0) { // RHS is wider + // float -> _Complex double + if (!isCompAssign) { + QualType fp = cast<ComplexType>(rhs)->getElementType(); + lhsExpr = ImpCastExprToType(lhsExpr.take(), fp, CK_FloatingCast); + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingRealToComplex); + } + return rhs; + } + + // LHS is at least as wide. Find its corresponding complex type. + QualType result = (order == 0 ? rhs : Context.getComplexType(lhs)); + + // double -> _Complex double + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex); + + // _Complex float -> _Complex double + if (order > 0) + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingComplexCast); + + return result; + } + + // Now handle "real" floating types (i.e. float, double, long double). + bool LHSFloat = lhs->isRealFloatingType(); + bool RHSFloat = rhs->isRealFloatingType(); + if (LHSFloat || RHSFloat) { + // If we have two real floating types, convert the smaller operand + // to the bigger result. + if (LHSFloat && RHSFloat) { + int order = Context.getFloatingTypeOrder(lhs, rhs); + if (order > 0) { + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_FloatingCast); + return lhs; + } + + assert(order < 0 && "illegal float comparison"); + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_FloatingCast); + return rhs; + } + + // If we have an integer operand, the result is the real floating type. + if (LHSFloat) { + if (rhs->isIntegerType()) { + // Convert rhs to the lhs floating point type. + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralToFloating); + return lhs; + } + + // Convert both sides to the appropriate complex float. + assert(rhs->isComplexIntegerType()); + QualType result = Context.getComplexType(lhs); + + // _Complex int -> _Complex float + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralComplexToFloatingComplex); + + // float -> _Complex float + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_FloatingRealToComplex); + + return result; + } + + assert(RHSFloat); + if (lhs->isIntegerType()) { + // Convert lhs to the rhs floating point type. + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralToFloating); + return rhs; + } + + // Convert both sides to the appropriate complex float. + assert(lhs->isComplexIntegerType()); + QualType result = Context.getComplexType(rhs); + + // _Complex int -> _Complex float + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralComplexToFloatingComplex); + + // float -> _Complex float + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_FloatingRealToComplex); + + return result; + } + + // Handle GCC complex int extension. + // FIXME: if the operands are (int, _Complex long), we currently + // don't promote the complex. Also, signedness? + const ComplexType *lhsComplexInt = lhs->getAsComplexIntegerType(); + const ComplexType *rhsComplexInt = rhs->getAsComplexIntegerType(); + if (lhsComplexInt && rhsComplexInt) { + int order = Context.getIntegerTypeOrder(lhsComplexInt->getElementType(), + rhsComplexInt->getElementType()); + assert(order && "inequal types with equal element ordering"); + if (order > 0) { + // _Complex int -> _Complex long + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralComplexCast); + return lhs; + } + + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralComplexCast); + return rhs; + } else if (lhsComplexInt) { + // int -> _Complex int + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralRealToComplex); + return lhs; + } else if (rhsComplexInt) { + // int -> _Complex int + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralRealToComplex); + return rhs; + } + + // Finally, we have two differing integer types. + // The rules for this case are in C99 6.3.1.8 + int compare = Context.getIntegerTypeOrder(lhs, rhs); + bool lhsSigned = lhs->hasSignedIntegerRepresentation(), + rhsSigned = rhs->hasSignedIntegerRepresentation(); + if (lhsSigned == rhsSigned) { + // Same signedness; use the higher-ranked type + if (compare >= 0) { + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); + return lhs; + } else if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); + return rhs; + } else if (compare != (lhsSigned ? 1 : -1)) { + // The unsigned type has greater than or equal rank to the + // signed type, so use the unsigned type + if (rhsSigned) { + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); + return lhs; + } else if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); + return rhs; + } else if (Context.getIntWidth(lhs) != Context.getIntWidth(rhs)) { + // The two types are different widths; if we are here, that + // means the signed type is larger than the unsigned type, so + // use the signed type. + if (lhsSigned) { + rhsExpr = ImpCastExprToType(rhsExpr.take(), lhs, CK_IntegralCast); + return lhs; + } else if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), rhs, CK_IntegralCast); + return rhs; + } else { + // The signed type is higher-ranked than the unsigned type, + // but isn't actually any bigger (like unsigned int and long + // on most 32-bit systems). Use the unsigned type corresponding + // to the signed type. + QualType result = + Context.getCorrespondingUnsignedType(lhsSigned ? lhs : rhs); + rhsExpr = ImpCastExprToType(rhsExpr.take(), result, CK_IntegralCast); + if (!isCompAssign) + lhsExpr = ImpCastExprToType(lhsExpr.take(), result, CK_IntegralCast); + return result; + } +} + +//===----------------------------------------------------------------------===// +// Semantic Analysis for various Expression Types +//===----------------------------------------------------------------------===// + + +ExprResult +Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + MultiTypeArg types, + MultiExprArg exprs) { + unsigned NumAssocs = types.size(); + assert(NumAssocs == exprs.size()); + + ParsedType *ParsedTypes = types.release(); + Expr **Exprs = exprs.release(); + + TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs]; + for (unsigned i = 0; i < NumAssocs; ++i) { + if (ParsedTypes[i]) + (void) GetTypeFromParser(ParsedTypes[i], &Types[i]); + else + Types[i] = 0; + } + + ExprResult ER = CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr, Types, Exprs, + NumAssocs); + delete [] Types; + return ER; +} + +ExprResult +Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs) { + bool TypeErrorFound = false, + IsResultDependent = ControllingExpr->isTypeDependent(), + ContainsUnexpandedParameterPack + = ControllingExpr->containsUnexpandedParameterPack(); + + for (unsigned i = 0; i < NumAssocs; ++i) { + if (Exprs[i]->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + + if (Types[i]) { + if (Types[i]->getType()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + + if (Types[i]->getType()->isDependentType()) { + IsResultDependent = true; + } else { + // C1X 6.5.1.1p2 "The type name in a generic association shall specify a + // complete object type other than a variably modified type." + unsigned D = 0; + if (Types[i]->getType()->isIncompleteType()) + D = diag::err_assoc_type_incomplete; + else if (!Types[i]->getType()->isObjectType()) + D = diag::err_assoc_type_nonobject; + else if (Types[i]->getType()->isVariablyModifiedType()) + D = diag::err_assoc_type_variably_modified; + + if (D != 0) { + Diag(Types[i]->getTypeLoc().getBeginLoc(), D) + << Types[i]->getTypeLoc().getSourceRange() + << Types[i]->getType(); + TypeErrorFound = true; + } + + // C1X 6.5.1.1p2 "No two generic associations in the same generic + // selection shall specify compatible types." + for (unsigned j = i+1; j < NumAssocs; ++j) + if (Types[j] && !Types[j]->getType()->isDependentType() && + Context.typesAreCompatible(Types[i]->getType(), + Types[j]->getType())) { + Diag(Types[j]->getTypeLoc().getBeginLoc(), + diag::err_assoc_compatible_types) + << Types[j]->getTypeLoc().getSourceRange() + << Types[j]->getType() + << Types[i]->getType(); + Diag(Types[i]->getTypeLoc().getBeginLoc(), + diag::note_compat_assoc) + << Types[i]->getTypeLoc().getSourceRange() + << Types[i]->getType(); + TypeErrorFound = true; + } + } + } + } + if (TypeErrorFound) + return ExprError(); + + // If we determined that the generic selection is result-dependent, don't + // try to compute the result expression. + if (IsResultDependent) + return Owned(new (Context) GenericSelectionExpr( + Context, KeyLoc, ControllingExpr, + Types, Exprs, NumAssocs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack)); + + llvm::SmallVector<unsigned, 1> CompatIndices; + unsigned DefaultIndex = -1U; + for (unsigned i = 0; i < NumAssocs; ++i) { + if (!Types[i]) + DefaultIndex = i; + else if (Context.typesAreCompatible(ControllingExpr->getType(), + Types[i]->getType())) + CompatIndices.push_back(i); + } + + // C1X 6.5.1.1p2 "The controlling expression of a generic selection shall have + // type compatible with at most one of the types named in its generic + // association list." + if (CompatIndices.size() > 1) { + // We strip parens here because the controlling expression is typically + // parenthesized in macro definitions. + ControllingExpr = ControllingExpr->IgnoreParens(); + Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_multi_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType() + << (unsigned) CompatIndices.size(); + for (llvm::SmallVector<unsigned, 1>::iterator I = CompatIndices.begin(), + E = CompatIndices.end(); I != E; ++I) { + Diag(Types[*I]->getTypeLoc().getBeginLoc(), + diag::note_compat_assoc) + << Types[*I]->getTypeLoc().getSourceRange() + << Types[*I]->getType(); + } + return ExprError(); + } + + // C1X 6.5.1.1p2 "If a generic selection has no default generic association, + // its controlling expression shall have type compatible with exactly one of + // the types named in its generic association list." + if (DefaultIndex == -1U && CompatIndices.size() == 0) { + // We strip parens here because the controlling expression is typically + // parenthesized in macro definitions. + ControllingExpr = ControllingExpr->IgnoreParens(); + Diag(ControllingExpr->getLocStart(), diag::err_generic_sel_no_match) + << ControllingExpr->getSourceRange() << ControllingExpr->getType(); + return ExprError(); + } + + // C1X 6.5.1.1p3 "If a generic selection has a generic association with a + // type name that is compatible with the type of the controlling expression, + // then the result expression of the generic selection is the expression + // in that generic association. Otherwise, the result expression of the + // generic selection is the expression in the default generic association." + unsigned ResultIndex = + CompatIndices.size() ? CompatIndices[0] : DefaultIndex; + + return Owned(new (Context) GenericSelectionExpr( + Context, KeyLoc, ControllingExpr, + Types, Exprs, NumAssocs, DefaultLoc, + RParenLoc, ContainsUnexpandedParameterPack, + ResultIndex)); +} + +/// ActOnStringLiteral - The specified tokens were lexed as pasted string +/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string +/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from +/// multiple tokens. However, the common case is that StringToks points to one +/// string. +/// +ExprResult +Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { + assert(NumStringToks && "Must have at least one string!"); + + StringLiteralParser Literal(StringToks, NumStringToks, PP); + if (Literal.hadError) + return ExprError(); + + llvm::SmallVector<SourceLocation, 4> StringTokLocs; + for (unsigned i = 0; i != NumStringToks; ++i) + StringTokLocs.push_back(StringToks[i].getLocation()); + + QualType StrTy = Context.CharTy; + if (Literal.AnyWide) + StrTy = Context.getWCharType(); + else if (Literal.Pascal) + StrTy = Context.UnsignedCharTy; + + // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). + if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) + StrTy.addConst(); + + // Get an array type for the string, according to C99 6.4.5. This includes + // the nul terminator character as well as the string length for pascal + // strings. + StrTy = Context.getConstantArrayType(StrTy, + llvm::APInt(32, Literal.GetNumStringChars()+1), + ArrayType::Normal, 0); + + // Pass &StringTokLocs[0], StringTokLocs.size() to factory! + return Owned(StringLiteral::Create(Context, Literal.GetString(), + Literal.GetStringLength(), + Literal.AnyWide, Literal.Pascal, StrTy, + &StringTokLocs[0], + StringTokLocs.size())); +} + +enum CaptureResult { + /// No capture is required. + CR_NoCapture, + + /// A capture is required. + CR_Capture, + + /// A by-ref capture is required. + CR_CaptureByRef, + + /// An error occurred when trying to capture the given variable. + CR_Error +}; + +/// Diagnose an uncapturable value reference. +/// +/// \param var - the variable referenced +/// \param DC - the context which we couldn't capture through +static CaptureResult +diagnoseUncapturableValueReference(Sema &S, SourceLocation loc, + VarDecl *var, DeclContext *DC) { + switch (S.ExprEvalContexts.back().Context) { + case Sema::Unevaluated: + // The argument will never be evaluated, so don't complain. + return CR_NoCapture; + + case Sema::PotentiallyEvaluated: + case Sema::PotentiallyEvaluatedIfUsed: + break; + + case Sema::PotentiallyPotentiallyEvaluated: + // FIXME: delay these! + break; + } + + // Don't diagnose about capture if we're not actually in code right + // now; in general, there are more appropriate places that will + // diagnose this. + if (!S.CurContext->isFunctionOrMethod()) return CR_NoCapture; + + // Certain madnesses can happen with parameter declarations, which + // we want to ignore. + if (isa<ParmVarDecl>(var)) { + // - If the parameter still belongs to the translation unit, then + // we're actually just using one parameter in the declaration of + // the next. This is useful in e.g. VLAs. + if (isa<TranslationUnitDecl>(var->getDeclContext())) + return CR_NoCapture; + + // - This particular madness can happen in ill-formed default + // arguments; claim it's okay and let downstream code handle it. + if (S.CurContext == var->getDeclContext()->getParent()) + return CR_NoCapture; + } + + DeclarationName functionName; + if (FunctionDecl *fn = dyn_cast<FunctionDecl>(var->getDeclContext())) + functionName = fn->getDeclName(); + // FIXME: variable from enclosing block that we couldn't capture from! + + S.Diag(loc, diag::err_reference_to_local_var_in_enclosing_function) + << var->getIdentifier() << functionName; + S.Diag(var->getLocation(), diag::note_local_variable_declared_here) + << var->getIdentifier(); + + return CR_Error; +} + +/// There is a well-formed capture at a particular scope level; +/// propagate it through all the nested blocks. +static CaptureResult propagateCapture(Sema &S, unsigned validScopeIndex, + const BlockDecl::Capture &capture) { + VarDecl *var = capture.getVariable(); + + // Update all the inner blocks with the capture information. + for (unsigned i = validScopeIndex + 1, e = S.FunctionScopes.size(); + i != e; ++i) { + BlockScopeInfo *innerBlock = cast<BlockScopeInfo>(S.FunctionScopes[i]); + innerBlock->Captures.push_back( + BlockDecl::Capture(capture.getVariable(), capture.isByRef(), + /*nested*/ true, capture.getCopyExpr())); + innerBlock->CaptureMap[var] = innerBlock->Captures.size(); // +1 + } + + return capture.isByRef() ? CR_CaptureByRef : CR_Capture; +} + +/// shouldCaptureValueReference - Determine if a reference to the +/// given value in the current context requires a variable capture. +/// +/// This also keeps the captures set in the BlockScopeInfo records +/// up-to-date. +static CaptureResult shouldCaptureValueReference(Sema &S, SourceLocation loc, + ValueDecl *value) { + // Only variables ever require capture. + VarDecl *var = dyn_cast<VarDecl>(value); + if (!var) return CR_NoCapture; + + // Fast path: variables from the current context never require capture. + DeclContext *DC = S.CurContext; + if (var->getDeclContext() == DC) return CR_NoCapture; + + // Only variables with local storage require capture. + // FIXME: What about 'const' variables in C++? + if (!var->hasLocalStorage()) return CR_NoCapture; + + // Otherwise, we need to capture. + + unsigned functionScopesIndex = S.FunctionScopes.size() - 1; + do { + // Only blocks (and eventually C++0x closures) can capture; other + // scopes don't work. + if (!isa<BlockDecl>(DC)) + return diagnoseUncapturableValueReference(S, loc, var, DC); + + BlockScopeInfo *blockScope = + cast<BlockScopeInfo>(S.FunctionScopes[functionScopesIndex]); + assert(blockScope->TheDecl == static_cast<BlockDecl*>(DC)); + + // Check whether we've already captured it in this block. If so, + // we're done. + if (unsigned indexPlus1 = blockScope->CaptureMap[var]) + return propagateCapture(S, functionScopesIndex, + blockScope->Captures[indexPlus1 - 1]); + + functionScopesIndex--; + DC = cast<BlockDecl>(DC)->getDeclContext(); + } while (var->getDeclContext() != DC); + + // Okay, we descended all the way to the block that defines the variable. + // Actually try to capture it. + QualType type = var->getType(); + + // Prohibit variably-modified types. + if (type->isVariablyModifiedType()) { + S.Diag(loc, diag::err_ref_vm_type); + S.Diag(var->getLocation(), diag::note_declared_at); + return CR_Error; + } + + // Prohibit arrays, even in __block variables, but not references to + // them. + if (type->isArrayType()) { + S.Diag(loc, diag::err_ref_array_type); + S.Diag(var->getLocation(), diag::note_declared_at); + return CR_Error; + } + + S.MarkDeclarationReferenced(loc, var); + + // The BlocksAttr indicates the variable is bound by-reference. + bool byRef = var->hasAttr<BlocksAttr>(); + + // Build a copy expression. + Expr *copyExpr = 0; + const RecordType *rtype; + if (!byRef && S.getLangOptions().CPlusPlus && !type->isDependentType() && + (rtype = type->getAs<RecordType>())) { + + // The capture logic needs the destructor, so make sure we mark it. + // Usually this is unnecessary because most local variables have + // their destructors marked at declaration time, but parameters are + // an exception because it's technically only the call site that + // actually requires the destructor. + if (isa<ParmVarDecl>(var)) + S.FinalizeVarWithDestructor(var, rtype); + + // According to the blocks spec, the capture of a variable from + // the stack requires a const copy constructor. This is not true + // of the copy/move done to move a __block variable to the heap. + type.addConst(); + + Expr *declRef = new (S.Context) DeclRefExpr(var, type, VK_LValue, loc); + ExprResult result = + S.PerformCopyInitialization( + InitializedEntity::InitializeBlock(var->getLocation(), + type, false), + loc, S.Owned(declRef)); + + // Build a full-expression copy expression if initialization + // succeeded and used a non-trivial constructor. Recover from + // errors by pretending that the copy isn't necessary. + if (!result.isInvalid() && + !cast<CXXConstructExpr>(result.get())->getConstructor()->isTrivial()) { + result = S.MaybeCreateExprWithCleanups(result); + copyExpr = result.take(); + } + } + + // We're currently at the declarer; go back to the closure. + functionScopesIndex++; + BlockScopeInfo *blockScope = + cast<BlockScopeInfo>(S.FunctionScopes[functionScopesIndex]); + + // Build a valid capture in this scope. + blockScope->Captures.push_back( + BlockDecl::Capture(var, byRef, /*nested*/ false, copyExpr)); + blockScope->CaptureMap[var] = blockScope->Captures.size(); // +1 + + // Propagate that to inner captures if necessary. + return propagateCapture(S, functionScopesIndex, + blockScope->Captures.back()); +} + +static ExprResult BuildBlockDeclRefExpr(Sema &S, ValueDecl *vd, + const DeclarationNameInfo &NameInfo, + bool byRef) { + assert(isa<VarDecl>(vd) && "capturing non-variable"); + + VarDecl *var = cast<VarDecl>(vd); + assert(var->hasLocalStorage() && "capturing non-local"); + assert(byRef == var->hasAttr<BlocksAttr>() && "byref set wrong"); + + QualType exprType = var->getType().getNonReferenceType(); + + BlockDeclRefExpr *BDRE; + if (!byRef) { + // The variable will be bound by copy; make it const within the + // closure, but record that this was done in the expression. + bool constAdded = !exprType.isConstQualified(); + exprType.addConst(); + + BDRE = new (S.Context) BlockDeclRefExpr(var, exprType, VK_LValue, + NameInfo.getLoc(), false, + constAdded); + } else { + BDRE = new (S.Context) BlockDeclRefExpr(var, exprType, VK_LValue, + NameInfo.getLoc(), true); + } + + return S.Owned(BDRE); +} + +ExprResult +Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + SourceLocation Loc, + const CXXScopeSpec *SS) { + DeclarationNameInfo NameInfo(D->getDeclName(), Loc); + return BuildDeclRefExpr(D, Ty, VK, NameInfo, SS); +} + +/// BuildDeclRefExpr - Build an expression that references a +/// declaration that does not require a closure capture. +ExprResult +Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, + const DeclarationNameInfo &NameInfo, + const CXXScopeSpec *SS) { + MarkDeclarationReferenced(NameInfo.getLoc(), D); + + Expr *E = DeclRefExpr::Create(Context, + SS? SS->getWithLocInContext(Context) + : NestedNameSpecifierLoc(), + D, NameInfo, Ty, VK); + + // Just in case we're building an illegal pointer-to-member. + if (isa<FieldDecl>(D) && cast<FieldDecl>(D)->getBitWidth()) + E->setObjectKind(OK_BitField); + + return Owned(E); +} + +static ExprResult +BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, + const CXXScopeSpec &SS, FieldDecl *Field, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo); + +ExprResult +Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS, + SourceLocation loc, + IndirectFieldDecl *indirectField, + Expr *baseObjectExpr, + SourceLocation opLoc) { + // First, build the expression that refers to the base object. + + bool baseObjectIsPointer = false; + Qualifiers baseQuals; + + // Case 1: the base of the indirect field is not a field. + VarDecl *baseVariable = indirectField->getVarDecl(); + CXXScopeSpec EmptySS; + if (baseVariable) { + assert(baseVariable->getType()->isRecordType()); + + // In principle we could have a member access expression that + // accesses an anonymous struct/union that's a static member of + // the base object's class. However, under the current standard, + // static data members cannot be anonymous structs or unions. + // Supporting this is as easy as building a MemberExpr here. + assert(!baseObjectExpr && "anonymous struct/union is static data member?"); + + DeclarationNameInfo baseNameInfo(DeclarationName(), loc); + + ExprResult result = + BuildDeclarationNameExpr(EmptySS, baseNameInfo, baseVariable); + if (result.isInvalid()) return ExprError(); + + baseObjectExpr = result.take(); + baseObjectIsPointer = false; + baseQuals = baseObjectExpr->getType().getQualifiers(); + + // Case 2: the base of the indirect field is a field and the user + // wrote a member expression. + } else if (baseObjectExpr) { + // The caller provided the base object expression. Determine + // whether its a pointer and whether it adds any qualifiers to the + // anonymous struct/union fields we're looking into. + QualType objectType = baseObjectExpr->getType(); + + if (const PointerType *ptr = objectType->getAs<PointerType>()) { + baseObjectIsPointer = true; + objectType = ptr->getPointeeType(); + } else { + baseObjectIsPointer = false; + } + baseQuals = objectType.getQualifiers(); + + // Case 3: the base of the indirect field is a field and we should + // build an implicit member access. + } else { + // We've found a member of an anonymous struct/union that is + // inside a non-anonymous struct/union, so in a well-formed + // program our base object expression is "this". + QualType ThisTy = getAndCaptureCurrentThisType(); + if (ThisTy.isNull()) { + Diag(loc, diag::err_invalid_member_use_in_static_method) + << indirectField->getDeclName(); + return ExprError(); + } + + // Our base object expression is "this". + baseObjectExpr = + new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true); + baseObjectIsPointer = true; + baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers(); + } + + // Build the implicit member references to the field of the + // anonymous struct/union. + Expr *result = baseObjectExpr; + IndirectFieldDecl::chain_iterator + FI = indirectField->chain_begin(), FEnd = indirectField->chain_end(); + + // Build the first member access in the chain with full information. + if (!baseVariable) { + FieldDecl *field = cast<FieldDecl>(*FI); + + // FIXME: use the real found-decl info! + DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); + + // Make a nameInfo that properly uses the anonymous name. + DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); + + result = BuildFieldReferenceExpr(*this, result, baseObjectIsPointer, + EmptySS, field, foundDecl, + memberNameInfo).take(); + baseObjectIsPointer = false; + + // FIXME: check qualified member access + } + + // In all cases, we should now skip the first declaration in the chain. + ++FI; + + while (FI != FEnd) { + FieldDecl *field = cast<FieldDecl>(*FI++); + + // FIXME: these are somewhat meaningless + DeclarationNameInfo memberNameInfo(field->getDeclName(), loc); + DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess()); + + result = BuildFieldReferenceExpr(*this, result, /*isarrow*/ false, + (FI == FEnd? SS : EmptySS), field, + foundDecl, memberNameInfo) + .take(); + } + + return Owned(result); +} + +/// Decomposes the given name into a DeclarationNameInfo, its location, and +/// possibly a list of template arguments. +/// +/// If this produces template arguments, it is permitted to call +/// DecomposeTemplateName. +/// +/// This actually loses a lot of source location information for +/// non-standard name kinds; we should consider preserving that in +/// some way. +static void DecomposeUnqualifiedId(Sema &SemaRef, + const UnqualifiedId &Id, + TemplateArgumentListInfo &Buffer, + DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *&TemplateArgs) { + if (Id.getKind() == UnqualifiedId::IK_TemplateId) { + Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc); + Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc); + + ASTTemplateArgsPtr TemplateArgsPtr(SemaRef, + Id.TemplateId->getTemplateArgs(), + Id.TemplateId->NumArgs); + SemaRef.translateTemplateArguments(TemplateArgsPtr, Buffer); + TemplateArgsPtr.release(); + + TemplateName TName = Id.TemplateId->Template.get(); + SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc; + NameInfo = SemaRef.Context.getNameForTemplate(TName, TNameLoc); + TemplateArgs = &Buffer; + } else { + NameInfo = SemaRef.GetNameFromUnqualifiedId(Id); + TemplateArgs = 0; + } +} + +/// Determines if the given class is provably not derived from all of +/// the prospective base classes. +static bool IsProvablyNotDerivedFrom(Sema &SemaRef, + CXXRecordDecl *Record, + const llvm::SmallPtrSet<CXXRecordDecl*, 4> &Bases) { + if (Bases.count(Record->getCanonicalDecl())) + return false; + + RecordDecl *RD = Record->getDefinition(); + if (!RD) return false; + Record = cast<CXXRecordDecl>(RD); + + for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), + E = Record->bases_end(); I != E; ++I) { + CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType()); + CanQual<RecordType> BaseRT = BaseT->getAs<RecordType>(); + if (!BaseRT) return false; + + CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl()); + if (!IsProvablyNotDerivedFrom(SemaRef, BaseRecord, Bases)) + return false; + } + + return true; +} + +enum IMAKind { + /// The reference is definitely not an instance member access. + IMA_Static, + + /// The reference may be an implicit instance member access. + IMA_Mixed, + + /// The reference may be to an instance member, but it is invalid if + /// so, because the context is not an instance method. + IMA_Mixed_StaticContext, + + /// The reference may be to an instance member, but it is invalid if + /// so, because the context is from an unrelated class. + IMA_Mixed_Unrelated, + + /// The reference is definitely an implicit instance member access. + IMA_Instance, + + /// The reference may be to an unresolved using declaration. + IMA_Unresolved, + + /// The reference may be to an unresolved using declaration and the + /// context is not an instance method. + IMA_Unresolved_StaticContext, + + /// All possible referrents are instance members and the current + /// context is not an instance method. + IMA_Error_StaticContext, + + /// All possible referrents are instance members of an unrelated + /// class. + IMA_Error_Unrelated +}; + +/// The given lookup names class member(s) and is not being used for +/// an address-of-member expression. Classify the type of access +/// according to whether it's possible that this reference names an +/// instance member. This is best-effort; it is okay to +/// conservatively answer "yes", in which case some errors will simply +/// not be caught until template-instantiation. +static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, + Scope *CurScope, + const LookupResult &R) { + assert(!R.empty() && (*R.begin())->isCXXClassMember()); + + DeclContext *DC = SemaRef.getFunctionLevelDeclContext(); + + bool isStaticContext = + (!isa<CXXMethodDecl>(DC) || + cast<CXXMethodDecl>(DC)->isStatic()); + + // C++0x [expr.prim]p4: + // Otherwise, if a member-declarator declares a non-static data member + // of a class X, the expression this is a prvalue of type "pointer to X" + // within the optional brace-or-equal-initializer. + if (CurScope->getFlags() & Scope::ThisScope) + isStaticContext = false; + + if (R.isUnresolvableResult()) + return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved; + + // Collect all the declaring classes of instance members we find. + bool hasNonInstance = false; + bool hasField = false; + llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes; + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *D = *I; + + if (D->isCXXInstanceMember()) { + if (dyn_cast<FieldDecl>(D)) + hasField = true; + + CXXRecordDecl *R = cast<CXXRecordDecl>(D->getDeclContext()); + Classes.insert(R->getCanonicalDecl()); + } + else + hasNonInstance = true; + } + + // If we didn't find any instance members, it can't be an implicit + // member reference. + if (Classes.empty()) + return IMA_Static; + + // If the current context is not an instance method, it can't be + // an implicit member reference. + if (isStaticContext) { + if (hasNonInstance) + return IMA_Mixed_StaticContext; + + if (SemaRef.getLangOptions().CPlusPlus0x && hasField) { + // C++0x [expr.prim.general]p10: + // An id-expression that denotes a non-static data member or non-static + // member function of a class can only be used: + // (...) + // - if that id-expression denotes a non-static data member and it appears in an unevaluated operand. + const Sema::ExpressionEvaluationContextRecord& record = SemaRef.ExprEvalContexts.back(); + bool isUnevaluatedExpression = record.Context == Sema::Unevaluated; + if (isUnevaluatedExpression) + return IMA_Mixed_StaticContext; + } + + return IMA_Error_StaticContext; + } + + CXXRecordDecl *contextClass; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) + contextClass = MD->getParent()->getCanonicalDecl(); + else + contextClass = cast<CXXRecordDecl>(DC); + + // [class.mfct.non-static]p3: + // ...is used in the body of a non-static member function of class X, + // if name lookup (3.4.1) resolves the name in the id-expression to a + // non-static non-type member of some class C [...] + // ...if C is not X or a base class of X, the class member access expression + // is ill-formed. + if (R.getNamingClass() && + contextClass != R.getNamingClass()->getCanonicalDecl() && + contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) + return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + + // If we can prove that the current context is unrelated to all the + // declaring classes, it can't be an implicit member reference (in + // which case it's an error if any of those members are selected). + if (IsProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) + return (hasNonInstance ? IMA_Mixed_Unrelated : IMA_Error_Unrelated); + + return (hasNonInstance ? IMA_Mixed : IMA_Instance); +} + +/// Diagnose a reference to a field with no object available. +static void DiagnoseInstanceReference(Sema &SemaRef, + const CXXScopeSpec &SS, + NamedDecl *rep, + const DeclarationNameInfo &nameInfo) { + SourceLocation Loc = nameInfo.getLoc(); + SourceRange Range(Loc); + if (SS.isSet()) Range.setBegin(SS.getRange().getBegin()); + + if (isa<FieldDecl>(rep) || isa<IndirectFieldDecl>(rep)) { + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) { + if (MD->isStatic()) { + // "invalid use of member 'x' in static member function" + SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method) + << Range << nameInfo.getName(); + return; + } + } + + SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use) + << nameInfo.getName() << Range; + return; + } + + SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range; +} + +/// Diagnose an empty lookup. +/// +/// \return false if new lookup candidates were found +bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectTypoContext CTC) { + DeclarationName Name = R.getLookupName(); + + unsigned diagnostic = diag::err_undeclared_var_use; + unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest; + if (Name.getNameKind() == DeclarationName::CXXOperatorName || + Name.getNameKind() == DeclarationName::CXXLiteralOperatorName || + Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { + diagnostic = diag::err_undeclared_use; + diagnostic_suggest = diag::err_undeclared_use_suggest; + } + + // If the original lookup was an unqualified lookup, fake an + // unqualified lookup. This is useful when (for example) the + // original lookup would not have found something because it was a + // dependent name. + for (DeclContext *DC = SS.isEmpty() ? CurContext : 0; + DC; DC = DC->getParent()) { + if (isa<CXXRecordDecl>(DC)) { + LookupQualifiedName(R, DC); + + if (!R.empty()) { + // Don't give errors about ambiguities in this lookup. + R.suppressDiagnostics(); + + CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext); + bool isInstance = CurMethod && + CurMethod->isInstance() && + DC == CurMethod->getParent(); + + // Give a code modification hint to insert 'this->'. + // TODO: fixit for inserting 'Base<T>::' in the other cases. + // Actually quite difficult! + if (isInstance) { + UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>( + CallsUndergoingInstantiation.back()->getCallee()); + CXXMethodDecl *DepMethod = cast_or_null<CXXMethodDecl>( + CurMethod->getInstantiatedFromMemberFunction()); + if (DepMethod) { + Diag(R.getNameLoc(), diagnostic) << Name + << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); + QualType DepThisType = DepMethod->getThisType(Context); + CXXThisExpr *DepThis = new (Context) CXXThisExpr( + R.getNameLoc(), DepThisType, false); + TemplateArgumentListInfo TList; + if (ULE->hasExplicitTemplateArgs()) + ULE->copyTemplateArgumentsInto(TList); + + CXXScopeSpec SS; + SS.Adopt(ULE->getQualifierLoc()); + CXXDependentScopeMemberExpr *DepExpr = + CXXDependentScopeMemberExpr::Create( + Context, DepThis, DepThisType, true, SourceLocation(), + SS.getWithLocInContext(Context), NULL, + R.getLookupNameInfo(), &TList); + CallsUndergoingInstantiation.back()->setCallee(DepExpr); + } else { + // FIXME: we should be able to handle this case too. It is correct + // to add this-> here. This is a workaround for PR7947. + Diag(R.getNameLoc(), diagnostic) << Name; + } + } else { + Diag(R.getNameLoc(), diagnostic) << Name; + } + + // Do we really want to note all of these? + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getLocation(), diag::note_dependent_var_use); + + // Tell the callee to try to recover. + return false; + } + + R.clear(); + } + } + + // We didn't find anything, so try to correct for a typo. + DeclarationName Corrected; + if (S && (Corrected = CorrectTypo(R, S, &SS, 0, false, CTC))) { + if (!R.empty()) { + if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) { + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName() + << FixItHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << R.getLookupName() + << SS.getRange() + << FixItHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) + Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); + + // Tell the callee to try to recover. + return false; + } + + if (isa<TypeDecl>(*R.begin()) || isa<ObjCInterfaceDecl>(*R.begin())) { + // FIXME: If we ended up with a typo for a type name or + // Objective-C class name, we're in trouble because the parser + // is in the wrong place to recover. Suggest the typo + // correction, but don't make it a fix-it since we're not going + // to recover well anyway. + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName(); + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << R.getLookupName() + << SS.getRange(); + + // Don't try to recover; it won't work. + return true; + } + } else { + // FIXME: We found a keyword. Suggest it, but don't provide a fix-it + // because we aren't able to recover. + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << Corrected; + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << Corrected + << SS.getRange(); + return true; + } + R.clear(); + } + + // Emit a special diagnostic for failed member lookups. + // FIXME: computing the declaration context might fail here (?) + if (!SS.isEmpty()) { + Diag(R.getNameLoc(), diag::err_no_member) + << Name << computeDeclContext(SS, false) + << SS.getRange(); + return true; + } + + // Give up, we can't recover. + Diag(R.getNameLoc(), diagnostic) << Name; + return true; +} + +ObjCPropertyDecl *Sema::canSynthesizeProvisionalIvar(IdentifierInfo *II) { + ObjCMethodDecl *CurMeth = getCurMethodDecl(); + ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); + if (!IDecl) + return 0; + ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); + if (!ClassImpDecl) + return 0; + ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II); + if (!property) + return 0; + if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) + if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic || + PIDecl->getPropertyIvarDecl()) + return 0; + return property; +} + +bool Sema::canSynthesizeProvisionalIvar(ObjCPropertyDecl *Property) { + ObjCMethodDecl *CurMeth = getCurMethodDecl(); + ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); + if (!IDecl) + return false; + ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); + if (!ClassImpDecl) + return false; + if (ObjCPropertyImplDecl *PIDecl + = ClassImpDecl->FindPropertyImplDecl(Property->getIdentifier())) + if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic || + PIDecl->getPropertyIvarDecl()) + return false; + + return true; +} + +ObjCIvarDecl *Sema::SynthesizeProvisionalIvar(LookupResult &Lookup, + IdentifierInfo *II, + SourceLocation NameLoc) { + ObjCMethodDecl *CurMeth = getCurMethodDecl(); + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (CurMeth->isClassMethod()) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod() && + (Lookup.getAsSingle<VarDecl>() != 0)); + if (!LookForIvars) + return 0; + + ObjCInterfaceDecl *IDecl = CurMeth->getClassInterface(); + if (!IDecl) + return 0; + ObjCImplementationDecl *ClassImpDecl = IDecl->getImplementation(); + if (!ClassImpDecl) + return 0; + bool DynamicImplSeen = false; + ObjCPropertyDecl *property = LookupPropertyDecl(IDecl, II); + if (!property) + return 0; + if (ObjCPropertyImplDecl *PIDecl = ClassImpDecl->FindPropertyImplDecl(II)) { + DynamicImplSeen = + (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); + // property implementation has a designated ivar. No need to assume a new + // one. + if (!DynamicImplSeen && PIDecl->getPropertyIvarDecl()) + return 0; + } + if (!DynamicImplSeen) { + QualType PropType = Context.getCanonicalType(property->getType()); + ObjCIvarDecl *Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, + NameLoc, NameLoc, + II, PropType, /*Dinfo=*/0, + ObjCIvarDecl::Private, + (Expr *)0, true); + ClassImpDecl->addDecl(Ivar); + IDecl->makeDeclVisibleInContext(Ivar, false); + property->setPropertyIvarDecl(Ivar); + return Ivar; + } + return 0; +} + +ExprResult Sema::ActOnIdExpression(Scope *S, + CXXScopeSpec &SS, + UnqualifiedId &Id, + bool HasTrailingLParen, + bool isAddressOfOperand) { + assert(!(isAddressOfOperand && HasTrailingLParen) && + "cannot be direct & operand and have a trailing lparen"); + + if (SS.isInvalid()) + return ExprError(); + + TemplateArgumentListInfo TemplateArgsBuffer; + + // Decompose the UnqualifiedId into the following data. + DeclarationNameInfo NameInfo; + const TemplateArgumentListInfo *TemplateArgs; + DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, NameInfo, TemplateArgs); + + DeclarationName Name = NameInfo.getName(); + IdentifierInfo *II = Name.getAsIdentifierInfo(); + SourceLocation NameLoc = NameInfo.getLoc(); + + // C++ [temp.dep.expr]p3: + // An id-expression is type-dependent if it contains: + // -- an identifier that was declared with a dependent type, + // (note: handled after lookup) + // -- a template-id that is dependent, + // (note: handled in BuildTemplateIdExpr) + // -- a conversion-function-id that specifies a dependent type, + // -- a nested-name-specifier that contains a class-name that + // names a dependent type. + // Determine whether this is a member of an unknown specialization; + // we need to handle these differently. + bool DependentID = false; + if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName && + Name.getCXXNameType()->isDependentType()) { + DependentID = true; + } else if (SS.isSet()) { + if (DeclContext *DC = computeDeclContext(SS, false)) { + if (RequireCompleteDeclContext(SS, DC)) + return ExprError(); + } else { + DependentID = true; + } + } + + if (DependentID) + return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand, + TemplateArgs); + + bool IvarLookupFollowUp = false; + // Perform the required lookup. + LookupResult R(*this, NameInfo, LookupOrdinaryName); + if (TemplateArgs) { + // Lookup the template name again to correctly establish the context in + // which it was found. This is really unfortunate as we already did the + // lookup to determine that it was a template name in the first place. If + // this becomes a performance hit, we can work harder to preserve those + // results until we get here but it's likely not worth it. + bool MemberOfUnknownSpecialization; + LookupTemplateName(R, S, SS, QualType(), /*EnteringContext=*/false, + MemberOfUnknownSpecialization); + + if (MemberOfUnknownSpecialization || + (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation)) + return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand, + TemplateArgs); + } else { + IvarLookupFollowUp = (!SS.isSet() && II && getCurMethodDecl()); + LookupParsedName(R, S, &SS, !IvarLookupFollowUp); + + // If the result might be in a dependent base class, this is a dependent + // id-expression. + if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + return ActOnDependentIdExpression(SS, NameInfo, isAddressOfOperand, + TemplateArgs); + + // If this reference is in an Objective-C method, then we need to do + // some special Objective-C lookup, too. + if (IvarLookupFollowUp) { + ExprResult E(LookupInObjCMethod(R, S, II, true)); + if (E.isInvalid()) + return ExprError(); + + if (Expr *Ex = E.takeAs<Expr>()) + return Owned(Ex); + + // Synthesize ivars lazily. + if (getLangOptions().ObjCDefaultSynthProperties && + getLangOptions().ObjCNonFragileABI2) { + if (SynthesizeProvisionalIvar(R, II, NameLoc)) { + if (const ObjCPropertyDecl *Property = + canSynthesizeProvisionalIvar(II)) { + Diag(NameLoc, diag::warn_synthesized_ivar_access) << II; + Diag(Property->getLocation(), diag::note_property_declare); + } + return ActOnIdExpression(S, SS, Id, HasTrailingLParen, + isAddressOfOperand); + } + } + // for further use, this must be set to false if in class method. + IvarLookupFollowUp = getCurMethodDecl()->isInstanceMethod(); + } + } + + if (R.isAmbiguous()) + return ExprError(); + + // Determine whether this name might be a candidate for + // argument-dependent lookup. + bool ADL = UseArgumentDependentLookup(SS, R, HasTrailingLParen); + + if (R.empty() && !ADL) { + // Otherwise, this could be an implicitly declared function reference (legal + // in C90, extension in C99, forbidden in C++). + if (HasTrailingLParen && II && !getLangOptions().CPlusPlus) { + NamedDecl *D = ImplicitlyDefineFunction(NameLoc, *II, S); + if (D) R.addDecl(D); + } + + // If this name wasn't predeclared and if this is not a function + // call, diagnose the problem. + if (R.empty()) { + if (DiagnoseEmptyLookup(S, SS, R, CTC_Unknown)) + return ExprError(); + + assert(!R.empty() && + "DiagnoseEmptyLookup returned false but added no results"); + + // If we found an Objective-C instance variable, let + // LookupInObjCMethod build the appropriate expression to + // reference the ivar. + if (ObjCIvarDecl *Ivar = R.getAsSingle<ObjCIvarDecl>()) { + R.clear(); + ExprResult E(LookupInObjCMethod(R, S, Ivar->getIdentifier())); + assert(E.isInvalid() || E.get()); + return move(E); + } + } + } + + // This is guaranteed from this point on. + assert(!R.empty() || ADL); + + // Check whether this might be a C++ implicit instance member access. + // C++ [class.mfct.non-static]p3: + // When an id-expression that is not part of a class member access + // syntax and not used to form a pointer to member is used in the + // body of a non-static member function of class X, if name lookup + // resolves the name in the id-expression to a non-static non-type + // member of some class C, the id-expression is transformed into a + // class member access expression using (*this) as the + // postfix-expression to the left of the . operator. + // + // But we don't actually need to do this for '&' operands if R + // resolved to a function or overloaded function set, because the + // expression is ill-formed if it actually works out to be a + // non-static member function: + // + // C++ [expr.ref]p4: + // Otherwise, if E1.E2 refers to a non-static member function. . . + // [t]he expression can be used only as the left-hand operand of a + // member function call. + // + // There are other safeguards against such uses, but it's important + // to get this right here so that we don't end up making a + // spuriously dependent expression if we're inside a dependent + // instance method. + if (!R.empty() && (*R.begin())->isCXXClassMember()) { + bool MightBeImplicitMember; + if (!isAddressOfOperand) + MightBeImplicitMember = true; + else if (!SS.isEmpty()) + MightBeImplicitMember = false; + else if (R.isOverloadedResult()) + MightBeImplicitMember = false; + else if (R.isUnresolvableResult()) + MightBeImplicitMember = true; + else + MightBeImplicitMember = isa<FieldDecl>(R.getFoundDecl()) || + isa<IndirectFieldDecl>(R.getFoundDecl()); + + if (MightBeImplicitMember) + return BuildPossibleImplicitMemberExpr(SS, R, TemplateArgs); + } + + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, ADL, *TemplateArgs); + + return BuildDeclarationNameExpr(SS, R, ADL); +} + +/// Builds an expression which might be an implicit member expression. +ExprResult +Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + switch (ClassifyImplicitMemberAccess(*this, CurScope, R)) { + case IMA_Instance: + return BuildImplicitMemberExpr(SS, R, TemplateArgs, true); + + case IMA_Mixed: + case IMA_Mixed_Unrelated: + case IMA_Unresolved: + return BuildImplicitMemberExpr(SS, R, TemplateArgs, false); + + case IMA_Static: + case IMA_Mixed_StaticContext: + case IMA_Unresolved_StaticContext: + if (TemplateArgs) + return BuildTemplateIdExpr(SS, R, false, *TemplateArgs); + return BuildDeclarationNameExpr(SS, R, false); + + case IMA_Error_StaticContext: + case IMA_Error_Unrelated: + DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(), + R.getLookupNameInfo()); + return ExprError(); + } + + llvm_unreachable("unexpected instance member access kind"); + return ExprError(); +} + +/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified +/// declaration name, generally during template instantiation. +/// There's a large number of things which don't need to be done along +/// this path. +ExprResult +Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext()) + return BuildDependentDeclRefExpr(SS, NameInfo, 0); + + if (RequireCompleteDeclContext(SS, DC)) + return ExprError(); + + LookupResult R(*this, NameInfo, LookupOrdinaryName); + LookupQualifiedName(R, DC); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameInfo.getLoc(), diag::err_no_member) + << NameInfo.getName() << DC << SS.getRange(); + return ExprError(); + } + + return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); +} + +/// LookupInObjCMethod - The parser has read a name in, and Sema has +/// detected that we're currently inside an ObjC method. Perform some +/// additional lookup. +/// +/// Ideally, most of this would be done by lookup, but there's +/// actually quite a lot of extra work involved. +/// +/// Returns a null sentinel to indicate trivial success. +ExprResult +Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, + IdentifierInfo *II, bool AllowBuiltinCreation) { + SourceLocation Loc = Lookup.getNameLoc(); + ObjCMethodDecl *CurMethod = getCurMethodDecl(); + + // There are two cases to handle here. 1) scoped lookup could have failed, + // in which case we should look for an ivar. 2) scoped lookup could have + // found a decl, but that decl is outside the current instance method (i.e. + // a global variable). In these two cases, we do a lookup for an ivar with + // this name, if the lookup sucedes, we replace it our current decl. + + // If we're in a class method, we don't normally want to look for + // ivars. But if we don't find anything else, and there's an + // ivar, that's an error. + bool IsClassMethod = CurMethod->isClassMethod(); + + bool LookForIvars; + if (Lookup.empty()) + LookForIvars = true; + else if (IsClassMethod) + LookForIvars = false; + else + LookForIvars = (Lookup.isSingleResult() && + Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); + ObjCInterfaceDecl *IFace = 0; + if (LookForIvars) { + IFace = CurMethod->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + // Diagnose using an ivar in a class method. + if (IsClassMethod) + return ExprError(Diag(Loc, diag::error_ivar_use_in_class_method) + << IV->getDeclName()); + + // If we're referencing an invalid decl, just return this as a silent + // error node. The error diagnostic was already emitted on the decl. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check if referencing a field with __attribute__((deprecated)). + if (DiagnoseUseOfDecl(IV, Loc)) + return ExprError(); + + // Diagnose the use of an ivar outside of the declaring class. + if (IV->getAccessControl() == ObjCIvarDecl::Private && + ClassDeclared != IFace) + Diag(Loc, diag::error_private_ivar_access) << IV->getDeclName(); + + // FIXME: This should use a new expr for a direct reference, don't + // turn this into Self->ivar, just return a BareIVarExpr or something. + IdentifierInfo &II = Context.Idents.get("self"); + UnqualifiedId SelfName; + SelfName.setIdentifier(&II, SourceLocation()); + CXXScopeSpec SelfScopeSpec; + ExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, + SelfName, false, false); + if (SelfExpr.isInvalid()) + return ExprError(); + + SelfExpr = DefaultLvalueConversion(SelfExpr.take()); + if (SelfExpr.isInvalid()) + return ExprError(); + + MarkDeclarationReferenced(Loc, IV); + Expr *base = SelfExpr.take(); + base = base->IgnoreParenImpCasts(); + if (const DeclRefExpr *DE = dyn_cast<DeclRefExpr>(base)) { + const NamedDecl *ND = DE->getDecl(); + if (!isa<ImplicitParamDecl>(ND)) { + // relax the rule such that it is allowed to have a shadow 'self' + // where stand-alone ivar can be found in this 'self' object. + // This is to match gcc's behavior. + ObjCInterfaceDecl *selfIFace = 0; + if (const ObjCObjectPointerType *OPT = + base->getType()->getAsObjCInterfacePointerType()) + selfIFace = OPT->getInterfaceDecl(); + if (!selfIFace || + !selfIFace->lookupInstanceVariable(IV->getIdentifier())) { + Diag(Loc, diag::error_implicit_ivar_access) + << IV->getDeclName(); + Diag(ND->getLocation(), diag::note_declared_at); + return ExprError(); + } + } + } + return Owned(new (Context) + ObjCIvarRefExpr(IV, IV->getType(), Loc, + SelfExpr.take(), true, true)); + } + } else if (CurMethod->isInstanceMethod()) { + // We should warn if a local variable hides an ivar. + ObjCInterfaceDecl *IFace = CurMethod->getClassInterface(); + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { + if (IV->getAccessControl() != ObjCIvarDecl::Private || + IFace == ClassDeclared) + Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); + } + } + + if (Lookup.empty() && II && AllowBuiltinCreation) { + // FIXME. Consolidate this with similar code in LookupName. + if (unsigned BuiltinID = II->getBuiltinID()) { + if (!(getLangOptions().CPlusPlus && + Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))) { + NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, + S, Lookup.isForRedeclaration(), + Lookup.getNameLoc()); + if (D) Lookup.addDecl(D); + } + } + } + // Sentinel value saying that we didn't do anything special. + return Owned((Expr*) 0); +} + +/// \brief Cast a base object to a member's actual type. +/// +/// Logically this happens in three phases: +/// +/// * First we cast from the base type to the naming class. +/// The naming class is the class into which we were looking +/// when we found the member; it's the qualifier type if a +/// qualifier was provided, and otherwise it's the base type. +/// +/// * Next we cast from the naming class to the declaring class. +/// If the member we found was brought into a class's scope by +/// a using declaration, this is that class; otherwise it's +/// the class declaring the member. +/// +/// * Finally we cast from the declaring class to the "true" +/// declaring class of the member. This conversion does not +/// obey access control. +ExprResult +Sema::PerformObjectMemberConversion(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + NamedDecl *Member) { + CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Member->getDeclContext()); + if (!RD) + return Owned(From); + + QualType DestRecordType; + QualType DestType; + QualType FromRecordType; + QualType FromType = From->getType(); + bool PointerConversions = false; + if (isa<FieldDecl>(Member)) { + DestRecordType = Context.getCanonicalType(Context.getTypeDeclType(RD)); + + if (FromType->getAs<PointerType>()) { + DestType = Context.getPointerType(DestRecordType); + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + DestType = DestRecordType; + FromRecordType = FromType; + } + } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Member)) { + if (Method->isStatic()) + return Owned(From); + + DestType = Method->getThisType(Context); + DestRecordType = DestType->getPointeeType(); + + if (FromType->getAs<PointerType>()) { + FromRecordType = FromType->getPointeeType(); + PointerConversions = true; + } else { + FromRecordType = FromType; + DestType = DestRecordType; + } + } else { + // No conversion necessary. + return Owned(From); + } + + if (DestType->isDependentType() || FromType->isDependentType()) + return Owned(From); + + // If the unqualified types are the same, no conversion is necessary. + if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) + return Owned(From); + + SourceRange FromRange = From->getSourceRange(); + SourceLocation FromLoc = FromRange.getBegin(); + + ExprValueKind VK = CastCategory(From); + + // C++ [class.member.lookup]p8: + // [...] Ambiguities can often be resolved by qualifying a name with its + // class name. + // + // If the member was a qualified name and the qualified referred to a + // specific base subobject type, we'll cast to that intermediate type + // first and then to the object in which the member is declared. That allows + // one to resolve ambiguities in, e.g., a diamond-shaped hierarchy such as: + // + // class Base { public: int x; }; + // class Derived1 : public Base { }; + // class Derived2 : public Base { }; + // class VeryDerived : public Derived1, public Derived2 { void f(); }; + // + // void VeryDerived::f() { + // x = 17; // error: ambiguous base subobjects + // Derived1::x = 17; // okay, pick the Base subobject of Derived1 + // } + if (Qualifier) { + QualType QType = QualType(Qualifier->getAsType(), 0); + assert(!QType.isNull() && "lookup done with dependent qualifier?"); + assert(QType->isRecordType() && "lookup done with non-record type"); + + QualType QRecordType = QualType(QType->getAs<RecordType>(), 0); + + // In C++98, the qualifier type doesn't actually have to be a base + // type of the object type, in which case we just ignore it. + // Otherwise build the appropriate casts. + if (IsDerivedFrom(FromRecordType, QRecordType)) { + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(FromRecordType, QRecordType, + FromLoc, FromRange, &BasePath)) + return ExprError(); + + if (PointerConversions) + QType = Context.getPointerType(QType); + From = ImpCastExprToType(From, QType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); + + FromType = QType; + FromRecordType = QRecordType; + + // If the qualifier type was the same as the destination type, + // we're done. + if (Context.hasSameUnqualifiedType(FromRecordType, DestRecordType)) + return Owned(From); + } + } + + bool IgnoreAccess = false; + + // If we actually found the member through a using declaration, cast + // down to the using declaration's type. + // + // Pointer equality is fine here because only one declaration of a + // class ever has member declarations. + if (FoundDecl->getDeclContext() != Member->getDeclContext()) { + assert(isa<UsingShadowDecl>(FoundDecl)); + QualType URecordType = Context.getTypeDeclType( + cast<CXXRecordDecl>(FoundDecl->getDeclContext())); + + // We only need to do this if the naming-class to declaring-class + // conversion is non-trivial. + if (!Context.hasSameUnqualifiedType(FromRecordType, URecordType)) { + assert(IsDerivedFrom(FromRecordType, URecordType)); + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(FromRecordType, URecordType, + FromLoc, FromRange, &BasePath)) + return ExprError(); + + QualType UType = URecordType; + if (PointerConversions) + UType = Context.getPointerType(UType); + From = ImpCastExprToType(From, UType, CK_UncheckedDerivedToBase, + VK, &BasePath).take(); + FromType = UType; + FromRecordType = URecordType; + } + + // We don't do access control for the conversion from the + // declaring class to the true declaring class. + IgnoreAccess = true; + } + + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(FromRecordType, DestRecordType, + FromLoc, FromRange, &BasePath, + IgnoreAccess)) + return ExprError(); + + return ImpCastExprToType(From, DestType, CK_UncheckedDerivedToBase, + VK, &BasePath); +} + +/// \brief Build a MemberExpr AST node. +static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow, + const CXXScopeSpec &SS, ValueDecl *Member, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo, + QualType Ty, + ExprValueKind VK, ExprObjectKind OK, + const TemplateArgumentListInfo *TemplateArgs = 0) { + return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C), + Member, FoundDecl, MemberNameInfo, + TemplateArgs, Ty, VK, OK); +} + +static ExprResult +BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, + const CXXScopeSpec &SS, FieldDecl *Field, + DeclAccessPair FoundDecl, + const DeclarationNameInfo &MemberNameInfo) { + // x.a is an l-value if 'a' has a reference type. Otherwise: + // x.a is an l-value/x-value/pr-value if the base is (and note + // that *x is always an l-value), except that if the base isn't + // an ordinary object then we must have an rvalue. + ExprValueKind VK = VK_LValue; + ExprObjectKind OK = OK_Ordinary; + if (!IsArrow) { + if (BaseExpr->getObjectKind() == OK_Ordinary) + VK = BaseExpr->getValueKind(); + else + VK = VK_RValue; + } + if (VK != VK_RValue && Field->isBitField()) + OK = OK_BitField; + + // Figure out the type of the member; see C99 6.5.2.3p3, C++ [expr.ref] + QualType MemberType = Field->getType(); + if (const ReferenceType *Ref = MemberType->getAs<ReferenceType>()) { + MemberType = Ref->getPointeeType(); + VK = VK_LValue; + } else { + QualType BaseType = BaseExpr->getType(); + if (IsArrow) BaseType = BaseType->getAs<PointerType>()->getPointeeType(); + + Qualifiers BaseQuals = BaseType.getQualifiers(); + + // GC attributes are never picked up by members. + BaseQuals.removeObjCGCAttr(); + + // CVR attributes from the base are picked up by members, + // except that 'mutable' members don't pick up 'const'. + if (Field->isMutable()) BaseQuals.removeConst(); + + Qualifiers MemberQuals + = S.Context.getCanonicalType(MemberType).getQualifiers(); + + // TR 18037 does not allow fields to be declared with address spaces. + assert(!MemberQuals.hasAddressSpace()); + + Qualifiers Combined = BaseQuals + MemberQuals; + if (Combined != MemberQuals) + MemberType = S.Context.getQualifiedType(MemberType, Combined); + } + + S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field); + ExprResult Base = + S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(), + FoundDecl, Field); + if (Base.isInvalid()) + return ExprError(); + return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS, + Field, FoundDecl, MemberNameInfo, + MemberType, VK, OK)); +} + +/// Builds an implicit member access expression. The current context +/// is known to be an instance method, and the given unqualified lookup +/// set is known to contain only instance members, at least one of which +/// is from an appropriate type. +ExprResult +Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool IsKnownInstance) { + assert(!R.empty() && !R.isAmbiguous()); + + SourceLocation loc = R.getNameLoc(); + + // We may have found a field within an anonymous union or struct + // (C++ [class.union]). + // FIXME: template-ids inside anonymous structs? + if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>()) + return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD); + + // If this is known to be an instance access, go ahead and build an + // implicit 'this' expression now. + // 'this' expression now. + QualType ThisTy = getAndCaptureCurrentThisType(); + assert(!ThisTy.isNull() && "didn't correctly pre-flight capture of 'this'"); + + Expr *baseExpr = 0; // null signifies implicit access + if (IsKnownInstance) { + SourceLocation Loc = R.getNameLoc(); + if (SS.getRange().isValid()) + Loc = SS.getRange().getBegin(); + baseExpr = new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/true); + } + + return BuildMemberReferenceExpr(baseExpr, ThisTy, + /*OpLoc*/ SourceLocation(), + /*IsArrow*/ true, + SS, + /*FirstQualifierInScope*/ 0, + R, TemplateArgs); +} + +bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, + const LookupResult &R, + bool HasTrailingLParen) { + // Only when used directly as the postfix-expression of a call. + if (!HasTrailingLParen) + return false; + + // Never if a scope specifier was provided. + if (SS.isSet()) + return false; + + // Only in C++ or ObjC++. + if (!getLangOptions().CPlusPlus) + return false; + + // Turn off ADL when we find certain kinds of declarations during + // normal lookup: + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *D = *I; + + // C++0x [basic.lookup.argdep]p3: + // -- a declaration of a class member + // Since using decls preserve this property, we check this on the + // original decl. + if (D->isCXXClassMember()) + return false; + + // C++0x [basic.lookup.argdep]p3: + // -- a block-scope function declaration that is not a + // using-declaration + // NOTE: we also trigger this for function templates (in fact, we + // don't check the decl type at all, since all other decl types + // turn off ADL anyway). + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + else if (D->getDeclContext()->isFunctionOrMethod()) + return false; + + // C++0x [basic.lookup.argdep]p3: + // -- a declaration that is neither a function or a function + // template + // And also for builtin functions. + if (isa<FunctionDecl>(D)) { + FunctionDecl *FDecl = cast<FunctionDecl>(D); + + // But also builtin functions. + if (FDecl->getBuiltinID() && FDecl->isImplicit()) + return false; + } else if (!isa<FunctionTemplateDecl>(D)) + return false; + } + + return true; +} + + +/// Diagnoses obvious problems with the use of the given declaration +/// as an expression. This is only actually called for lookups that +/// were not overloaded, and it doesn't promise that the declaration +/// will in fact be used. +static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { + if (isa<TypedefNameDecl>(D)) { + S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName(); + return true; + } + + if (isa<ObjCInterfaceDecl>(D)) { + S.Diag(Loc, diag::err_unexpected_interface) << D->getDeclName(); + return true; + } + + if (isa<NamespaceDecl>(D)) { + S.Diag(Loc, diag::err_unexpected_namespace) << D->getDeclName(); + return true; + } + + return false; +} + +ExprResult +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool NeedsADL) { + // If this is a single, fully-resolved result and we don't need ADL, + // just build an ordinary singleton decl ref. + if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>()) + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), + R.getFoundDecl()); + + // We only need to check the declaration if there's exactly one + // result, because in the overloaded case the results can only be + // functions and function templates. + if (R.isSingleResult() && + CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) + return ExprError(); + + // Otherwise, just build an unresolved lookup expression. Suppress + // any lookup-related diagnostics; we'll hash these out later, when + // we've picked a target. + R.suppressDiagnostics(); + + UnresolvedLookupExpr *ULE + = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), + SS.getWithLocInContext(Context), + R.getLookupNameInfo(), + NeedsADL, R.isOverloadedResult(), + R.begin(), R.end()); + + return Owned(ULE); +} + +/// \brief Complete semantic analysis for a reference to the given declaration. +ExprResult +Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + NamedDecl *D) { + assert(D && "Cannot refer to a NULL declaration"); + assert(!isa<FunctionTemplateDecl>(D) && + "Cannot refer unambiguously to a function template"); + + SourceLocation Loc = NameInfo.getLoc(); + if (CheckDeclInExpr(*this, Loc, D)) + return ExprError(); + + if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) { + // Specifically diagnose references to class templates that are missing + // a template argument list. + Diag(Loc, diag::err_template_decl_ref) + << Template << SS.getRange(); + Diag(Template->getLocation(), diag::note_template_decl_here); + return ExprError(); + } + + // Make sure that we're referring to a value. + ValueDecl *VD = dyn_cast<ValueDecl>(D); + if (!VD) { + Diag(Loc, diag::err_ref_non_value) + << D << SS.getRange(); + Diag(D->getLocation(), diag::note_declared_at); + return ExprError(); + } + + // Check whether this declaration can be used. Note that we suppress + // this check when we're going to perform argument-dependent lookup + // on this function name, because this might not be the function + // that overload resolution actually selects. + if (DiagnoseUseOfDecl(VD, Loc)) + return ExprError(); + + // Only create DeclRefExpr's for valid Decl's. + if (VD->isInvalidDecl()) + return ExprError(); + + // Handle members of anonymous structs and unions. If we got here, + // and the reference is to a class member indirect field, then this + // must be the subject of a pointer-to-member expression. + if (IndirectFieldDecl *indirectField = dyn_cast<IndirectFieldDecl>(VD)) + if (!indirectField->isCXXClassMember()) + return BuildAnonymousStructUnionMemberReference(SS, NameInfo.getLoc(), + indirectField); + + // If the identifier reference is inside a block, and it refers to a value + // that is outside the block, create a BlockDeclRefExpr instead of a + // DeclRefExpr. This ensures the value is treated as a copy-in snapshot when + // the block is formed. + // + // We do not do this for things like enum constants, global variables, etc, + // as they do not get snapshotted. + // + switch (shouldCaptureValueReference(*this, NameInfo.getLoc(), VD)) { + case CR_Error: + return ExprError(); + + case CR_Capture: + assert(!SS.isSet() && "referenced local variable with scope specifier?"); + return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ false); + + case CR_CaptureByRef: + assert(!SS.isSet() && "referenced local variable with scope specifier?"); + return BuildBlockDeclRefExpr(*this, VD, NameInfo, /*byref*/ true); + + case CR_NoCapture: { + // If this reference is not in a block or if the referenced + // variable is within the block, create a normal DeclRefExpr. + + QualType type = VD->getType(); + ExprValueKind valueKind = VK_RValue; + + switch (D->getKind()) { + // Ignore all the non-ValueDecl kinds. +#define ABSTRACT_DECL(kind) +#define VALUE(type, base) +#define DECL(type, base) \ + case Decl::type: +#include "clang/AST/DeclNodes.inc" + llvm_unreachable("invalid value decl kind"); + return ExprError(); + + // These shouldn't make it here. + case Decl::ObjCAtDefsField: + case Decl::ObjCIvar: + llvm_unreachable("forming non-member reference to ivar?"); + return ExprError(); + + // Enum constants are always r-values and never references. + // Unresolved using declarations are dependent. + case Decl::EnumConstant: + case Decl::UnresolvedUsingValue: + valueKind = VK_RValue; + break; + + // Fields and indirect fields that got here must be for + // pointer-to-member expressions; we just call them l-values for + // internal consistency, because this subexpression doesn't really + // exist in the high-level semantics. + case Decl::Field: + case Decl::IndirectField: + assert(getLangOptions().CPlusPlus && + "building reference to field in C?"); + + // These can't have reference type in well-formed programs, but + // for internal consistency we do this anyway. + type = type.getNonReferenceType(); + valueKind = VK_LValue; + break; + + // Non-type template parameters are either l-values or r-values + // depending on the type. + case Decl::NonTypeTemplateParm: { + if (const ReferenceType *reftype = type->getAs<ReferenceType>()) { + type = reftype->getPointeeType(); + valueKind = VK_LValue; // even if the parameter is an r-value reference + break; + } + + // For non-references, we need to strip qualifiers just in case + // the template parameter was declared as 'const int' or whatever. + valueKind = VK_RValue; + type = type.getUnqualifiedType(); + break; + } + + case Decl::Var: + // In C, "extern void blah;" is valid and is an r-value. + if (!getLangOptions().CPlusPlus && + !type.hasQualifiers() && + type->isVoidType()) { + valueKind = VK_RValue; + break; + } + // fallthrough + + case Decl::ImplicitParam: + case Decl::ParmVar: + // These are always l-values. + valueKind = VK_LValue; + type = type.getNonReferenceType(); + break; + + case Decl::Function: { + const FunctionType *fty = type->castAs<FunctionType>(); + + // If we're referring to a function with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + if (fty->getResultType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; + valueKind = VK_RValue; + break; + } + + // Functions are l-values in C++. + if (getLangOptions().CPlusPlus) { + valueKind = VK_LValue; + break; + } + + // C99 DR 316 says that, if a function type comes from a + // function definition (without a prototype), that type is only + // used for checking compatibility. Therefore, when referencing + // the function, we pretend that we don't have the full function + // type. + if (!cast<FunctionDecl>(VD)->hasPrototype() && + isa<FunctionProtoType>(fty)) + type = Context.getFunctionNoProtoType(fty->getResultType(), + fty->getExtInfo()); + + // Functions are r-values in C. + valueKind = VK_RValue; + break; + } + + case Decl::CXXMethod: + // If we're referring to a method with an __unknown_anytype + // result type, make the entire expression __unknown_anytype. + // This should only be possible with a type written directly. + if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(VD->getType())) + if (proto->getResultType() == Context.UnknownAnyTy) { + type = Context.UnknownAnyTy; + valueKind = VK_RValue; + break; + } + + // C++ methods are l-values if static, r-values if non-static. + if (cast<CXXMethodDecl>(VD)->isStatic()) { + valueKind = VK_LValue; + break; + } + // fallthrough + + case Decl::CXXConversion: + case Decl::CXXDestructor: + case Decl::CXXConstructor: + valueKind = VK_RValue; + break; + } + + return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS); + } + + } + + llvm_unreachable("unknown capture result"); + return ExprError(); +} + +ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { + PredefinedExpr::IdentType IT; + + switch (Kind) { + default: assert(0 && "Unknown simple primary expr!"); + case tok::kw___func__: IT = PredefinedExpr::Func; break; // [C99 6.4.2.2] + case tok::kw___FUNCTION__: IT = PredefinedExpr::Function; break; + case tok::kw___PRETTY_FUNCTION__: IT = PredefinedExpr::PrettyFunction; break; + } + + // Pre-defined identifiers are of type char[x], where x is the length of the + // string. + + Decl *currentDecl = getCurFunctionOrMethodDecl(); + if (!currentDecl && getCurBlock()) + currentDecl = getCurBlock()->TheDecl; + if (!currentDecl) { + Diag(Loc, diag::ext_predef_outside_function); + currentDecl = Context.getTranslationUnitDecl(); + } + + QualType ResTy; + if (cast<DeclContext>(currentDecl)->isDependentContext()) { + ResTy = Context.DependentTy; + } else { + unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); + + llvm::APInt LengthI(32, Length + 1); + ResTy = Context.CharTy.withConst(); + ResTy = Context.getConstantArrayType(ResTy, LengthI, ArrayType::Normal, 0); + } + return Owned(new (Context) PredefinedExpr(Loc, ResTy, IT)); +} + +ExprResult Sema::ActOnCharacterConstant(const Token &Tok) { + llvm::SmallString<16> CharBuffer; + bool Invalid = false; + llvm::StringRef ThisTok = PP.getSpelling(Tok, CharBuffer, &Invalid); + if (Invalid) + return ExprError(); + + CharLiteralParser Literal(ThisTok.begin(), ThisTok.end(), Tok.getLocation(), + PP); + if (Literal.hadError()) + return ExprError(); + + QualType Ty; + if (!getLangOptions().CPlusPlus) + Ty = Context.IntTy; // 'x' and L'x' -> int in C. + else if (Literal.isWide()) + Ty = Context.WCharTy; // L'x' -> wchar_t in C++. + else if (Literal.isMultiChar()) + Ty = Context.IntTy; // 'wxyz' -> int in C++. + else + Ty = Context.CharTy; // 'x' -> char in C++ + + return Owned(new (Context) CharacterLiteral(Literal.getValue(), + Literal.isWide(), + Ty, Tok.getLocation())); +} + +ExprResult Sema::ActOnNumericConstant(const Token &Tok) { + // Fast path for a single digit (which is quite common). A single digit + // cannot have a trigraph, escaped newline, radix prefix, or type suffix. + if (Tok.getLength() == 1) { + const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok); + unsigned IntSize = Context.Target.getIntWidth(); + return Owned(IntegerLiteral::Create(Context, llvm::APInt(IntSize, Val-'0'), + Context.IntTy, Tok.getLocation())); + } + + llvm::SmallString<512> IntegerBuffer; + // Add padding so that NumericLiteralParser can overread by one character. + IntegerBuffer.resize(Tok.getLength()+1); + const char *ThisTokBegin = &IntegerBuffer[0]; + + // Get the spelling of the token, which eliminates trigraphs, etc. + bool Invalid = false; + unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid); + if (Invalid) + return ExprError(); + + NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, + Tok.getLocation(), PP); + if (Literal.hadError) + return ExprError(); + + Expr *Res; + + if (Literal.isFloatingLiteral()) { + QualType Ty; + if (Literal.isFloat) + Ty = Context.FloatTy; + else if (!Literal.isLong) + Ty = Context.DoubleTy; + else + Ty = Context.LongDoubleTy; + + const llvm::fltSemantics &Format = Context.getFloatTypeSemantics(Ty); + + using llvm::APFloat; + APFloat Val(Format); + + APFloat::opStatus result = Literal.GetFloatValue(Val); + + // Overflow is always an error, but underflow is only an error if + // we underflowed to zero (APFloat reports denormals as underflow). + if ((result & APFloat::opOverflow) || + ((result & APFloat::opUnderflow) && Val.isZero())) { + unsigned diagnostic; + llvm::SmallString<20> buffer; + if (result & APFloat::opOverflow) { + diagnostic = diag::warn_float_overflow; + APFloat::getLargest(Format).toString(buffer); + } else { + diagnostic = diag::warn_float_underflow; + APFloat::getSmallest(Format).toString(buffer); + } + + Diag(Tok.getLocation(), diagnostic) + << Ty + << llvm::StringRef(buffer.data(), buffer.size()); + } + + bool isExact = (result == APFloat::opOK); + Res = FloatingLiteral::Create(Context, Val, isExact, Ty, Tok.getLocation()); + + if (Ty == Context.DoubleTy) { + if (getLangOptions().SinglePrecisionConstants) { + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); + } else if (getLangOptions().OpenCL && !getOpenCLOptions().cl_khr_fp64) { + Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); + Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).take(); + } + } + } else if (!Literal.isIntegerLiteral()) { + return ExprError(); + } else { + QualType Ty; + + // long long is a C99 feature. + if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x && + Literal.isLongLong) + Diag(Tok.getLocation(), diag::ext_longlong); + + // Get the value in the widest-possible width. + llvm::APInt ResultVal(Context.Target.getIntMaxTWidth(), 0); + + if (Literal.GetIntegerValue(ResultVal)) { + // If this value didn't fit into uintmax_t, warn and force to ull. + Diag(Tok.getLocation(), diag::warn_integer_too_large); + Ty = Context.UnsignedLongLongTy; + assert(Context.getTypeSize(Ty) == ResultVal.getBitWidth() && + "long long is not intmax_t?"); + } else { + // If this value fits into a ULL, try to figure out what else it fits into + // according to the rules of C99 6.4.4.1p5. + + // Octal, Hexadecimal, and integers with a U suffix are allowed to + // be an unsigned int. + bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10; + + // Check from smallest to largest, picking the smallest type we can. + unsigned Width = 0; + if (!Literal.isLong && !Literal.isLongLong) { + // Are int/unsigned possibilities? + unsigned IntSize = Context.Target.getIntWidth(); + + // Does it fit in a unsigned int? + if (ResultVal.isIntN(IntSize)) { + // Does it fit in a signed int? + if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0) + Ty = Context.IntTy; + else if (AllowUnsigned) + Ty = Context.UnsignedIntTy; + Width = IntSize; + } + } + + // Are long/unsigned long possibilities? + if (Ty.isNull() && !Literal.isLongLong) { + unsigned LongSize = Context.Target.getLongWidth(); + + // Does it fit in a unsigned long? + if (ResultVal.isIntN(LongSize)) { + // Does it fit in a signed long? + if (!Literal.isUnsigned && ResultVal[LongSize-1] == 0) + Ty = Context.LongTy; + else if (AllowUnsigned) + Ty = Context.UnsignedLongTy; + Width = LongSize; + } + } + + // Finally, check long long if needed. + if (Ty.isNull()) { + unsigned LongLongSize = Context.Target.getLongLongWidth(); + + // Does it fit in a unsigned long long? + if (ResultVal.isIntN(LongLongSize)) { + // Does it fit in a signed long long? + // To be compatible with MSVC, hex integer literals ending with the + // LL or i64 suffix are always signed in Microsoft mode. + if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 || + (getLangOptions().Microsoft && Literal.isLongLong))) + Ty = Context.LongLongTy; + else if (AllowUnsigned) + Ty = Context.UnsignedLongLongTy; + Width = LongLongSize; + } + } + + // If we still couldn't decide a type, we probably have something that + // does not fit in a signed long long, but has no U suffix. + if (Ty.isNull()) { + Diag(Tok.getLocation(), diag::warn_integer_too_large_for_signed); + Ty = Context.UnsignedLongLongTy; + Width = Context.Target.getLongLongWidth(); + } + + if (ResultVal.getBitWidth() != Width) + ResultVal = ResultVal.trunc(Width); + } + Res = IntegerLiteral::Create(Context, ResultVal, Ty, Tok.getLocation()); + } + + // If this is an imaginary literal, create the ImaginaryLiteral wrapper. + if (Literal.isImaginary) + Res = new (Context) ImaginaryLiteral(Res, + Context.getComplexType(Res->getType())); + + return Owned(Res); +} + +ExprResult Sema::ActOnParenExpr(SourceLocation L, + SourceLocation R, Expr *E) { + assert((E != 0) && "ActOnParenExpr() missing expr"); + return Owned(new (Context) ParenExpr(L, R, E)); +} + +static bool CheckVecStepTraitOperandType(Sema &S, QualType T, + SourceLocation Loc, + SourceRange ArgRange) { + // [OpenCL 1.1 6.11.12] "The vec_step built-in function takes a built-in + // scalar or vector data type argument..." + // Every built-in scalar type (OpenCL 1.1 6.1.1) is either an arithmetic + // type (C99 6.2.5p18) or void. + if (!(T->isArithmeticType() || T->isVoidType() || T->isVectorType())) { + S.Diag(Loc, diag::err_vecstep_non_scalar_vector_type) + << T << ArgRange; + return true; + } + + assert((T->isVoidType() || !T->isIncompleteType()) && + "Scalar types should always be complete"); + return false; +} + +static bool CheckExtensionTraitOperandType(Sema &S, QualType T, + SourceLocation Loc, + SourceRange ArgRange, + UnaryExprOrTypeTrait TraitKind) { + // C99 6.5.3.4p1: + if (T->isFunctionType()) { + // alignof(function) is allowed as an extension. + if (TraitKind == UETT_SizeOf) + S.Diag(Loc, diag::ext_sizeof_function_type) << ArgRange; + return false; + } + + // Allow sizeof(void)/alignof(void) as an extension. + if (T->isVoidType()) { + S.Diag(Loc, diag::ext_sizeof_void_type) << TraitKind << ArgRange; + return false; + } + + return true; +} + +static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T, + SourceLocation Loc, + SourceRange ArgRange, + UnaryExprOrTypeTrait TraitKind) { + // Reject sizeof(interface) and sizeof(interface<proto>) in 64-bit mode. + if (S.LangOpts.ObjCNonFragileABI && T->isObjCObjectType()) { + S.Diag(Loc, diag::err_sizeof_nonfragile_interface) + << T << (TraitKind == UETT_SizeOf) + << ArgRange; + return true; + } + + return false; +} + +/// \brief Check the constrains on expression operands to unary type expression +/// and type traits. +/// +/// Completes any types necessary and validates the constraints on the operand +/// expression. The logic mostly mirrors the type-based overload, but may modify +/// the expression as it completes the type for that expression through template +/// instantiation, etc. +bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *Op, + UnaryExprOrTypeTrait ExprKind) { + QualType ExprTy = Op->getType(); + + // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, + // the result is the size of the referenced type." + // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the + // result shall be the alignment of the referenced type." + if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>()) + ExprTy = Ref->getPointeeType(); + + if (ExprKind == UETT_VecStep) + return CheckVecStepTraitOperandType(*this, ExprTy, Op->getExprLoc(), + Op->getSourceRange()); + + // Whitelist some types as extensions + if (!CheckExtensionTraitOperandType(*this, ExprTy, Op->getExprLoc(), + Op->getSourceRange(), ExprKind)) + return false; + + if (RequireCompleteExprType(Op, + PDiag(diag::err_sizeof_alignof_incomplete_type) + << ExprKind << Op->getSourceRange(), + std::make_pair(SourceLocation(), PDiag(0)))) + return true; + + // Completeing the expression's type may have changed it. + ExprTy = Op->getType(); + if (const ReferenceType *Ref = ExprTy->getAs<ReferenceType>()) + ExprTy = Ref->getPointeeType(); + + if (CheckObjCTraitOperandConstraints(*this, ExprTy, Op->getExprLoc(), + Op->getSourceRange(), ExprKind)) + return true; + + return false; +} + +/// \brief Check the constraints on operands to unary expression and type +/// traits. +/// +/// This will complete any types necessary, and validate the various constraints +/// on those operands. +/// +/// The UsualUnaryConversions() function is *not* called by this routine. +/// C99 6.3.2.1p[2-4] all state: +/// Except when it is the operand of the sizeof operator ... +/// +/// C++ [expr.sizeof]p4 +/// The lvalue-to-rvalue, array-to-pointer, and function-to-pointer +/// standard conversions are not applied to the operand of sizeof. +/// +/// This policy is followed for all of the unary trait expressions. +bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType exprType, + SourceLocation OpLoc, + SourceRange ExprRange, + UnaryExprOrTypeTrait ExprKind) { + if (exprType->isDependentType()) + return false; + + // C++ [expr.sizeof]p2: "When applied to a reference or a reference type, + // the result is the size of the referenced type." + // C++ [expr.alignof]p3: "When alignof is applied to a reference type, the + // result shall be the alignment of the referenced type." + if (const ReferenceType *Ref = exprType->getAs<ReferenceType>()) + exprType = Ref->getPointeeType(); + + if (ExprKind == UETT_VecStep) + return CheckVecStepTraitOperandType(*this, exprType, OpLoc, ExprRange); + + // Whitelist some types as extensions + if (!CheckExtensionTraitOperandType(*this, exprType, OpLoc, ExprRange, + ExprKind)) + return false; + + if (RequireCompleteType(OpLoc, exprType, + PDiag(diag::err_sizeof_alignof_incomplete_type) + << ExprKind << ExprRange)) + return true; + + if (CheckObjCTraitOperandConstraints(*this, exprType, OpLoc, ExprRange, + ExprKind)) + return true; + + return false; +} + +static bool CheckAlignOfExpr(Sema &S, Expr *E) { + E = E->IgnoreParens(); + + // alignof decl is always ok. + if (isa<DeclRefExpr>(E)) + return false; + + // Cannot know anything else if the expression is dependent. + if (E->isTypeDependent()) + return false; + + if (E->getBitField()) { + S.Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) + << 1 << E->getSourceRange(); + return true; + } + + // Alignment of a field access is always okay, so long as it isn't a + // bit-field. + if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) + if (isa<FieldDecl>(ME->getMemberDecl())) + return false; + + return S.CheckUnaryExprOrTypeTraitOperand(E, UETT_AlignOf); +} + +bool Sema::CheckVecStepExpr(Expr *E) { + E = E->IgnoreParens(); + + // Cannot know anything else if the expression is dependent. + if (E->isTypeDependent()) + return false; + + return CheckUnaryExprOrTypeTraitOperand(E, UETT_VecStep); +} + +/// \brief Build a sizeof or alignof expression given a type operand. +ExprResult +Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { + if (!TInfo) + return ExprError(); + + QualType T = TInfo->getType(); + + if (!T->isDependentType() && + CheckUnaryExprOrTypeTraitOperand(T, OpLoc, R, ExprKind)) + return ExprError(); + + // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. + return Owned(new (Context) UnaryExprOrTypeTraitExpr(ExprKind, TInfo, + Context.getSizeType(), + OpLoc, R.getEnd())); +} + +/// \brief Build a sizeof or alignof expression given an expression +/// operand. +ExprResult +Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind) { + // Verify that the operand is valid. + bool isInvalid = false; + if (E->isTypeDependent()) { + // Delay type-checking for type-dependent expressions. + } else if (ExprKind == UETT_AlignOf) { + isInvalid = CheckAlignOfExpr(*this, E); + } else if (ExprKind == UETT_VecStep) { + isInvalid = CheckVecStepExpr(E); + } else if (E->getBitField()) { // C99 6.5.3.4p1. + Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0; + isInvalid = true; + } else if (E->getType()->isPlaceholderType()) { + ExprResult PE = CheckPlaceholderExpr(E); + if (PE.isInvalid()) return ExprError(); + return CreateUnaryExprOrTypeTraitExpr(PE.take(), OpLoc, ExprKind); + } else { + isInvalid = CheckUnaryExprOrTypeTraitOperand(E, UETT_SizeOf); + } + + if (isInvalid) + return ExprError(); + + // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. + return Owned(new (Context) UnaryExprOrTypeTraitExpr( + ExprKind, E, Context.getSizeType(), OpLoc, + E->getSourceRange().getEnd())); +} + +/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c +/// expr and the same for @c alignof and @c __alignof +/// Note that the ArgRange is invalid if isType is false. +ExprResult +Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, bool isType, + void *TyOrEx, const SourceRange &ArgRange) { + // If error parsing type, ignore. + if (TyOrEx == 0) return ExprError(); + + if (isType) { + TypeSourceInfo *TInfo; + (void) GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrEx), &TInfo); + return CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, ArgRange); + } + + Expr *ArgEx = (Expr *)TyOrEx; + ExprResult Result = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind); + return move(Result); +} + +static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc, + bool isReal) { + if (V.get()->isTypeDependent()) + return S.Context.DependentTy; + + // _Real and _Imag are only l-values for normal l-values. + if (V.get()->getObjectKind() != OK_Ordinary) { + V = S.DefaultLvalueConversion(V.take()); + if (V.isInvalid()) + return QualType(); + } + + // These operators return the element type of a complex type. + if (const ComplexType *CT = V.get()->getType()->getAs<ComplexType>()) + return CT->getElementType(); + + // Otherwise they pass through real integer and floating point types here. + if (V.get()->getType()->isArithmeticType()) + return V.get()->getType(); + + // Test for placeholders. + ExprResult PR = S.CheckPlaceholderExpr(V.get()); + if (PR.isInvalid()) return QualType(); + if (PR.get() != V.get()) { + V = move(PR); + return CheckRealImagOperand(S, V, Loc, isReal); + } + + // Reject anything else. + S.Diag(Loc, diag::err_realimag_invalid_type) << V.get()->getType() + << (isReal ? "__real" : "__imag"); + return QualType(); +} + + + +ExprResult +Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Kind, Expr *Input) { + UnaryOperatorKind Opc; + switch (Kind) { + default: assert(0 && "Unknown unary op!"); + case tok::plusplus: Opc = UO_PostInc; break; + case tok::minusminus: Opc = UO_PostDec; break; + } + + return BuildUnaryOp(S, OpLoc, Opc, Input); +} + +/// Expressions of certain arbitrary types are forbidden by C from +/// having l-value type. These are: +/// - 'void', but not qualified void +/// - function types +/// +/// The exact rule here is C99 6.3.2.1: +/// An lvalue is an expression with an object type or an incomplete +/// type other than void. +static bool IsCForbiddenLValueType(ASTContext &C, QualType T) { + return ((T->isVoidType() && !T.hasQualifiers()) || + T->isFunctionType()); +} + +ExprResult +Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc) { + // Since this might be a postfix expression, get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); + + Expr *LHSExp = Base, *RHSExp = Idx; + + if (getLangOptions().CPlusPlus && + (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) { + return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, + Context.DependentTy, + VK_LValue, OK_Ordinary, + RLoc)); + } + + if (getLangOptions().CPlusPlus && + (LHSExp->getType()->isRecordType() || + LHSExp->getType()->isEnumeralType() || + RHSExp->getType()->isRecordType() || + RHSExp->getType()->isEnumeralType())) { + return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx); + } + + return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc); +} + + +ExprResult +Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, + Expr *Idx, SourceLocation RLoc) { + Expr *LHSExp = Base; + Expr *RHSExp = Idx; + + // Perform default conversions. + if (!LHSExp->getType()->getAs<VectorType>()) { + ExprResult Result = DefaultFunctionArrayLvalueConversion(LHSExp); + if (Result.isInvalid()) + return ExprError(); + LHSExp = Result.take(); + } + ExprResult Result = DefaultFunctionArrayLvalueConversion(RHSExp); + if (Result.isInvalid()) + return ExprError(); + RHSExp = Result.take(); + + QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType(); + ExprValueKind VK = VK_LValue; + ExprObjectKind OK = OK_Ordinary; + + // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent + // to the expression *((e1)+(e2)). This means the array "Base" may actually be + // in the subscript position. As a result, we need to derive the array base + // and index from the expression types. + Expr *BaseExpr, *IndexExpr; + QualType ResultType; + if (LHSTy->isDependentType() || RHSTy->isDependentType()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = Context.DependentTy; + } else if (const PointerType *PTy = LHSTy->getAs<PointerType>()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = PTy->getPointeeType(); + } else if (const PointerType *PTy = RHSTy->getAs<PointerType>()) { + // Handle the uncommon case of "123[Ptr]". + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = PTy->getPointeeType(); + } else if (const ObjCObjectPointerType *PTy = + LHSTy->getAs<ObjCObjectPointerType>()) { + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = PTy->getPointeeType(); + } else if (const ObjCObjectPointerType *PTy = + RHSTy->getAs<ObjCObjectPointerType>()) { + // Handle the uncommon case of "123[Ptr]". + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = PTy->getPointeeType(); + } else if (const VectorType *VTy = LHSTy->getAs<VectorType>()) { + BaseExpr = LHSExp; // vectors: V[123] + IndexExpr = RHSExp; + VK = LHSExp->getValueKind(); + if (VK != VK_RValue) + OK = OK_VectorComponent; + + // FIXME: need to deal with const... + ResultType = VTy->getElementType(); + } else if (LHSTy->isArrayType()) { + // If we see an array that wasn't promoted by + // DefaultFunctionArrayLvalueConversion, it must be an array that + // wasn't promoted because of the C90 rule that doesn't + // allow promoting non-lvalue arrays. Warn, then + // force the promotion here. + Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << + LHSExp->getSourceRange(); + LHSExp = ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), + CK_ArrayToPointerDecay).take(); + LHSTy = LHSExp->getType(); + + BaseExpr = LHSExp; + IndexExpr = RHSExp; + ResultType = LHSTy->getAs<PointerType>()->getPointeeType(); + } else if (RHSTy->isArrayType()) { + // Same as previous, except for 123[f().a] case + Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) << + RHSExp->getSourceRange(); + RHSExp = ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), + CK_ArrayToPointerDecay).take(); + RHSTy = RHSExp->getType(); + + BaseExpr = RHSExp; + IndexExpr = LHSExp; + ResultType = RHSTy->getAs<PointerType>()->getPointeeType(); + } else { + return ExprError(Diag(LLoc, diag::err_typecheck_subscript_value) + << LHSExp->getSourceRange() << RHSExp->getSourceRange()); + } + // C99 6.5.2.1p1 + if (!IndexExpr->getType()->isIntegerType() && !IndexExpr->isTypeDependent()) + return ExprError(Diag(LLoc, diag::err_typecheck_subscript_not_integer) + << IndexExpr->getSourceRange()); + + if ((IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_S) || + IndexExpr->getType()->isSpecificBuiltinType(BuiltinType::Char_U)) + && !IndexExpr->isTypeDependent()) + Diag(LLoc, diag::warn_subscript_is_char) << IndexExpr->getSourceRange(); + + // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly, + // C++ [expr.sub]p1: The type "T" shall be a completely-defined object + // type. Note that Functions are not objects, and that (in C99 parlance) + // incomplete types are not object types. + if (ResultType->isFunctionType()) { + Diag(BaseExpr->getLocStart(), diag::err_subscript_function_type) + << ResultType << BaseExpr->getSourceRange(); + return ExprError(); + } + + if (ResultType->isVoidType() && !getLangOptions().CPlusPlus) { + // GNU extension: subscripting on pointer to void + Diag(LLoc, diag::ext_gnu_void_ptr) + << BaseExpr->getSourceRange(); + + // C forbids expressions of unqualified void type from being l-values. + // See IsCForbiddenLValueType. + if (!ResultType.hasQualifiers()) VK = VK_RValue; + } else if (!ResultType->isDependentType() && + RequireCompleteType(LLoc, ResultType, + PDiag(diag::err_subscript_incomplete_type) + << BaseExpr->getSourceRange())) + return ExprError(); + + // Diagnose bad cases where we step over interface counts. + if (ResultType->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { + Diag(LLoc, diag::err_subscript_nonfragile_interface) + << ResultType << BaseExpr->getSourceRange(); + return ExprError(); + } + + assert(VK == VK_RValue || LangOpts.CPlusPlus || + !IsCForbiddenLValueType(Context, ResultType)); + + return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, + ResultType, VK, OK, RLoc)); +} + +/// Check an ext-vector component access expression. +/// +/// VK should be set in advance to the value kind of the base +/// expression. +static QualType +CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK, + SourceLocation OpLoc, const IdentifierInfo *CompName, + SourceLocation CompLoc) { + // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements, + // see FIXME there. + // + // FIXME: This logic can be greatly simplified by splitting it along + // halving/not halving and reworking the component checking. + const ExtVectorType *vecType = baseType->getAs<ExtVectorType>(); + + // The vector accessor can't exceed the number of elements. + const char *compStr = CompName->getNameStart(); + + // This flag determines whether or not the component is one of the four + // special names that indicate a subset of exactly half the elements are + // to be selected. + bool HalvingSwizzle = false; + + // This flag determines whether or not CompName has an 's' char prefix, + // indicating that it is a string of hex values to be used as vector indices. + bool HexSwizzle = *compStr == 's' || *compStr == 'S'; + + bool HasRepeated = false; + bool HasIndex[16] = {}; + + int Idx; + + // Check that we've found one of the special components, or that the component + // names must come from the same set. + if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") || + !strcmp(compStr, "even") || !strcmp(compStr, "odd")) { + HalvingSwizzle = true; + } else if (!HexSwizzle && + (Idx = vecType->getPointAccessorIdx(*compStr)) != -1) { + do { + if (HasIndex[Idx]) HasRepeated = true; + HasIndex[Idx] = true; + compStr++; + } while (*compStr && (Idx = vecType->getPointAccessorIdx(*compStr)) != -1); + } else { + if (HexSwizzle) compStr++; + while ((Idx = vecType->getNumericAccessorIdx(*compStr)) != -1) { + if (HasIndex[Idx]) HasRepeated = true; + HasIndex[Idx] = true; + compStr++; + } + } + + if (!HalvingSwizzle && *compStr) { + // We didn't get to the end of the string. This means the component names + // didn't come from the same set *or* we encountered an illegal name. + S.Diag(OpLoc, diag::err_ext_vector_component_name_illegal) + << llvm::StringRef(compStr, 1) << SourceRange(CompLoc); + return QualType(); + } + + // Ensure no component accessor exceeds the width of the vector type it + // operates on. + if (!HalvingSwizzle) { + compStr = CompName->getNameStart(); + + if (HexSwizzle) + compStr++; + + while (*compStr) { + if (!vecType->isAccessorWithinNumElements(*compStr++)) { + S.Diag(OpLoc, diag::err_ext_vector_component_exceeds_length) + << baseType << SourceRange(CompLoc); + return QualType(); + } + } + } + + // The component accessor looks fine - now we need to compute the actual type. + // The vector type is implied by the component accessor. For example, + // vec4.b is a float, vec4.xy is a vec2, vec4.rgb is a vec3, etc. + // vec4.s0 is a float, vec4.s23 is a vec3, etc. + // vec4.hi, vec4.lo, vec4.e, and vec4.o all return vec2. + unsigned CompSize = HalvingSwizzle ? (vecType->getNumElements() + 1) / 2 + : CompName->getLength(); + if (HexSwizzle) + CompSize--; + + if (CompSize == 1) + return vecType->getElementType(); + + if (HasRepeated) VK = VK_RValue; + + QualType VT = S.Context.getExtVectorType(vecType->getElementType(), CompSize); + // Now look up the TypeDefDecl from the vector type. Without this, + // diagostics look bad. We want extended vector types to appear built-in. + for (unsigned i = 0, E = S.ExtVectorDecls.size(); i != E; ++i) { + if (S.ExtVectorDecls[i]->getUnderlyingType() == VT) + return S.Context.getTypedefType(S.ExtVectorDecls[i]); + } + return VT; // should never get here (a typedef type should always be found). +} + +static Decl *FindGetterSetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, + IdentifierInfo *Member, + const Selector &Sel, + ASTContext &Context) { + if (Member) + if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Member)) + return PD; + if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) + return OMD; + + for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), + E = PDecl->protocol_end(); I != E; ++I) { + if (Decl *D = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel, + Context)) + return D; + } + return 0; +} + +static Decl *FindGetterSetterNameDecl(const ObjCObjectPointerType *QIdTy, + IdentifierInfo *Member, + const Selector &Sel, + ASTContext &Context) { + // Check protocols on qualified interfaces. + Decl *GDecl = 0; + for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), + E = QIdTy->qual_end(); I != E; ++I) { + if (Member) + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { + GDecl = PD; + break; + } + // Also must look for a getter or setter name which uses property syntax. + if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) { + GDecl = OMD; + break; + } + } + if (!GDecl) { + for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), + E = QIdTy->qual_end(); I != E; ++I) { + // Search in the protocol-qualifier list of current protocol. + GDecl = FindGetterSetterNameDeclFromProtocolList(*I, Member, Sel, + Context); + if (GDecl) + return GDecl; + } + } + return GDecl; +} + +ExprResult +Sema::ActOnDependentMemberExpr(Expr *BaseExpr, QualType BaseType, + bool IsArrow, SourceLocation OpLoc, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + // Even in dependent contexts, try to diagnose base expressions with + // obviously wrong types, e.g.: + // + // T* t; + // t.f; + // + // In Obj-C++, however, the above expression is valid, since it could be + // accessing the 'f' property if T is an Obj-C interface. The extra check + // allows this, while still reporting an error if T is a struct pointer. + if (!IsArrow) { + const PointerType *PT = BaseType->getAs<PointerType>(); + if (PT && (!getLangOptions().ObjC1 || + PT->getPointeeType()->isRecordType())) { + assert(BaseExpr && "cannot happen with implicit member accesses"); + Diag(NameInfo.getLoc(), diag::err_typecheck_member_reference_struct_union) + << BaseType << BaseExpr->getSourceRange(); + return ExprError(); + } + } + + assert(BaseType->isDependentType() || + NameInfo.getName().isDependentName() || + isDependentScopeSpecifier(SS)); + + // Get the type being accessed in BaseType. If this is an arrow, the BaseExpr + // must have pointer type, and the accessed type is the pointee. + return Owned(CXXDependentScopeMemberExpr::Create(Context, BaseExpr, BaseType, + IsArrow, OpLoc, + SS.getWithLocInContext(Context), + FirstQualifierInScope, + NameInfo, TemplateArgs)); +} + +/// We know that the given qualified member reference points only to +/// declarations which do not belong to the static type of the base +/// expression. Diagnose the problem. +static void DiagnoseQualifiedMemberReference(Sema &SemaRef, + Expr *BaseExpr, + QualType BaseType, + const CXXScopeSpec &SS, + NamedDecl *rep, + const DeclarationNameInfo &nameInfo) { + // If this is an implicit member access, use a different set of + // diagnostics. + if (!BaseExpr) + return DiagnoseInstanceReference(SemaRef, SS, rep, nameInfo); + + SemaRef.Diag(nameInfo.getLoc(), diag::err_qualified_member_of_unrelated) + << SS.getRange() << rep << BaseType; +} + +// Check whether the declarations we found through a nested-name +// specifier in a member expression are actually members of the base +// type. The restriction here is: +// +// C++ [expr.ref]p2: +// ... In these cases, the id-expression shall name a +// member of the class or of one of its base classes. +// +// So it's perfectly legitimate for the nested-name specifier to name +// an unrelated class, and for us to find an overload set including +// decls from classes which are not superclasses, as long as the decl +// we actually pick through overload resolution is from a superclass. +bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, + QualType BaseType, + const CXXScopeSpec &SS, + const LookupResult &R) { + const RecordType *BaseRT = BaseType->getAs<RecordType>(); + if (!BaseRT) { + // We can't check this yet because the base type is still + // dependent. + assert(BaseType->isDependentType()); + return false; + } + CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl()); + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { + // If this is an implicit member reference and we find a + // non-instance member, it's not an error. + if (!BaseExpr && !(*I)->isCXXInstanceMember()) + return false; + + // Note that we use the DC of the decl, not the underlying decl. + DeclContext *DC = (*I)->getDeclContext(); + while (DC->isTransparentContext()) + DC = DC->getParent(); + + if (!DC->isRecord()) + continue; + + llvm::SmallPtrSet<CXXRecordDecl*,4> MemberRecord; + MemberRecord.insert(cast<CXXRecordDecl>(DC)->getCanonicalDecl()); + + if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord)) + return false; + } + + DiagnoseQualifiedMemberReference(*this, BaseExpr, BaseType, SS, + R.getRepresentativeDecl(), + R.getLookupNameInfo()); + return true; +} + +static bool +LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, + SourceRange BaseRange, const RecordType *RTy, + SourceLocation OpLoc, CXXScopeSpec &SS, + bool HasTemplateArgs) { + RecordDecl *RDecl = RTy->getDecl(); + if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0), + SemaRef.PDiag(diag::err_typecheck_incomplete_tag) + << BaseRange)) + return true; + + if (HasTemplateArgs) { + // LookupTemplateName doesn't expect these both to exist simultaneously. + QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0); + + bool MOUS; + SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS); + return false; + } + + DeclContext *DC = RDecl; + if (SS.isSet()) { + // If the member name was a qualified-id, look into the + // nested-name-specifier. + DC = SemaRef.computeDeclContext(SS, false); + + if (SemaRef.RequireCompleteDeclContext(SS, DC)) { + SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag) + << SS.getRange() << DC; + return true; + } + + assert(DC && "Cannot handle non-computable dependent contexts in lookup"); + + if (!isa<TypeDecl>(DC)) { + SemaRef.Diag(R.getNameLoc(), diag::err_qualified_member_nonclass) + << DC << SS.getRange(); + return true; + } + } + + // The record definition is complete, now look up the member. + SemaRef.LookupQualifiedName(R, DC); + + if (!R.empty()) + return false; + + // We didn't find anything with the given name, so try to correct + // for typos. + DeclarationName Name = R.getLookupName(); + if (SemaRef.CorrectTypo(R, 0, &SS, DC, false, Sema::CTC_MemberLookup) && + !R.empty() && + (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) { + SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << DC << R.getLookupName() << SS.getRange() + << FixItHint::CreateReplacement(R.getNameLoc(), + R.getLookupName().getAsString()); + if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) + SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); + return false; + } else { + R.clear(); + R.setLookupName(Name); + } + + return false; +} + +ExprResult +Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, + SourceLocation OpLoc, bool IsArrow, + CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + if (BaseType->isDependentType() || + (SS.isSet() && isDependentScopeSpecifier(SS))) + return ActOnDependentMemberExpr(Base, BaseType, + IsArrow, OpLoc, + SS, FirstQualifierInScope, + NameInfo, TemplateArgs); + + LookupResult R(*this, NameInfo, LookupMemberName); + + // Implicit member accesses. + if (!Base) { + QualType RecordTy = BaseType; + if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType(); + if (LookupMemberExprInRecord(*this, R, SourceRange(), + RecordTy->getAs<RecordType>(), + OpLoc, SS, TemplateArgs != 0)) + return ExprError(); + + // Explicit member accesses. + } else { + ExprResult BaseResult = Owned(Base); + ExprResult Result = + LookupMemberExpr(R, BaseResult, IsArrow, OpLoc, + SS, /*ObjCImpDecl*/ 0, TemplateArgs != 0); + + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + + if (Result.isInvalid()) { + Owned(Base); + return ExprError(); + } + + if (Result.get()) + return move(Result); + + // LookupMemberExpr can modify Base, and thus change BaseType + BaseType = Base->getType(); + } + + return BuildMemberReferenceExpr(Base, BaseType, + OpLoc, IsArrow, SS, FirstQualifierInScope, + R, TemplateArgs); +} + +ExprResult +Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, + SourceLocation OpLoc, bool IsArrow, + const CXXScopeSpec &SS, + NamedDecl *FirstQualifierInScope, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs, + bool SuppressQualifierCheck) { + QualType BaseType = BaseExprType; + if (IsArrow) { + assert(BaseType->isPointerType()); + BaseType = BaseType->getAs<PointerType>()->getPointeeType(); + } + R.setBaseObjectType(BaseType); + + const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); + DeclarationName MemberName = MemberNameInfo.getName(); + SourceLocation MemberLoc = MemberNameInfo.getLoc(); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + // Rederive where we looked up. + DeclContext *DC = (SS.isSet() + ? computeDeclContext(SS, false) + : BaseType->getAs<RecordType>()->getDecl()); + + Diag(R.getNameLoc(), diag::err_no_member) + << MemberName << DC + << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + return ExprError(); + } + + // Diagnose lookups that find only declarations from a non-base + // type. This is possible for either qualified lookups (which may + // have been qualified with an unrelated type) or implicit member + // expressions (which were found with unqualified lookup and thus + // may have come from an enclosing scope). Note that it's okay for + // lookup to find declarations from a non-base type as long as those + // aren't the ones picked by overload resolution. + if ((SS.isSet() || !BaseExpr || + (isa<CXXThisExpr>(BaseExpr) && + cast<CXXThisExpr>(BaseExpr)->isImplicit())) && + !SuppressQualifierCheck && + CheckQualifiedMemberReference(BaseExpr, BaseType, SS, R)) + return ExprError(); + + // Construct an unresolved result if we in fact got an unresolved + // result. + if (R.isOverloadedResult() || R.isUnresolvableResult()) { + // Suppress any lookup-related diagnostics; we'll do these when we + // pick a member. + R.suppressDiagnostics(); + + UnresolvedMemberExpr *MemExpr + = UnresolvedMemberExpr::Create(Context, R.isUnresolvableResult(), + BaseExpr, BaseExprType, + IsArrow, OpLoc, + SS.getWithLocInContext(Context), + MemberNameInfo, + TemplateArgs, R.begin(), R.end()); + + return Owned(MemExpr); + } + + assert(R.isSingleResult()); + DeclAccessPair FoundDecl = R.begin().getPair(); + NamedDecl *MemberDecl = R.getFoundDecl(); + + // FIXME: diagnose the presence of template arguments now. + + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (MemberDecl->isInvalidDecl()) + return ExprError(); + + // Handle the implicit-member-access case. + if (!BaseExpr) { + // If this is not an instance member, convert to a non-member access. + if (!MemberDecl->isCXXInstanceMember()) + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), MemberDecl); + + SourceLocation Loc = R.getNameLoc(); + if (SS.getRange().isValid()) + Loc = SS.getRange().getBegin(); + BaseExpr = new (Context) CXXThisExpr(Loc, BaseExprType,/*isImplicit=*/true); + } + + bool ShouldCheckUse = true; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) { + // Don't diagnose the use of a virtual member function unless it's + // explicitly qualified. + if (MD->isVirtual() && !SS.isSet()) + ShouldCheckUse = false; + } + + // Check the use of this member. + if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) { + Owned(BaseExpr); + return ExprError(); + } + + // Perform a property load on the base regardless of whether we + // actually need it for the declaration. + if (BaseExpr->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(BaseExpr); + if (Result.isInvalid()) + return ExprError(); + BaseExpr = Result.take(); + } + + if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) + return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, + SS, FD, FoundDecl, MemberNameInfo); + + if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) + // We may have found a field within an anonymous union or struct + // (C++ [class.union]). + return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, + BaseExpr, OpLoc); + + if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, Var); + return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, + Var, FoundDecl, MemberNameInfo, + Var->getType().getNonReferenceType(), + VK_LValue, OK_Ordinary)); + } + + if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { + ExprValueKind valueKind; + QualType type; + if (MemberFn->isInstance()) { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } else { + valueKind = VK_LValue; + type = MemberFn->getType(); + } + + MarkDeclarationReferenced(MemberLoc, MemberDecl); + return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, + MemberFn, FoundDecl, MemberNameInfo, + type, valueKind, OK_Ordinary)); + } + assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); + + if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, MemberDecl); + return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, + Enum, FoundDecl, MemberNameInfo, + Enum->getType(), VK_RValue, OK_Ordinary)); + } + + Owned(BaseExpr); + + // We found something that we didn't expect. Complain. + if (isa<TypeDecl>(MemberDecl)) + Diag(MemberLoc, diag::err_typecheck_member_reference_type) + << MemberName << BaseType << int(IsArrow); + else + Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) + << MemberName << BaseType << int(IsArrow); + + Diag(MemberDecl->getLocation(), diag::note_member_declared_here) + << MemberName; + R.suppressDiagnostics(); + return ExprError(); +} + +/// Given that normal member access failed on the given expression, +/// and given that the expression's type involves builtin-id or +/// builtin-Class, decide whether substituting in the redefinition +/// types would be profitable. The redefinition type is whatever +/// this translation unit tried to typedef to id/Class; we store +/// it to the side and then re-use it in places like this. +static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { + const ObjCObjectPointerType *opty + = base.get()->getType()->getAs<ObjCObjectPointerType>(); + if (!opty) return false; + + const ObjCObjectType *ty = opty->getObjectType(); + + QualType redef; + if (ty->isObjCId()) { + redef = S.Context.ObjCIdRedefinitionType; + } else if (ty->isObjCClass()) { + redef = S.Context.ObjCClassRedefinitionType; + } else { + return false; + } + + // Do the substitution as long as the redefinition type isn't just a + // possibly-qualified pointer to builtin-id or builtin-Class again. + opty = redef->getAs<ObjCObjectPointerType>(); + if (opty && !opty->getObjectType()->getInterface() != 0) + return false; + + base = S.ImpCastExprToType(base.take(), redef, CK_BitCast); + return true; +} + +/// Look up the given member of the given non-type-dependent +/// expression. This can return in one of two ways: +/// * If it returns a sentinel null-but-valid result, the caller will +/// assume that lookup was performed and the results written into +/// the provided structure. It will take over from there. +/// * Otherwise, the returned expression will be produced in place of +/// an ordinary member expression. +/// +/// The ObjCImpDecl bit is a gross hack that will need to be properly +/// fixed for ObjC++. +ExprResult +Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, + bool &IsArrow, SourceLocation OpLoc, + CXXScopeSpec &SS, + Decl *ObjCImpDecl, bool HasTemplateArgs) { + assert(BaseExpr.get() && "no base expression"); + + // Perform default conversions. + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); + + if (IsArrow) { + BaseExpr = DefaultLvalueConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); + } + + QualType BaseType = BaseExpr.get()->getType(); + assert(!BaseType->isDependentType()); + + DeclarationName MemberName = R.getLookupName(); + SourceLocation MemberLoc = R.getNameLoc(); + + // For later type-checking purposes, turn arrow accesses into dot + // accesses. The only access type we support that doesn't follow + // the C equivalence "a->b === (*a).b" is ObjC property accesses, + // and those never use arrows, so this is unaffected. + if (IsArrow) { + if (const PointerType *Ptr = BaseType->getAs<PointerType>()) + BaseType = Ptr->getPointeeType(); + else if (const ObjCObjectPointerType *Ptr + = BaseType->getAs<ObjCObjectPointerType>()) + BaseType = Ptr->getPointeeType(); + else if (BaseType->isRecordType()) { + // Recover from arrow accesses to records, e.g.: + // struct MyRecord foo; + // foo->bar + // This is actually well-formed in C++ if MyRecord has an + // overloaded operator->, but that should have been dealt with + // by now. + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); + IsArrow = false; + } else if (BaseType == Context.BoundMemberTy) { + goto fail; + } else { + Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) + << BaseType << BaseExpr.get()->getSourceRange(); + return ExprError(); + } + } + + // Handle field access to simple records. + if (const RecordType *RTy = BaseType->getAs<RecordType>()) { + if (LookupMemberExprInRecord(*this, R, BaseExpr.get()->getSourceRange(), + RTy, OpLoc, SS, HasTemplateArgs)) + return ExprError(); + + // Returning valid-but-null is how we indicate to the caller that + // the lookup result was filled in. + return Owned((Expr*) 0); + } + + // Handle ivar access to Objective-C objects. + if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) { + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + + // There are three cases for the base type: + // - builtin id (qualified or unqualified) + // - builtin Class (qualified or unqualified) + // - an interface + ObjCInterfaceDecl *IDecl = OTy->getInterface(); + if (!IDecl) { + // There's an implicit 'isa' ivar on all objects. + // But we only actually find it this way on objects of type 'id', + // apparently. + if (OTy->isObjCId() && Member->isStr("isa")) + return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc, + Context.getObjCClassType())); + + if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + goto fail; + } + + ObjCInterfaceDecl *ClassDeclared; + ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); + + if (!IV) { + // Attempt to correct for typos in ivar names. + LookupResult Res(*this, R.getLookupName(), R.getNameLoc(), + LookupMemberName); + if (CorrectTypo(Res, 0, 0, IDecl, false, + IsArrow ? CTC_ObjCIvarLookup + : CTC_ObjCPropertyLookup) && + (IV = Res.getAsSingle<ObjCIvarDecl>())) { + Diag(R.getNameLoc(), + diag::err_typecheck_member_reference_ivar_suggest) + << IDecl->getDeclName() << MemberName << IV->getDeclName() + << FixItHint::CreateReplacement(R.getNameLoc(), + IV->getNameAsString()); + Diag(IV->getLocation(), diag::note_previous_decl) + << IV->getDeclName(); + } else { + Res.clear(); + Res.setLookupName(Member); + + Diag(MemberLoc, diag::err_typecheck_member_reference_ivar) + << IDecl->getDeclName() << MemberName + << BaseExpr.get()->getSourceRange(); + return ExprError(); + } + } + + // If the decl being referenced had an error, return an error for this + // sub-expr without emitting another error, in order to avoid cascading + // error cases. + if (IV->isInvalidDecl()) + return ExprError(); + + // Check whether we can reference this field. + if (DiagnoseUseOfDecl(IV, MemberLoc)) + return ExprError(); + if (IV->getAccessControl() != ObjCIvarDecl::Public && + IV->getAccessControl() != ObjCIvarDecl::Package) { + ObjCInterfaceDecl *ClassOfMethodDecl = 0; + if (ObjCMethodDecl *MD = getCurMethodDecl()) + ClassOfMethodDecl = MD->getClassInterface(); + else if (ObjCImpDecl && getCurFunctionDecl()) { + // Case of a c-function declared inside an objc implementation. + // FIXME: For a c-style function nested inside an objc implementation + // class, there is no implementation context available, so we pass + // down the context as argument to this routine. Ideally, this context + // need be passed down in the AST node and somehow calculated from the + // AST for a function decl. + if (ObjCImplementationDecl *IMPD = + dyn_cast<ObjCImplementationDecl>(ObjCImpDecl)) + ClassOfMethodDecl = IMPD->getClassInterface(); + else if (ObjCCategoryImplDecl* CatImplClass = + dyn_cast<ObjCCategoryImplDecl>(ObjCImpDecl)) + ClassOfMethodDecl = CatImplClass->getClassInterface(); + } + + if (IV->getAccessControl() == ObjCIvarDecl::Private) { + if (ClassDeclared != IDecl || + ClassOfMethodDecl != ClassDeclared) + Diag(MemberLoc, diag::error_private_ivar_access) + << IV->getDeclName(); + } else if (!IDecl->isSuperClassOf(ClassOfMethodDecl)) + // @protected + Diag(MemberLoc, diag::error_protected_ivar_access) + << IV->getDeclName(); + } + + return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), + MemberLoc, BaseExpr.take(), + IsArrow)); + } + + // Objective-C property access. + const ObjCObjectPointerType *OPT; + if (!IsArrow && (OPT = BaseType->getAs<ObjCObjectPointerType>())) { + // This actually uses the base as an r-value. + BaseExpr = DefaultLvalueConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); + + assert(Context.hasSameUnqualifiedType(BaseType, BaseExpr.get()->getType())); + + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + + const ObjCObjectType *OT = OPT->getObjectType(); + + // id, with and without qualifiers. + if (OT->isObjCId()) { + // Check protocols on qualified interfaces. + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + if (Decl *PMDecl = FindGetterSetterNameDecl(OPT, Member, Sel, Context)) { + if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(PMDecl)) { + // Check the use of this declaration + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + + QualType T = PD->getType(); + if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + T = getMessageSendResultType(BaseType, Getter, false, false); + + return Owned(new (Context) ObjCPropertyRefExpr(PD, T, + VK_LValue, + OK_ObjCProperty, + MemberLoc, + BaseExpr.take())); + } + + if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(PMDecl)) { + // Check the use of this method. + if (DiagnoseUseOfDecl(OMD, MemberLoc)) + return ExprError(); + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); + ObjCMethodDecl *SMD = 0; + if (Decl *SDecl = FindGetterSetterNameDecl(OPT, /*Property id*/0, + SetterSel, Context)) + SMD = dyn_cast<ObjCMethodDecl>(SDecl); + QualType PType = getMessageSendResultType(BaseType, OMD, false, + false); + + ExprValueKind VK = VK_LValue; + if (!getLangOptions().CPlusPlus && + IsCForbiddenLValueType(Context, PType)) + VK = VK_RValue; + ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); + + return Owned(new (Context) ObjCPropertyRefExpr(OMD, SMD, PType, + VK, OK, + MemberLoc, BaseExpr.take())); + } + } + // Use of id.member can only be for a property reference. Do not + // use the 'id' redefinition in this case. + if (IsArrow && ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + + return ExprError(Diag(MemberLoc, diag::err_property_not_found) + << MemberName << BaseType); + } + + // 'Class', unqualified only. + if (OT->isObjCClass()) { + // Only works in a method declaration (??!). + ObjCMethodDecl *MD = getCurMethodDecl(); + if (!MD) { + if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + + goto fail; + } + + // Also must look for a getter name which uses property syntax. + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + ObjCInterfaceDecl *IFace = MD->getClassInterface(); + ObjCMethodDecl *Getter; + if ((Getter = IFace->lookupClassMethod(Sel))) { + // Check the use of this method. + if (DiagnoseUseOfDecl(Getter, MemberLoc)) + return ExprError(); + } else + Getter = IFace->lookupPrivateMethod(Sel, false); + // If we found a getter then this may be a valid dot-reference, we + // will look for the matching setter, in case it is needed. + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + Setter = IFace->lookupPrivateMethod(SetterSel, false); + } + // Look through local category implementations associated with the class. + if (!Setter) + Setter = IFace->getCategoryClassMethod(SetterSel); + + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) + return ExprError(); + + if (Getter || Setter) { + QualType PType; + + ExprValueKind VK = VK_LValue; + if (Getter) { + PType = getMessageSendResultType(QualType(OT, 0), Getter, true, + false); + if (!getLangOptions().CPlusPlus && + IsCForbiddenLValueType(Context, PType)) + VK = VK_RValue; + } else { + // Get the expression type from Setter's incoming parameter. + PType = (*(Setter->param_end() -1))->getType(); + } + ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); + + // FIXME: we must check that the setter has property type. + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + MemberLoc, BaseExpr.take())); + } + + if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + + return ExprError(Diag(MemberLoc, diag::err_property_not_found) + << MemberName << BaseType); + } + + // Normal property access. + return HandleExprPropertyRefExpr(OPT, BaseExpr.get(), MemberName, MemberLoc, + SourceLocation(), QualType(), false); + } + + // Handle 'field access' to vectors, such as 'V.xx'. + if (BaseType->isExtVectorType()) { + // FIXME: this expr should store IsArrow. + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + ExprValueKind VK = (IsArrow ? VK_LValue : BaseExpr.get()->getValueKind()); + QualType ret = CheckExtVectorComponent(*this, BaseType, VK, OpLoc, + Member, MemberLoc); + if (ret.isNull()) + return ExprError(); + + return Owned(new (Context) ExtVectorElementExpr(ret, VK, BaseExpr.take(), + *Member, MemberLoc)); + } + + // Adjust builtin-sel to the appropriate redefinition type if that's + // not just a pointer to builtin-sel again. + if (IsArrow && + BaseType->isSpecificBuiltinType(BuiltinType::ObjCSel) && + !Context.ObjCSelRedefinitionType->isObjCSelType()) { + BaseExpr = ImpCastExprToType(BaseExpr.take(), Context.ObjCSelRedefinitionType, + CK_BitCast); + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + } + + // Failure cases. + fail: + + // Recover from dot accesses to pointers, e.g.: + // type *foo; + // foo.bar + // This is actually well-formed in two cases: + // - 'type' is an Objective C type + // - 'bar' is a pseudo-destructor name which happens to refer to + // the appropriate pointer type + if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { + if (!IsArrow && Ptr->getPointeeType()->isRecordType() && + MemberName.getNameKind() != DeclarationName::CXXDestructorName) { + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "->"); + + // Recurse as an -> access. + IsArrow = true; + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + } + } + + // If the user is trying to apply -> or . to a function name, it's probably + // because they forgot parentheses to call that function. + QualType ZeroArgCallTy; + UnresolvedSet<4> Overloads; + if (isExprCallable(*BaseExpr.get(), ZeroArgCallTy, Overloads)) { + if (ZeroArgCallTy.isNull()) { + Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) + << (Overloads.size() > 1) << 0 << BaseExpr.get()->getSourceRange(); + UnresolvedSet<2> PlausibleOverloads; + for (OverloadExpr::decls_iterator It = Overloads.begin(), + DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { + const FunctionDecl *OverloadDecl = cast<FunctionDecl>(*It); + QualType OverloadResultTy = OverloadDecl->getResultType(); + if ((!IsArrow && OverloadResultTy->isRecordType()) || + (IsArrow && OverloadResultTy->isPointerType() && + OverloadResultTy->getPointeeType()->isRecordType())) + PlausibleOverloads.addDecl(It.getDecl()); + } + NoteOverloads(PlausibleOverloads, BaseExpr.get()->getExprLoc()); + return ExprError(); + } + if ((!IsArrow && ZeroArgCallTy->isRecordType()) || + (IsArrow && ZeroArgCallTy->isPointerType() && + ZeroArgCallTy->getPointeeType()->isRecordType())) { + // At this point, we know BaseExpr looks like it's potentially callable + // with 0 arguments, and that it returns something of a reasonable type, + // so we can emit a fixit and carry on pretending that BaseExpr was + // actually a CallExpr. + SourceLocation ParenInsertionLoc = + PP.getLocForEndOfToken(BaseExpr.get()->getLocEnd()); + Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) + << (Overloads.size() > 1) << 1 << BaseExpr.get()->getSourceRange() + << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); + // FIXME: Try this before emitting the fixit, and suppress diagnostics + // while doing so. + ExprResult NewBase = + ActOnCallExpr(0, BaseExpr.take(), ParenInsertionLoc, + MultiExprArg(*this, 0, 0), + ParenInsertionLoc.getFileLocWithOffset(1)); + if (NewBase.isInvalid()) + return ExprError(); + BaseExpr = NewBase; + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); + } + } + + Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union) + << BaseType << BaseExpr.get()->getSourceRange(); + + return ExprError(); +} + +/// The main callback when the parser finds something like +/// expression . [nested-name-specifier] identifier +/// expression -> [nested-name-specifier] identifier +/// where 'identifier' encompasses a fairly broad spectrum of +/// possibilities, including destructor and operator references. +/// +/// \param OpKind either tok::arrow or tok::period +/// \param HasTrailingLParen whether the next token is '(', which +/// is used to diagnose mis-uses of special members that can +/// only be called +/// \param ObjCImpDecl the current ObjC @implementation decl; +/// this is an ugly hack around the fact that ObjC @implementations +/// aren't properly put in the context chain +ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &Id, + Decl *ObjCImpDecl, + bool HasTrailingLParen) { + if (SS.isSet() && SS.isInvalid()) + return ExprError(); + + // Warn about the explicit constructor calls Microsoft extension. + if (getLangOptions().Microsoft && + Id.getKind() == UnqualifiedId::IK_ConstructorName) + Diag(Id.getSourceRange().getBegin(), + diag::ext_ms_explicit_constructor_call); + + TemplateArgumentListInfo TemplateArgsBuffer; + + // Decompose the name into its component parts. + DeclarationNameInfo NameInfo; + const TemplateArgumentListInfo *TemplateArgs; + DecomposeUnqualifiedId(*this, Id, TemplateArgsBuffer, + NameInfo, TemplateArgs); + + DeclarationName Name = NameInfo.getName(); + bool IsArrow = (OpKind == tok::arrow); + + NamedDecl *FirstQualifierInScope + = (!SS.isSet() ? 0 : FindFirstQualifierInScope(S, + static_cast<NestedNameSpecifier*>(SS.getScopeRep()))); + + // This is a postfix expression, so get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.take(); + + if (Base->getType()->isDependentType() || Name.isDependentName() || + isDependentScopeSpecifier(SS)) { + Result = ActOnDependentMemberExpr(Base, Base->getType(), + IsArrow, OpLoc, + SS, FirstQualifierInScope, + NameInfo, TemplateArgs); + } else { + LookupResult R(*this, NameInfo, LookupMemberName); + ExprResult BaseResult = Owned(Base); + Result = LookupMemberExpr(R, BaseResult, IsArrow, OpLoc, + SS, ObjCImpDecl, TemplateArgs != 0); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + + if (Result.isInvalid()) { + Owned(Base); + return ExprError(); + } + + if (Result.get()) { + // The only way a reference to a destructor can be used is to + // immediately call it, which falls into this case. If the + // next token is not a '(', produce a diagnostic and build the + // call now. + if (!HasTrailingLParen && + Id.getKind() == UnqualifiedId::IK_DestructorName) + return DiagnoseDtorReference(NameInfo.getLoc(), Result.get()); + + return move(Result); + } + + Result = BuildMemberReferenceExpr(Base, Base->getType(), + OpLoc, IsArrow, SS, FirstQualifierInScope, + R, TemplateArgs); + } + + return move(Result); +} + +ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, + FunctionDecl *FD, + ParmVarDecl *Param) { + if (Param->hasUnparsedDefaultArg()) { + Diag(CallLoc, + diag::err_use_of_default_argument_to_function_declared_later) << + FD << cast<CXXRecordDecl>(FD->getDeclContext())->getDeclName(); + Diag(UnparsedDefaultArgLocs[Param], + diag::note_default_argument_declared_here); + return ExprError(); + } + + if (Param->hasUninstantiatedDefaultArg()) { + Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); + + // Instantiate the expression. + MultiLevelTemplateArgumentList ArgList + = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true); + + std::pair<const TemplateArgument *, unsigned> Innermost + = ArgList.getInnermost(); + InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first, + Innermost.second); + + ExprResult Result; + { + // C++ [dcl.fct.default]p5: + // The names in the [default argument] expression are bound, and + // the semantic constraints are checked, at the point where the + // default argument expression appears. + ContextRAII SavedContext(*this, FD); + Result = SubstExpr(UninstExpr, ArgList); + } + if (Result.isInvalid()) + return ExprError(); + + // Check the expression as an initializer for the parameter. + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, Param); + InitializationKind Kind + = InitializationKind::CreateCopy(Param->getLocation(), + /*FIXME:EqualLoc*/UninstExpr->getSourceRange().getBegin()); + Expr *ResultE = Result.takeAs<Expr>(); + + InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1); + Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &ResultE, 1)); + if (Result.isInvalid()) + return ExprError(); + + // Build the default argument expression. + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, + Result.takeAs<Expr>())); + } + + // If the default expression creates temporaries, we need to + // push them to the current stack of expression temporaries so they'll + // be properly destroyed. + // FIXME: We should really be rebuilding the default argument with new + // bound temporaries; see the comment in PR5810. + for (unsigned i = 0, e = Param->getNumDefaultArgTemporaries(); i != e; ++i) { + CXXTemporary *Temporary = Param->getDefaultArgTemporary(i); + MarkDeclarationReferenced(Param->getDefaultArg()->getLocStart(), + const_cast<CXXDestructorDecl*>(Temporary->getDestructor())); + ExprTemporaries.push_back(Temporary); + } + + // We already type-checked the argument, so we know it works. + // Just mark all of the declarations in this potentially-evaluated expression + // as being "referenced". + MarkDeclarationsReferencedInExpr(Param->getDefaultArg()); + return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param)); +} + +/// ConvertArgumentsForCall - Converts the arguments specified in +/// Args/NumArgs to the parameter types of the function FDecl with +/// function prototype Proto. Call is the call expression itself, and +/// Fn is the function expression. For a C++ member function, this +/// routine does not attempt to convert the object argument. Returns +/// true if the call is ill-formed. +bool +Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc) { + // Bail out early if calling a builtin with custom typechecking. + // We don't need to do this in the + if (FDecl) + if (unsigned ID = FDecl->getBuiltinID()) + if (Context.BuiltinInfo.hasCustomTypechecking(ID)) + return false; + + // C99 6.5.2.2p7 - the arguments are implicitly converted, as if by + // assignment, to the types of the corresponding parameter, ... + unsigned NumArgsInProto = Proto->getNumArgs(); + bool Invalid = false; + + // If too few arguments are available (and we don't have default + // arguments for the remaining parameters), don't make the call. + if (NumArgs < NumArgsInProto) { + if (!FDecl || NumArgs < FDecl->getMinRequiredArguments()) + return Diag(RParenLoc, diag::err_typecheck_call_too_few_args) + << Fn->getType()->isBlockPointerType() + << NumArgsInProto << NumArgs << Fn->getSourceRange(); + Call->setNumArgs(Context, NumArgsInProto); + } + + // If too many are passed and not variadic, error on the extras and drop + // them. + if (NumArgs > NumArgsInProto) { + if (!Proto->isVariadic()) { + Diag(Args[NumArgsInProto]->getLocStart(), + diag::err_typecheck_call_too_many_args) + << Fn->getType()->isBlockPointerType() + << NumArgsInProto << NumArgs << Fn->getSourceRange() + << SourceRange(Args[NumArgsInProto]->getLocStart(), + Args[NumArgs-1]->getLocEnd()); + + // Emit the location of the prototype. + if (FDecl && !FDecl->getBuiltinID()) + Diag(FDecl->getLocStart(), + diag::note_typecheck_call_too_many_args) + << FDecl; + + // This deletes the extra arguments. + Call->setNumArgs(Context, NumArgsInProto); + return true; + } + } + llvm::SmallVector<Expr *, 8> AllArgs; + VariadicCallType CallType = + Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; + if (Fn->getType()->isBlockPointerType()) + CallType = VariadicBlock; // Block + else if (isa<MemberExpr>(Fn)) + CallType = VariadicMethod; + Invalid = GatherArgumentsForCall(Call->getSourceRange().getBegin(), FDecl, + Proto, 0, Args, NumArgs, AllArgs, CallType); + if (Invalid) + return true; + unsigned TotalNumArgs = AllArgs.size(); + for (unsigned i = 0; i < TotalNumArgs; ++i) + Call->setArg(i, AllArgs[i]); + + return false; +} + +bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, + FunctionDecl *FDecl, + const FunctionProtoType *Proto, + unsigned FirstProtoArg, + Expr **Args, unsigned NumArgs, + llvm::SmallVector<Expr *, 8> &AllArgs, + VariadicCallType CallType) { + unsigned NumArgsInProto = Proto->getNumArgs(); + unsigned NumArgsToCheck = NumArgs; + bool Invalid = false; + if (NumArgs != NumArgsInProto) + // Use default arguments for missing arguments + NumArgsToCheck = NumArgsInProto; + unsigned ArgIx = 0; + // Continue to check argument types (even if we have too few/many args). + for (unsigned i = FirstProtoArg; i != NumArgsToCheck; i++) { + QualType ProtoArgType = Proto->getArgType(i); + + Expr *Arg; + if (ArgIx < NumArgs) { + Arg = Args[ArgIx++]; + + if (RequireCompleteType(Arg->getSourceRange().getBegin(), + ProtoArgType, + PDiag(diag::err_call_incomplete_argument) + << Arg->getSourceRange())) + return true; + + // Pass the argument + ParmVarDecl *Param = 0; + if (FDecl && i < FDecl->getNumParams()) + Param = FDecl->getParamDecl(i); + + InitializedEntity Entity = + Param? InitializedEntity::InitializeParameter(Context, Param) + : InitializedEntity::InitializeParameter(Context, ProtoArgType); + ExprResult ArgE = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(Arg)); + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs<Expr>(); + } else { + ParmVarDecl *Param = FDecl->getParamDecl(i); + + ExprResult ArgExpr = + BuildCXXDefaultArgExpr(CallLoc, FDecl, Param); + if (ArgExpr.isInvalid()) + return true; + + Arg = ArgExpr.takeAs<Expr>(); + } + AllArgs.push_back(Arg); + } + + // If this is a variadic call, handle args passed through "...". + if (CallType != VariadicDoesNotApply) { + + // Assume that extern "C" functions with variadic arguments that + // return __unknown_anytype aren't *really* variadic. + if (Proto->getResultType() == Context.UnknownAnyTy && + FDecl && FDecl->isExternC()) { + for (unsigned i = ArgIx; i != NumArgs; ++i) { + ExprResult arg; + if (isa<ExplicitCastExpr>(Args[i]->IgnoreParens())) + arg = DefaultFunctionArrayLvalueConversion(Args[i]); + else + arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl); + Invalid |= arg.isInvalid(); + AllArgs.push_back(arg.take()); + } + + // Otherwise do argument promotion, (C99 6.5.2.2p7). + } else { + for (unsigned i = ArgIx; i != NumArgs; ++i) { + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], CallType, FDecl); + Invalid |= Arg.isInvalid(); + AllArgs.push_back(Arg.take()); + } + } + } + return Invalid; +} + +/// Given a function expression of unknown-any type, try to rebuild it +/// to have a function type. +static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn); + +/// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. +/// This provides the location of the left/right parens and a list of comma +/// locations. +ExprResult +Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, + MultiExprArg args, SourceLocation RParenLoc, + Expr *ExecConfig) { + unsigned NumArgs = args.size(); + + // Since this might be a postfix expression, get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn); + if (Result.isInvalid()) return ExprError(); + Fn = Result.take(); + + Expr **Args = args.release(); + + if (getLangOptions().CPlusPlus) { + // If this is a pseudo-destructor expression, build the call immediately. + if (isa<CXXPseudoDestructorExpr>(Fn)) { + if (NumArgs > 0) { + // Pseudo-destructor calls should not have any arguments. + Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args) + << FixItHint::CreateRemoval( + SourceRange(Args[0]->getLocStart(), + Args[NumArgs-1]->getLocEnd())); + + NumArgs = 0; + } + + return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy, + VK_RValue, RParenLoc)); + } + + // Determine whether this is a dependent call inside a C++ template, + // in which case we won't do any semantic analysis now. + // FIXME: Will need to cache the results of name lookup (including ADL) in + // Fn. + bool Dependent = false; + if (Fn->isTypeDependent()) + Dependent = true; + else if (Expr::hasAnyTypeDependentArguments(Args, NumArgs)) + Dependent = true; + + if (Dependent) { + if (ExecConfig) { + return Owned(new (Context) CUDAKernelCallExpr( + Context, Fn, cast<CallExpr>(ExecConfig), Args, NumArgs, + Context.DependentTy, VK_RValue, RParenLoc)); + } else { + return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs, + Context.DependentTy, VK_RValue, + RParenLoc)); + } + } + + // Determine whether this is a call to an object (C++ [over.call.object]). + if (Fn->getType()->isRecordType()) + return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, + RParenLoc)); + + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult result = rebuildUnknownAnyFunction(*this, Fn); + if (result.isInvalid()) return ExprError(); + Fn = result.take(); + } + + if (Fn->getType() == Context.BoundMemberTy) { + return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, + RParenLoc); + } + } + + // Check for overloaded calls. This can happen even in C due to extensions. + if (Fn->getType() == Context.OverloadTy) { + OverloadExpr::FindResult find = OverloadExpr::find(Fn); + + // We aren't supposed to apply this logic if there's an '&' involved. + if (!find.IsAddressOfOperand) { + OverloadExpr *ovl = find.Expression; + if (isa<UnresolvedLookupExpr>(ovl)) { + UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl); + return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); + } else { + return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, + RParenLoc); + } + } + } + + // If we're directly calling a function, get the appropriate declaration. + + Expr *NakedFn = Fn->IgnoreParens(); + + NamedDecl *NDecl = 0; + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn)) + if (UnOp->getOpcode() == UO_AddrOf) + NakedFn = UnOp->getSubExpr()->IgnoreParens(); + + if (isa<DeclRefExpr>(NakedFn)) + NDecl = cast<DeclRefExpr>(NakedFn)->getDecl(); + else if (isa<MemberExpr>(NakedFn)) + NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); + + return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc, + ExecConfig); +} + +ExprResult +Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, + MultiExprArg execConfig, SourceLocation GGGLoc) { + FunctionDecl *ConfigDecl = Context.getcudaConfigureCallDecl(); + if (!ConfigDecl) + return ExprError(Diag(LLLLoc, diag::err_undeclared_var_use) + << "cudaConfigureCall"); + QualType ConfigQTy = ConfigDecl->getType(); + + DeclRefExpr *ConfigDR = new (Context) DeclRefExpr( + ConfigDecl, ConfigQTy, VK_LValue, LLLLoc); + + return ActOnCallExpr(S, ConfigDR, LLLLoc, execConfig, GGGLoc, 0); +} + +/// ActOnAsTypeExpr - create a new asType (bitcast) from the arguments. +/// +/// __builtin_astype( value, dst type ) +/// +ExprResult Sema::ActOnAsTypeExpr(Expr *expr, ParsedType destty, + SourceLocation BuiltinLoc, + SourceLocation RParenLoc) { + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType DstTy = GetTypeFromParser(destty); + QualType SrcTy = expr->getType(); + if (Context.getTypeSize(DstTy) != Context.getTypeSize(SrcTy)) + return ExprError(Diag(BuiltinLoc, + diag::err_invalid_astype_of_different_size) + << DstTy + << SrcTy + << expr->getSourceRange()); + return Owned(new (Context) AsTypeExpr(expr, DstTy, VK, OK, BuiltinLoc, RParenLoc)); +} + +/// BuildResolvedCallExpr - Build a call to a resolved expression, +/// i.e. an expression not of \p OverloadTy. The expression should +/// unary-convert to an expression of function-pointer or +/// block-pointer type. +/// +/// \param NDecl the declaration being called, if available +ExprResult +Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + Expr *Config) { + FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl); + + // Promote the function operand. + ExprResult Result = UsualUnaryConversions(Fn); + if (Result.isInvalid()) + return ExprError(); + Fn = Result.take(); + + // Make the call expr early, before semantic checks. This guarantees cleanup + // of arguments and function on error. + CallExpr *TheCall; + if (Config) { + TheCall = new (Context) CUDAKernelCallExpr(Context, Fn, + cast<CallExpr>(Config), + Args, NumArgs, + Context.BoolTy, + VK_RValue, + RParenLoc); + } else { + TheCall = new (Context) CallExpr(Context, Fn, + Args, NumArgs, + Context.BoolTy, + VK_RValue, + RParenLoc); + } + + unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); + + // Bail out early if calling a builtin with custom typechecking. + if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) + return CheckBuiltinFunctionCall(BuiltinID, TheCall); + + retry: + const FunctionType *FuncT; + if (const PointerType *PT = Fn->getType()->getAs<PointerType>()) { + // C99 6.5.2.2p1 - "The expression that denotes the called function shall + // have type pointer to function". + FuncT = PT->getPointeeType()->getAs<FunctionType>(); + if (FuncT == 0) + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } else if (const BlockPointerType *BPT = + Fn->getType()->getAs<BlockPointerType>()) { + FuncT = BPT->getPointeeType()->castAs<FunctionType>(); + } else { + // Handle calls to expressions of unknown-any type. + if (Fn->getType() == Context.UnknownAnyTy) { + ExprResult rewrite = rebuildUnknownAnyFunction(*this, Fn); + if (rewrite.isInvalid()) return ExprError(); + Fn = rewrite.take(); + TheCall->setCallee(Fn); + goto retry; + } + + return ExprError(Diag(LParenLoc, diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); + } + + if (getLangOptions().CUDA) { + if (Config) { + // CUDA: Kernel calls must be to global functions + if (FDecl && !FDecl->hasAttr<CUDAGlobalAttr>()) + return ExprError(Diag(LParenLoc,diag::err_kern_call_not_global_function) + << FDecl->getName() << Fn->getSourceRange()); + + // CUDA: Kernel function must have 'void' return type + if (!FuncT->getResultType()->isVoidType()) + return ExprError(Diag(LParenLoc, diag::err_kern_type_not_void_return) + << Fn->getType() << Fn->getSourceRange()); + } + } + + // Check for a valid return type + if (CheckCallReturnType(FuncT->getResultType(), + Fn->getSourceRange().getBegin(), TheCall, + FDecl)) + return ExprError(); + + // We know the result type of the call, set it. + TheCall->setType(FuncT->getCallResultType(Context)); + TheCall->setValueKind(Expr::getValueKindForType(FuncT->getResultType())); + + if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) { + if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, NumArgs, + RParenLoc)) + return ExprError(); + } else { + assert(isa<FunctionNoProtoType>(FuncT) && "Unknown FunctionType!"); + + if (FDecl) { + // Check if we have too few/too many template arguments, based + // on our knowledge of the function definition. + const FunctionDecl *Def = 0; + if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) { + const FunctionProtoType *Proto + = Def->getType()->getAs<FunctionProtoType>(); + if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) + Diag(RParenLoc, diag::warn_call_wrong_number_of_arguments) + << (NumArgs > Def->param_size()) << FDecl << Fn->getSourceRange(); + } + + // If the function we're calling isn't a function prototype, but we have + // a function prototype from a prior declaratiom, use that prototype. + if (!FDecl->hasPrototype()) + Proto = FDecl->getType()->getAs<FunctionProtoType>(); + } + + // Promote the arguments (C99 6.5.2.2p6). + for (unsigned i = 0; i != NumArgs; i++) { + Expr *Arg = Args[i]; + + if (Proto && i < Proto->getNumArgs()) { + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, + Proto->getArgType(i)); + ExprResult ArgE = PerformCopyInitialization(Entity, + SourceLocation(), + Owned(Arg)); + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs<Expr>(); + + } else { + ExprResult ArgE = DefaultArgumentPromotion(Arg); + + if (ArgE.isInvalid()) + return true; + + Arg = ArgE.takeAs<Expr>(); + } + + if (RequireCompleteType(Arg->getSourceRange().getBegin(), + Arg->getType(), + PDiag(diag::err_call_incomplete_argument) + << Arg->getSourceRange())) + return ExprError(); + + TheCall->setArg(i, Arg); + } + } + + if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(FDecl)) + if (!Method->isStatic()) + return ExprError(Diag(LParenLoc, diag::err_member_call_without_object) + << Fn->getSourceRange()); + + // Check for sentinels + if (NDecl) + DiagnoseSentinelCalls(NDecl, LParenLoc, Args, NumArgs); + + // Do special checking on direct calls to functions. + if (FDecl) { + if (CheckFunctionCall(FDecl, TheCall)) + return ExprError(); + + if (BuiltinID) + return CheckBuiltinFunctionCall(BuiltinID, TheCall); + } else if (NDecl) { + if (CheckBlockCall(NDecl, TheCall)) + return ExprError(); + } + + return MaybeBindToTemporary(TheCall); +} + +ExprResult +Sema::ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty, + SourceLocation RParenLoc, Expr *InitExpr) { + assert((Ty != 0) && "ActOnCompoundLiteral(): missing type"); + // FIXME: put back this assert when initializers are worked out. + //assert((InitExpr != 0) && "ActOnCompoundLiteral(): missing expression"); + + TypeSourceInfo *TInfo; + QualType literalType = GetTypeFromParser(Ty, &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(literalType); + + return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, InitExpr); +} + +ExprResult +Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, + SourceLocation RParenLoc, Expr *literalExpr) { + QualType literalType = TInfo->getType(); + + if (literalType->isArrayType()) { + if (RequireCompleteType(LParenLoc, Context.getBaseElementType(literalType), + PDiag(diag::err_illegal_decl_array_incomplete_type) + << SourceRange(LParenLoc, + literalExpr->getSourceRange().getEnd()))) + return ExprError(); + if (literalType->isVariableArrayType()) + return ExprError(Diag(LParenLoc, diag::err_variable_object_no_init) + << SourceRange(LParenLoc, literalExpr->getSourceRange().getEnd())); + } else if (!literalType->isDependentType() && + RequireCompleteType(LParenLoc, literalType, + PDiag(diag::err_typecheck_decl_incomplete_type) + << SourceRange(LParenLoc, + literalExpr->getSourceRange().getEnd()))) + return ExprError(); + + InitializedEntity Entity + = InitializedEntity::InitializeTemporary(literalType); + InitializationKind Kind + = InitializationKind::CreateCast(SourceRange(LParenLoc, RParenLoc), + /*IsCStyleCast=*/true); + InitializationSequence InitSeq(*this, Entity, Kind, &literalExpr, 1); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, &literalExpr, 1), + &literalType); + if (Result.isInvalid()) + return ExprError(); + literalExpr = Result.get(); + + bool isFileScope = getCurFunctionOrMethodDecl() == 0; + if (isFileScope) { // 6.5.2.5p3 + if (CheckForConstantInitializer(literalExpr, literalType)) + return ExprError(); + } + + // In C, compound literals are l-values for some reason. + ExprValueKind VK = getLangOptions().CPlusPlus ? VK_RValue : VK_LValue; + + return Owned(new (Context) CompoundLiteralExpr(LParenLoc, TInfo, literalType, + VK, literalExpr, isFileScope)); +} + +ExprResult +Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist, + SourceLocation RBraceLoc) { + unsigned NumInit = initlist.size(); + Expr **InitList = initlist.release(); + + // Semantic analysis for initializers is done by ActOnDeclarator() and + // CheckInitializer() - it requires knowledge of the object being intialized. + + InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitList, + NumInit, RBraceLoc); + E->setType(Context.VoidTy); // FIXME: just a place holder for now. + return Owned(E); +} + +/// Prepares for a scalar cast, performing all the necessary stages +/// except the final cast and returning the kind required. +static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { + // Both Src and Dest are scalar types, i.e. arithmetic or pointer. + // Also, callers should have filtered out the invalid cases with + // pointers. Everything else should be possible. + + QualType SrcTy = Src.get()->getType(); + if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy)) + return CK_NoOp; + + switch (SrcTy->getScalarTypeKind()) { + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + + case Type::STK_Pointer: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_Pointer: + return DestTy->isObjCObjectPointerType() ? + CK_AnyPointerToObjCPointerCast : + CK_BitCast; + case Type::STK_Bool: + return CK_PointerToBoolean; + case Type::STK_Integral: + return CK_PointerToIntegral; + case Type::STK_Floating: + case Type::STK_FloatingComplex: + case Type::STK_IntegralComplex: + case Type::STK_MemberPointer: + llvm_unreachable("illegal cast from pointer"); + } + break; + + case Type::STK_Bool: // casting from bool is like casting from an integer + case Type::STK_Integral: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_Pointer: + if (Src.get()->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull)) + return CK_NullToPointer; + return CK_IntegralToPointer; + case Type::STK_Bool: + return CK_IntegralToBoolean; + case Type::STK_Integral: + return CK_IntegralCast; + case Type::STK_Floating: + return CK_IntegralToFloating; + case Type::STK_IntegralComplex: + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_IntegralCast); + return CK_IntegralRealToComplex; + case Type::STK_FloatingComplex: + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_IntegralToFloating); + return CK_FloatingRealToComplex; + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + break; + + case Type::STK_Floating: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_Floating: + return CK_FloatingCast; + case Type::STK_Bool: + return CK_FloatingToBoolean; + case Type::STK_Integral: + return CK_FloatingToIntegral; + case Type::STK_FloatingComplex: + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_FloatingCast); + return CK_FloatingRealToComplex; + case Type::STK_IntegralComplex: + Src = S.ImpCastExprToType(Src.take(), DestTy->getAs<ComplexType>()->getElementType(), + CK_FloatingToIntegral); + return CK_IntegralRealToComplex; + case Type::STK_Pointer: + llvm_unreachable("valid float->pointer cast?"); + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + break; + + case Type::STK_FloatingComplex: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_FloatingComplex: + return CK_FloatingComplexCast; + case Type::STK_IntegralComplex: + return CK_FloatingComplexToIntegralComplex; + case Type::STK_Floating: { + QualType ET = SrcTy->getAs<ComplexType>()->getElementType(); + if (S.Context.hasSameType(ET, DestTy)) + return CK_FloatingComplexToReal; + Src = S.ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal); + return CK_FloatingCast; + } + case Type::STK_Bool: + return CK_FloatingComplexToBoolean; + case Type::STK_Integral: + Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs<ComplexType>()->getElementType(), + CK_FloatingComplexToReal); + return CK_FloatingToIntegral; + case Type::STK_Pointer: + llvm_unreachable("valid complex float->pointer cast?"); + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + break; + + case Type::STK_IntegralComplex: + switch (DestTy->getScalarTypeKind()) { + case Type::STK_FloatingComplex: + return CK_IntegralComplexToFloatingComplex; + case Type::STK_IntegralComplex: + return CK_IntegralComplexCast; + case Type::STK_Integral: { + QualType ET = SrcTy->getAs<ComplexType>()->getElementType(); + if (S.Context.hasSameType(ET, DestTy)) + return CK_IntegralComplexToReal; + Src = S.ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal); + return CK_IntegralCast; + } + case Type::STK_Bool: + return CK_IntegralComplexToBoolean; + case Type::STK_Floating: + Src = S.ImpCastExprToType(Src.take(), SrcTy->getAs<ComplexType>()->getElementType(), + CK_IntegralComplexToReal); + return CK_IntegralToFloating; + case Type::STK_Pointer: + llvm_unreachable("valid complex int->pointer cast?"); + case Type::STK_MemberPointer: + llvm_unreachable("member pointer type in C"); + } + break; + } + + llvm_unreachable("Unhandled scalar cast"); + return CK_BitCast; +} + +/// CheckCastTypes - Check type constraints for casting between types. +ExprResult Sema::CheckCastTypes(SourceRange TyR, QualType castType, + Expr *castExpr, CastKind& Kind, ExprValueKind &VK, + CXXCastPath &BasePath, bool FunctionalStyle) { + if (castExpr->getType() == Context.UnknownAnyTy) + return checkUnknownAnyCast(TyR, castType, castExpr, Kind, VK, BasePath); + + if (getLangOptions().CPlusPlus) + return CXXCheckCStyleCast(SourceRange(TyR.getBegin(), + castExpr->getLocEnd()), + castType, VK, castExpr, Kind, BasePath, + FunctionalStyle); + + assert(!castExpr->getType()->isPlaceholderType()); + + // We only support r-value casts in C. + VK = VK_RValue; + + // C99 6.5.4p2: the cast type needs to be void or scalar and the expression + // type needs to be scalar. + if (castType->isVoidType()) { + // We don't necessarily do lvalue-to-rvalue conversions on this. + ExprResult castExprRes = IgnoredValueConversions(castExpr); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); + + // Cast to void allows any expr type. + Kind = CK_ToVoid; + return Owned(castExpr); + } + + ExprResult castExprRes = DefaultFunctionArrayLvalueConversion(castExpr); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); + + if (RequireCompleteType(TyR.getBegin(), castType, + diag::err_typecheck_cast_to_incomplete)) + return ExprError(); + + if (!castType->isScalarType() && !castType->isVectorType()) { + if (Context.hasSameUnqualifiedType(castType, castExpr->getType()) && + (castType->isStructureType() || castType->isUnionType())) { + // GCC struct/union extension: allow cast to self. + // FIXME: Check that the cast destination type is complete. + Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar) + << castType << castExpr->getSourceRange(); + Kind = CK_NoOp; + return Owned(castExpr); + } + + if (castType->isUnionType()) { + // GCC cast to union extension + RecordDecl *RD = castType->getAs<RecordType>()->getDecl(); + RecordDecl::field_iterator Field, FieldEnd; + for (Field = RD->field_begin(), FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Context.hasSameUnqualifiedType(Field->getType(), + castExpr->getType()) && + !Field->isUnnamedBitfield()) { + Diag(TyR.getBegin(), diag::ext_typecheck_cast_to_union) + << castExpr->getSourceRange(); + break; + } + } + if (Field == FieldEnd) { + Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type) + << castExpr->getType() << castExpr->getSourceRange(); + return ExprError(); + } + Kind = CK_ToUnion; + return Owned(castExpr); + } + + // Reject any other conversions to non-scalar types. + Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) + << castType << castExpr->getSourceRange(); + return ExprError(); + } + + // The type we're casting to is known to be a scalar or vector. + + // Require the operand to be a scalar or vector. + if (!castExpr->getType()->isScalarType() && + !castExpr->getType()->isVectorType()) { + Diag(castExpr->getLocStart(), + diag::err_typecheck_expect_scalar_operand) + << castExpr->getType() << castExpr->getSourceRange(); + return ExprError(); + } + + if (castType->isExtVectorType()) + return CheckExtVectorCast(TyR, castType, castExpr, Kind); + + if (castType->isVectorType()) { + if (castType->getAs<VectorType>()->getVectorKind() == + VectorType::AltiVecVector && + (castExpr->getType()->isIntegerType() || + castExpr->getType()->isFloatingType())) { + Kind = CK_VectorSplat; + return Owned(castExpr); + } else if (CheckVectorCast(TyR, castType, castExpr->getType(), Kind)) { + return ExprError(); + } else + return Owned(castExpr); + } + if (castExpr->getType()->isVectorType()) { + if (CheckVectorCast(TyR, castExpr->getType(), castType, Kind)) + return ExprError(); + else + return Owned(castExpr); + } + + // The source and target types are both scalars, i.e. + // - arithmetic types (fundamental, enum, and complex) + // - all kinds of pointers + // Note that member pointers were filtered out with C++, above. + + if (isa<ObjCSelectorExpr>(castExpr)) { + Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); + return ExprError(); + } + + // If either type is a pointer, the other type has to be either an + // integer or a pointer. + if (!castType->isArithmeticType()) { + QualType castExprType = castExpr->getType(); + if (!castExprType->isIntegralType(Context) && + castExprType->isArithmeticType()) { + Diag(castExpr->getLocStart(), + diag::err_cast_pointer_from_non_pointer_int) + << castExprType << castExpr->getSourceRange(); + return ExprError(); + } + } else if (!castExpr->getType()->isArithmeticType()) { + if (!castType->isIntegralType(Context) && castType->isArithmeticType()) { + Diag(castExpr->getLocStart(), diag::err_cast_pointer_to_non_pointer_int) + << castType << castExpr->getSourceRange(); + return ExprError(); + } + } + + castExprRes = Owned(castExpr); + Kind = PrepareScalarCast(*this, castExprRes, castType); + if (castExprRes.isInvalid()) + return ExprError(); + castExpr = castExprRes.take(); + + if (Kind == CK_BitCast) + CheckCastAlign(castExpr, castType, TyR); + + return Owned(castExpr); +} + +bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, + CastKind &Kind) { + assert(VectorTy->isVectorType() && "Not a vector type!"); + + if (Ty->isVectorType() || Ty->isIntegerType()) { + if (Context.getTypeSize(VectorTy) != Context.getTypeSize(Ty)) + return Diag(R.getBegin(), + Ty->isVectorType() ? + diag::err_invalid_conversion_between_vectors : + diag::err_invalid_conversion_between_vector_and_integer) + << VectorTy << Ty << R; + } else + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_vector_and_scalar) + << VectorTy << Ty << R; + + Kind = CK_BitCast; + return false; +} + +ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, + Expr *CastExpr, CastKind &Kind) { + assert(DestTy->isExtVectorType() && "Not an extended vector type!"); + + QualType SrcTy = CastExpr->getType(); + + // If SrcTy is a VectorType, the total size must match to explicitly cast to + // an ExtVectorType. + if (SrcTy->isVectorType()) { + if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) { + Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) + << DestTy << SrcTy << R; + return ExprError(); + } + Kind = CK_BitCast; + return Owned(CastExpr); + } + + // All non-pointer scalars can be cast to ExtVector type. The appropriate + // conversion will take place first from scalar to elt type, and then + // splat from elt type to vector. + if (SrcTy->isPointerType()) + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_vector_and_scalar) + << DestTy << SrcTy << R; + + QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType(); + ExprResult CastExprRes = Owned(CastExpr); + CastKind CK = PrepareScalarCast(*this, CastExprRes, DestElemTy); + if (CastExprRes.isInvalid()) + return ExprError(); + CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take(); + + Kind = CK_VectorSplat; + return Owned(CastExpr); +} + +ExprResult +Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty, + SourceLocation RParenLoc, Expr *castExpr) { + assert((Ty != 0) && (castExpr != 0) && + "ActOnCastExpr(): missing type or expr"); + + TypeSourceInfo *castTInfo; + QualType castType = GetTypeFromParser(Ty, &castTInfo); + if (!castTInfo) + castTInfo = Context.getTrivialTypeSourceInfo(castType); + + // If the Expr being casted is a ParenListExpr, handle it specially. + if (isa<ParenListExpr>(castExpr)) + return ActOnCastOfParenListExpr(S, LParenLoc, RParenLoc, castExpr, + castTInfo); + + return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, castExpr); +} + +ExprResult +Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, + SourceLocation RParenLoc, Expr *castExpr) { + CastKind Kind = CK_Invalid; + ExprValueKind VK = VK_RValue; + CXXCastPath BasePath; + ExprResult CastResult = + CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr, + Kind, VK, BasePath); + if (CastResult.isInvalid()) + return ExprError(); + castExpr = CastResult.take(); + + return Owned(CStyleCastExpr::Create(Context, + Ty->getType().getNonLValueExprType(Context), + VK, Kind, castExpr, &BasePath, Ty, + LParenLoc, RParenLoc)); +} + +/// This is not an AltiVec-style cast, so turn the ParenListExpr into a sequence +/// of comma binary operators. +ExprResult +Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *expr) { + ParenListExpr *E = dyn_cast<ParenListExpr>(expr); + if (!E) + return Owned(expr); + + ExprResult Result(E->getExpr(0)); + + for (unsigned i = 1, e = E->getNumExprs(); i != e && !Result.isInvalid(); ++i) + Result = ActOnBinOp(S, E->getExprLoc(), tok::comma, Result.get(), + E->getExpr(i)); + + if (Result.isInvalid()) return ExprError(); + + return ActOnParenExpr(E->getLParenLoc(), E->getRParenLoc(), Result.get()); +} + +ExprResult +Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, + SourceLocation RParenLoc, Expr *Op, + TypeSourceInfo *TInfo) { + ParenListExpr *PE = cast<ParenListExpr>(Op); + QualType Ty = TInfo->getType(); + bool isVectorLiteral = false; + + // Check for an altivec or OpenCL literal, + // i.e. all the elements are integer constants. + if (getLangOptions().AltiVec && Ty->isVectorType()) { + if (PE->getNumExprs() == 0) { + Diag(PE->getExprLoc(), diag::err_altivec_empty_initializer); + return ExprError(); + } + if (PE->getNumExprs() == 1) { + if (!PE->getExpr(0)->getType()->isVectorType()) + isVectorLiteral = true; + } + else + isVectorLiteral = true; + } + + // If this is a vector initializer, '(' type ')' '(' init, ..., init ')' + // then handle it as such. + if (isVectorLiteral) { + llvm::SmallVector<Expr *, 8> initExprs; + // '(...)' form of vector initialization in AltiVec: the number of + // initializers must be one or must match the size of the vector. + // If a single value is specified in the initializer then it will be + // replicated to all the components of the vector + if (Ty->getAs<VectorType>()->getVectorKind() == + VectorType::AltiVecVector) { + unsigned numElems = Ty->getAs<VectorType>()->getNumElements(); + // The number of initializers must be one or must match the size of the + // vector. If a single value is specified in the initializer then it will + // be replicated to all the components of the vector + if (PE->getNumExprs() == 1) { + QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); + ExprResult Literal = Owned(PE->getExpr(0)); + Literal = ImpCastExprToType(Literal.take(), ElemTy, + PrepareScalarCast(*this, Literal, ElemTy)); + return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); + } + else if (PE->getNumExprs() < numElems) { + Diag(PE->getExprLoc(), + diag::err_incorrect_number_of_vector_initializers); + return ExprError(); + } + else + for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) + initExprs.push_back(PE->getExpr(i)); + } + else + for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) + initExprs.push_back(PE->getExpr(i)); + + // FIXME: This means that pretty-printing the final AST will produce curly + // braces instead of the original commas. + InitListExpr *E = new (Context) InitListExpr(Context, LParenLoc, + &initExprs[0], + initExprs.size(), RParenLoc); + E->setType(Ty); + return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, E); + } else { + // This is not an AltiVec-style cast, so turn the ParenListExpr into a + // sequence of BinOp comma operators. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Op); + if (Result.isInvalid()) return ExprError(); + return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Result.take()); + } +} + +ExprResult Sema::ActOnParenOrParenListExpr(SourceLocation L, + SourceLocation R, + MultiExprArg Val, + ParsedType TypeOfCast) { + unsigned nexprs = Val.size(); + Expr **exprs = reinterpret_cast<Expr**>(Val.release()); + assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list"); + Expr *expr; + if (nexprs == 1 && TypeOfCast && !TypeIsVectorType(TypeOfCast)) + expr = new (Context) ParenExpr(L, R, exprs[0]); + else + expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); + return Owned(expr); +} + +/// \brief Emit a specialized diagnostic when one expression is a null pointer +/// constant and the other is not a pointer. +bool Sema::DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, + SourceLocation QuestionLoc) { + Expr *NullExpr = LHS; + Expr *NonPointerExpr = RHS; + Expr::NullPointerConstantKind NullKind = + NullExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + + if (NullKind == Expr::NPCK_NotNull) { + NullExpr = RHS; + NonPointerExpr = LHS; + NullKind = + NullExpr->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNotNull); + } + + if (NullKind == Expr::NPCK_NotNull) + return false; + + if (NullKind == Expr::NPCK_ZeroInteger) { + // In this case, check to make sure that we got here from a "NULL" + // string in the source code. + NullExpr = NullExpr->IgnoreParenImpCasts(); + SourceLocation loc = NullExpr->getExprLoc(); + if (!findMacroSpelling(loc, "NULL")) + return false; + } + + int DiagType = (NullKind == Expr::NPCK_CXX0X_nullptr); + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null) + << NonPointerExpr->getType() << DiagType + << NonPointerExpr->getSourceRange(); + return true; +} + +/// Note that lhs is not null here, even if this is the gnu "x ?: y" extension. +/// In that case, lhs = cond. +/// C99 6.5.15 +QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, + ExprValueKind &VK, ExprObjectKind &OK, + SourceLocation QuestionLoc) { + + ExprResult lhsResult = CheckPlaceholderExpr(LHS.get()); + if (!lhsResult.isUsable()) return QualType(); + LHS = move(lhsResult); + + ExprResult rhsResult = CheckPlaceholderExpr(RHS.get()); + if (!rhsResult.isUsable()) return QualType(); + RHS = move(rhsResult); + + // C++ is sufficiently different to merit its own checker. + if (getLangOptions().CPlusPlus) + return CXXCheckConditionalOperands(Cond, LHS, RHS, VK, OK, QuestionLoc); + + VK = VK_RValue; + OK = OK_Ordinary; + + Cond = UsualUnaryConversions(Cond.take()); + if (Cond.isInvalid()) + return QualType(); + LHS = UsualUnaryConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + RHS = UsualUnaryConversions(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + + QualType CondTy = Cond.get()->getType(); + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + // first, check the condition. + if (!CondTy->isScalarType()) { // C99 6.5.15p2 + // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar. + // Throw an error if its not either. + if (getLangOptions().OpenCL) { + if (!CondTy->isVectorType()) { + Diag(Cond.get()->getLocStart(), + diag::err_typecheck_cond_expect_scalar_or_vector) + << CondTy; + return QualType(); + } + } + else { + Diag(Cond.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return QualType(); + } + } + + // Now check the two expressions. + if (LHSTy->isVectorType() || RHSTy->isVectorType()) + return CheckVectorOperands(QuestionLoc, LHS, RHS); + + // OpenCL: If the condition is a vector, and both operands are scalar, + // attempt to implicity convert them to the vector type to act like the + // built in select. + if (getLangOptions().OpenCL && CondTy->isVectorType()) { + // Both operands should be of scalar type. + if (!LHSTy->isScalarType()) { + Diag(LHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return QualType(); + } + if (!RHSTy->isScalarType()) { + Diag(RHS.get()->getLocStart(), diag::err_typecheck_cond_expect_scalar) + << CondTy; + return QualType(); + } + // Implicity convert these scalars to the type of the condition. + LHS = ImpCastExprToType(LHS.take(), CondTy, CK_IntegralCast); + RHS = ImpCastExprToType(RHS.take(), CondTy, CK_IntegralCast); + } + + // If both operands have arithmetic type, do the usual arithmetic conversions + // to find a common type: C99 6.5.15p3,5. + if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) { + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + return LHS.get()->getType(); + } + + // If both operands are the same structure or union type, the result is that + // type. + if (const RecordType *LHSRT = LHSTy->getAs<RecordType>()) { // C99 6.5.15p3 + if (const RecordType *RHSRT = RHSTy->getAs<RecordType>()) + if (LHSRT->getDecl() == RHSRT->getDecl()) + // "If both the operands have structure or union type, the result has + // that type." This implies that CV qualifiers are dropped. + return LHSTy.getUnqualifiedType(); + // FIXME: Type of conditional expression must be complete in C mode. + } + + // C99 6.5.15p5: "If both operands have void type, the result has void type." + // The following || allows only one side to be void (a GCC-ism). + if (LHSTy->isVoidType() || RHSTy->isVoidType()) { + if (!LHSTy->isVoidType()) + Diag(RHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void) + << RHS.get()->getSourceRange(); + if (!RHSTy->isVoidType()) + Diag(LHS.get()->getLocStart(), diag::ext_typecheck_cond_one_void) + << LHS.get()->getSourceRange(); + LHS = ImpCastExprToType(LHS.take(), Context.VoidTy, CK_ToVoid); + RHS = ImpCastExprToType(RHS.take(), Context.VoidTy, CK_ToVoid); + return Context.VoidTy; + } + // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has + // the type of the other operand." + if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) && + RHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + // promote the null to a pointer. + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_NullToPointer); + return LHSTy; + } + if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) && + LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_NullToPointer); + return RHSTy; + } + + // All objective-c pointer type analysis is done here. + QualType compositeType = FindCompositeObjCPointerType(LHS, RHS, + QuestionLoc); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + if (!compositeType.isNull()) + return compositeType; + + + // Handle block pointer types. + if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) { + if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { + if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) { + QualType destType = Context.getPointerType(Context.VoidTy); + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); + return destType; + } + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + // We have 2 block pointer types. + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical block pointer types are always compatible. + return LHSTy; + } + // The block pointer types aren't identical, continue checking. + QualType lhptee = LHSTy->getAs<BlockPointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<BlockPointerType>()->getPointeeType(); + + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), + rhptee.getUnqualifiedType())) { + Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + // In this situation, we assume void* type. No especially good + // reason, but this is what gcc does, and we do have to pick + // to get a consistent AST. + QualType incompatTy = Context.getPointerType(Context.VoidTy); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); + return incompatTy; + } + // The block pointer types are compatible. + LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + return LHSTy; + } + + // Check constraints for C object pointers types (C99 6.5.15p3,6). + if (LHSTy->isPointerType() && RHSTy->isPointerType()) { + // get the "pointed to" types + QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType(); + + // ignore qualifiers on void (C99 6.5.15p3, clause 6) + if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) { + // Figure out necessary qualifiers (C99 6.5.15p6) + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp); + // Promote to void*. + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); + return destType; + } + if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp); + // Promote to void*. + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); + return destType; + } + + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical pointer types are always compatible. + return LHSTy; + } + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), + rhptee.getUnqualifiedType())) { + Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + // In this situation, we assume void* type. No especially good + // reason, but this is what gcc does, and we do have to pick + // to get a consistent AST. + QualType incompatTy = Context.getPointerType(Context.VoidTy); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); + return incompatTy; + } + // The pointer types are compatible. + // C99 6.5.15p6: If both operands are pointers to compatible types *or* to + // differently qualified versions of compatible types, the result type is + // a pointer to an appropriately qualified version of the *composite* + // type. + // FIXME: Need to calculate the composite type. + // FIXME: Need to add qualifiers + LHS = ImpCastExprToType(LHS.take(), LHSTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + return LHSTy; + } + + // GCC compatibility: soften pointer/integer mismatch. Note that + // null pointers have been filtered out by this point. + if (RHSTy->isPointerType() && LHSTy->isIntegerType()) { + Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_IntegralToPointer); + return RHSTy; + } + if (LHSTy->isPointerType() && RHSTy->isIntegerType()) { + Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_IntegralToPointer); + return LHSTy; + } + + // Emit a better diagnostic if one of the expressions is a null pointer + // constant and the other is not a pointer type. In this case, the user most + // likely forgot to take the address of the other expression. + if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) + return QualType(); + + // Otherwise, the operands are not compatible. + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); +} + +/// FindCompositeObjCPointerType - Helper method to find composite type of +/// two objective-c pointer types of the two input expressions. +QualType Sema::FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc) { + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + + // Handle things like Class and struct objc_class*. Here we case the result + // to the pseudo-builtin, because that will be implicitly cast back to the + // redefinition type if an attempt is made to access its fields. + if (LHSTy->isObjCClassType() && + (Context.hasSameType(RHSTy, Context.ObjCClassRedefinitionType))) { + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + return LHSTy; + } + if (RHSTy->isObjCClassType() && + (Context.hasSameType(LHSTy, Context.ObjCClassRedefinitionType))) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); + return RHSTy; + } + // And the same for struct objc_object* / id + if (LHSTy->isObjCIdType() && + (Context.hasSameType(RHSTy, Context.ObjCIdRedefinitionType))) { + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + return LHSTy; + } + if (RHSTy->isObjCIdType() && + (Context.hasSameType(LHSTy, Context.ObjCIdRedefinitionType))) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); + return RHSTy; + } + // And the same for struct objc_selector* / SEL + if (Context.isObjCSelType(LHSTy) && + (Context.hasSameType(RHSTy, Context.ObjCSelRedefinitionType))) { + RHS = ImpCastExprToType(RHS.take(), LHSTy, CK_BitCast); + return LHSTy; + } + if (Context.isObjCSelType(RHSTy) && + (Context.hasSameType(LHSTy, Context.ObjCSelRedefinitionType))) { + LHS = ImpCastExprToType(LHS.take(), RHSTy, CK_BitCast); + return RHSTy; + } + // Check constraints for Objective-C object pointers types. + if (LHSTy->isObjCObjectPointerType() && RHSTy->isObjCObjectPointerType()) { + + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical object pointer types are always compatible. + return LHSTy; + } + const ObjCObjectPointerType *LHSOPT = LHSTy->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *RHSOPT = RHSTy->getAs<ObjCObjectPointerType>(); + QualType compositeType = LHSTy; + + // If both operands are interfaces and either operand can be + // assigned to the other, use that type as the composite + // type. This allows + // xxx ? (A*) a : (B*) b + // where B is a subclass of A. + // + // Additionally, as for assignment, if either type is 'id' + // allow silent coercion. Finally, if the types are + // incompatible then make sure to use 'id' as the composite + // type so the result is acceptable for sending messages to. + + // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. + // It could return the composite type. + if (Context.canAssignObjCInterfaces(LHSOPT, RHSOPT)) { + compositeType = RHSOPT->isObjCBuiltinType() ? RHSTy : LHSTy; + } else if (Context.canAssignObjCInterfaces(RHSOPT, LHSOPT)) { + compositeType = LHSOPT->isObjCBuiltinType() ? LHSTy : RHSTy; + } else if ((LHSTy->isObjCQualifiedIdType() || + RHSTy->isObjCQualifiedIdType()) && + Context.ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true)) { + // Need to handle "id<xx>" explicitly. + // GCC allows qualified id and any Objective-C type to devolve to + // id. Currently localizing to here until clear this should be + // part of ObjCQualifiedIdTypesAreCompatible. + compositeType = Context.getObjCIdType(); + } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { + compositeType = Context.getObjCIdType(); + } else if (!(compositeType = + Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) + ; + else { + Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + QualType incompatTy = Context.getObjCIdType(); + LHS = ImpCastExprToType(LHS.take(), incompatTy, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), incompatTy, CK_BitCast); + return incompatTy; + } + // The object pointer types are compatible. + LHS = ImpCastExprToType(LHS.take(), compositeType, CK_BitCast); + RHS = ImpCastExprToType(RHS.take(), compositeType, CK_BitCast); + return compositeType; + } + // Check Objective-C object pointer types and 'void *' + if (LHSTy->isVoidPointerType() && RHSTy->isObjCObjectPointerType()) { + QualType lhptee = LHSTy->getAs<PointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(lhptee, rhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + LHS = ImpCastExprToType(LHS.take(), destType, CK_NoOp); + // Promote to void*. + RHS = ImpCastExprToType(RHS.take(), destType, CK_BitCast); + return destType; + } + if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { + QualType lhptee = LHSTy->getAs<ObjCObjectPointerType>()->getPointeeType(); + QualType rhptee = RHSTy->getAs<PointerType>()->getPointeeType(); + QualType destPointee + = Context.getQualifiedType(rhptee, lhptee.getQualifiers()); + QualType destType = Context.getPointerType(destPointee); + // Add qualifiers if necessary. + RHS = ImpCastExprToType(RHS.take(), destType, CK_NoOp); + // Promote to void*. + LHS = ImpCastExprToType(LHS.take(), destType, CK_BitCast); + return destType; + } + return QualType(); +} + +/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps +/// ParenRange in parentheses. +static void SuggestParentheses(Sema &Self, SourceLocation Loc, + const PartialDiagnostic &PD, + const PartialDiagnostic &FirstNote, + SourceRange FirstParenRange, + const PartialDiagnostic &SecondNote, + SourceRange SecondParenRange) { + Self.Diag(Loc, PD); + + if (!FirstNote.getDiagID()) + return; + + SourceLocation EndLoc = Self.PP.getLocForEndOfToken(FirstParenRange.getEnd()); + if (!FirstParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { + // We can't display the parentheses, so just return. + return; + } + + Self.Diag(Loc, FirstNote) + << FixItHint::CreateInsertion(FirstParenRange.getBegin(), "(") + << FixItHint::CreateInsertion(EndLoc, ")"); + + if (!SecondNote.getDiagID()) + return; + + EndLoc = Self.PP.getLocForEndOfToken(SecondParenRange.getEnd()); + if (!SecondParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { + // We can't display the parentheses, so just dig the + // warning/error and return. + Self.Diag(Loc, SecondNote); + return; + } + + Self.Diag(Loc, SecondNote) + << FixItHint::CreateInsertion(SecondParenRange.getBegin(), "(") + << FixItHint::CreateInsertion(EndLoc, ")"); +} + +static bool IsArithmeticOp(BinaryOperatorKind Opc) { + return Opc >= BO_Mul && Opc <= BO_Shr; +} + +/// IsArithmeticBinaryExpr - Returns true if E is an arithmetic binary +/// expression, either using a built-in or overloaded operator, +/// and sets *OpCode to the opcode and *RHS to the right-hand side expression. +static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, + Expr **RHS) { + E = E->IgnoreParenImpCasts(); + E = E->IgnoreConversionOperator(); + E = E->IgnoreParenImpCasts(); + + // Built-in binary operator. + if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) { + if (IsArithmeticOp(OP->getOpcode())) { + *Opcode = OP->getOpcode(); + *RHS = OP->getRHS(); + return true; + } + } + + // Overloaded operator. + if (CXXOperatorCallExpr *Call = dyn_cast<CXXOperatorCallExpr>(E)) { + if (Call->getNumArgs() != 2) + return false; + + // Make sure this is really a binary operator that is safe to pass into + // BinaryOperator::getOverloadedOpcode(), e.g. it's not a subscript op. + OverloadedOperatorKind OO = Call->getOperator(); + if (OO < OO_Plus || OO > OO_Arrow) + return false; + + BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO); + if (IsArithmeticOp(OpKind)) { + *Opcode = OpKind; + *RHS = Call->getArg(1); + return true; + } + } + + return false; +} + +static bool IsLogicOp(BinaryOperatorKind Opc) { + return (Opc >= BO_LT && Opc <= BO_NE) || (Opc >= BO_LAnd && Opc <= BO_LOr); +} + +/// ExprLooksBoolean - Returns true if E looks boolean, i.e. it has boolean type +/// or is a logical expression such as (x==y) which has int type, but is +/// commonly interpreted as boolean. +static bool ExprLooksBoolean(Expr *E) { + E = E->IgnoreParenImpCasts(); + + if (E->getType()->isBooleanType()) + return true; + if (BinaryOperator *OP = dyn_cast<BinaryOperator>(E)) + return IsLogicOp(OP->getOpcode()); + if (UnaryOperator *OP = dyn_cast<UnaryOperator>(E)) + return OP->getOpcode() == UO_LNot; + + return false; +} + +/// DiagnoseConditionalPrecedence - Emit a warning when a conditional operator +/// and binary operator are mixed in a way that suggests the programmer assumed +/// the conditional operator has higher precedence, for example: +/// "int x = a + someBinaryCondition ? 1 : 2". +static void DiagnoseConditionalPrecedence(Sema &Self, + SourceLocation OpLoc, + Expr *cond, + Expr *lhs, + Expr *rhs) { + BinaryOperatorKind CondOpcode; + Expr *CondRHS; + + if (!IsArithmeticBinaryExpr(cond, &CondOpcode, &CondRHS)) + return; + if (!ExprLooksBoolean(CondRHS)) + return; + + // The condition is an arithmetic binary expression, with a right- + // hand side that looks boolean, so warn. + + PartialDiagnostic Warn = Self.PDiag(diag::warn_precedence_conditional) + << cond->getSourceRange() + << BinaryOperator::getOpcodeStr(CondOpcode); + + PartialDiagnostic FirstNote = + Self.PDiag(diag::note_precedence_conditional_silence) + << BinaryOperator::getOpcodeStr(CondOpcode); + + SourceRange FirstParenRange(cond->getLocStart(), + cond->getLocEnd()); + + PartialDiagnostic SecondNote = + Self.PDiag(diag::note_precedence_conditional_first); + + SourceRange SecondParenRange(CondRHS->getLocStart(), + rhs->getLocEnd()); + + SuggestParentheses(Self, OpLoc, Warn, FirstNote, FirstParenRange, + SecondNote, SecondParenRange); +} + +/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null +/// in the case of a the GNU conditional expr extension. +ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, + SourceLocation ColonLoc, + Expr *CondExpr, Expr *LHSExpr, + Expr *RHSExpr) { + // If this is the gnu "x ?: y" extension, analyze the types as though the LHS + // was the condition. + OpaqueValueExpr *opaqueValue = 0; + Expr *commonExpr = 0; + if (LHSExpr == 0) { + commonExpr = CondExpr; + + // We usually want to apply unary conversions *before* saving, except + // in the special case of a C++ l-value conditional. + if (!(getLangOptions().CPlusPlus + && !commonExpr->isTypeDependent() + && commonExpr->getValueKind() == RHSExpr->getValueKind() + && commonExpr->isGLValue() + && commonExpr->isOrdinaryOrBitFieldObject() + && RHSExpr->isOrdinaryOrBitFieldObject() + && Context.hasSameType(commonExpr->getType(), RHSExpr->getType()))) { + ExprResult commonRes = UsualUnaryConversions(commonExpr); + if (commonRes.isInvalid()) + return ExprError(); + commonExpr = commonRes.take(); + } + + opaqueValue = new (Context) OpaqueValueExpr(commonExpr->getExprLoc(), + commonExpr->getType(), + commonExpr->getValueKind(), + commonExpr->getObjectKind()); + LHSExpr = CondExpr = opaqueValue; + } + + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + ExprResult Cond = Owned(CondExpr), LHS = Owned(LHSExpr), RHS = Owned(RHSExpr); + QualType result = CheckConditionalOperands(Cond, LHS, RHS, + VK, OK, QuestionLoc); + if (result.isNull() || Cond.isInvalid() || LHS.isInvalid() || + RHS.isInvalid()) + return ExprError(); + + DiagnoseConditionalPrecedence(*this, QuestionLoc, Cond.get(), LHS.get(), + RHS.get()); + + if (!commonExpr) + return Owned(new (Context) ConditionalOperator(Cond.take(), QuestionLoc, + LHS.take(), ColonLoc, + RHS.take(), result, VK, OK)); + + return Owned(new (Context) + BinaryConditionalOperator(commonExpr, opaqueValue, Cond.take(), LHS.take(), + RHS.take(), QuestionLoc, ColonLoc, result, VK, OK)); +} + +// checkPointerTypesForAssignment - This is a very tricky routine (despite +// being closely modeled after the C99 spec:-). The odd characteristic of this +// routine is it effectively iqnores the qualifiers on the top level pointee. +// This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3]. +// FIXME: add a couple examples in this comment. +static Sema::AssignConvertType +checkPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) { + assert(lhsType.isCanonical() && "LHS not canonicalized!"); + assert(rhsType.isCanonical() && "RHS not canonicalized!"); + + // get the "pointed to" type (ignoring qualifiers at the top level) + const Type *lhptee, *rhptee; + Qualifiers lhq, rhq; + llvm::tie(lhptee, lhq) = cast<PointerType>(lhsType)->getPointeeType().split(); + llvm::tie(rhptee, rhq) = cast<PointerType>(rhsType)->getPointeeType().split(); + + Sema::AssignConvertType ConvTy = Sema::Compatible; + + // C99 6.5.16.1p1: This following citation is common to constraints + // 3 & 4 (below). ...and the type *pointed to* by the left has all the + // qualifiers of the type *pointed to* by the right; + Qualifiers lq; + + if (!lhq.compatiblyIncludes(rhq)) { + // Treat address-space mismatches as fatal. TODO: address subspaces + if (lhq.getAddressSpace() != rhq.getAddressSpace()) + ConvTy = Sema::IncompatiblePointerDiscardsQualifiers; + + // It's okay to add or remove GC qualifiers when converting to + // and from void*. + else if (lhq.withoutObjCGCAttr().compatiblyIncludes(rhq.withoutObjCGCAttr()) + && (lhptee->isVoidType() || rhptee->isVoidType())) + ; // keep old + + // For GCC compatibility, other qualifier mismatches are treated + // as still compatible in C. + else ConvTy = Sema::CompatiblePointerDiscardsQualifiers; + } + + // C99 6.5.16.1p1 (constraint 4): If one operand is a pointer to an object or + // incomplete type and the other is a pointer to a qualified or unqualified + // version of void... + if (lhptee->isVoidType()) { + if (rhptee->isIncompleteOrObjectType()) + return ConvTy; + + // As an extension, we allow cast to/from void* to function pointer. + assert(rhptee->isFunctionType()); + return Sema::FunctionVoidPointer; + } + + if (rhptee->isVoidType()) { + if (lhptee->isIncompleteOrObjectType()) + return ConvTy; + + // As an extension, we allow cast to/from void* to function pointer. + assert(lhptee->isFunctionType()); + return Sema::FunctionVoidPointer; + } + + // C99 6.5.16.1p1 (constraint 3): both operands are pointers to qualified or + // unqualified versions of compatible types, ... + QualType ltrans = QualType(lhptee, 0), rtrans = QualType(rhptee, 0); + if (!S.Context.typesAreCompatible(ltrans, rtrans)) { + // Check if the pointee types are compatible ignoring the sign. + // We explicitly check for char so that we catch "char" vs + // "unsigned char" on systems where "char" is unsigned. + if (lhptee->isCharType()) + ltrans = S.Context.UnsignedCharTy; + else if (lhptee->hasSignedIntegerRepresentation()) + ltrans = S.Context.getCorrespondingUnsignedType(ltrans); + + if (rhptee->isCharType()) + rtrans = S.Context.UnsignedCharTy; + else if (rhptee->hasSignedIntegerRepresentation()) + rtrans = S.Context.getCorrespondingUnsignedType(rtrans); + + if (ltrans == rtrans) { + // Types are compatible ignoring the sign. Qualifier incompatibility + // takes priority over sign incompatibility because the sign + // warning can be disabled. + if (ConvTy != Sema::Compatible) + return ConvTy; + + return Sema::IncompatiblePointerSign; + } + + // If we are a multi-level pointer, it's possible that our issue is simply + // one of qualification - e.g. char ** -> const char ** is not allowed. If + // the eventual target type is the same and the pointers have the same + // level of indirection, this must be the issue. + if (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)) { + do { + lhptee = cast<PointerType>(lhptee)->getPointeeType().getTypePtr(); + rhptee = cast<PointerType>(rhptee)->getPointeeType().getTypePtr(); + } while (isa<PointerType>(lhptee) && isa<PointerType>(rhptee)); + + if (lhptee == rhptee) + return Sema::IncompatibleNestedPointerQualifiers; + } + + // General pointer incompatibility takes priority over qualifiers. + return Sema::IncompatiblePointer; + } + return ConvTy; +} + +/// checkBlockPointerTypesForAssignment - This routine determines whether two +/// block pointer types are compatible or whether a block and normal pointer +/// are compatible. It is more restrict than comparing two function pointer +// types. +static Sema::AssignConvertType +checkBlockPointerTypesForAssignment(Sema &S, QualType lhsType, + QualType rhsType) { + assert(lhsType.isCanonical() && "LHS not canonicalized!"); + assert(rhsType.isCanonical() && "RHS not canonicalized!"); + + QualType lhptee, rhptee; + + // get the "pointed to" type (ignoring qualifiers at the top level) + lhptee = cast<BlockPointerType>(lhsType)->getPointeeType(); + rhptee = cast<BlockPointerType>(rhsType)->getPointeeType(); + + // In C++, the types have to match exactly. + if (S.getLangOptions().CPlusPlus) + return Sema::IncompatibleBlockPointer; + + Sema::AssignConvertType ConvTy = Sema::Compatible; + + // For blocks we enforce that qualifiers are identical. + if (lhptee.getLocalQualifiers() != rhptee.getLocalQualifiers()) + ConvTy = Sema::CompatiblePointerDiscardsQualifiers; + + if (!S.Context.typesAreBlockPointerCompatible(lhsType, rhsType)) + return Sema::IncompatibleBlockPointer; + + return ConvTy; +} + +/// checkObjCPointerTypesForAssignment - Compares two objective-c pointer types +/// for assignment compatibility. +static Sema::AssignConvertType +checkObjCPointerTypesForAssignment(Sema &S, QualType lhsType, QualType rhsType) { + assert(lhsType.isCanonical() && "LHS was not canonicalized!"); + assert(rhsType.isCanonical() && "RHS was not canonicalized!"); + + if (lhsType->isObjCBuiltinType()) { + // Class is not compatible with ObjC object pointers. + if (lhsType->isObjCClassType() && !rhsType->isObjCBuiltinType() && + !rhsType->isObjCQualifiedClassType()) + return Sema::IncompatiblePointer; + return Sema::Compatible; + } + if (rhsType->isObjCBuiltinType()) { + // Class is not compatible with ObjC object pointers. + if (rhsType->isObjCClassType() && !lhsType->isObjCBuiltinType() && + !lhsType->isObjCQualifiedClassType()) + return Sema::IncompatiblePointer; + return Sema::Compatible; + } + QualType lhptee = + lhsType->getAs<ObjCObjectPointerType>()->getPointeeType(); + QualType rhptee = + rhsType->getAs<ObjCObjectPointerType>()->getPointeeType(); + + if (!lhptee.isAtLeastAsQualifiedAs(rhptee)) + return Sema::CompatiblePointerDiscardsQualifiers; + + if (S.Context.typesAreCompatible(lhsType, rhsType)) + return Sema::Compatible; + if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) + return Sema::IncompatibleObjCQualifiedId; + return Sema::IncompatiblePointer; +} + +Sema::AssignConvertType +Sema::CheckAssignmentConstraints(SourceLocation Loc, + QualType lhsType, QualType rhsType) { + // Fake up an opaque expression. We don't actually care about what + // cast operations are required, so if CheckAssignmentConstraints + // adds casts to this they'll be wasted, but fortunately that doesn't + // usually happen on valid code. + OpaqueValueExpr rhs(Loc, rhsType, VK_RValue); + ExprResult rhsPtr = &rhs; + CastKind K = CK_Invalid; + + return CheckAssignmentConstraints(lhsType, rhsPtr, K); +} + +/// CheckAssignmentConstraints (C99 6.5.16) - This routine currently +/// has code to accommodate several GCC extensions when type checking +/// pointers. Here are some objectionable examples that GCC considers warnings: +/// +/// int a, *pint; +/// short *pshort; +/// struct foo *pfoo; +/// +/// pint = pshort; // warning: assignment from incompatible pointer type +/// a = pint; // warning: assignment makes integer from pointer without a cast +/// pint = a; // warning: assignment makes pointer from integer without a cast +/// pint = pfoo; // warning: assignment from incompatible pointer type +/// +/// As a result, the code for dealing with pointers is more complex than the +/// C99 spec dictates. +/// +/// Sets 'Kind' for any result kind except Incompatible. +Sema::AssignConvertType +Sema::CheckAssignmentConstraints(QualType lhsType, ExprResult &rhs, + CastKind &Kind) { + QualType rhsType = rhs.get()->getType(); + + // Get canonical types. We're not formatting these types, just comparing + // them. + lhsType = Context.getCanonicalType(lhsType).getUnqualifiedType(); + rhsType = Context.getCanonicalType(rhsType).getUnqualifiedType(); + + // Common case: no conversion required. + if (lhsType == rhsType) { + Kind = CK_NoOp; + return Compatible; + } + + // If the left-hand side is a reference type, then we are in a + // (rare!) case where we've allowed the use of references in C, + // e.g., as a parameter type in a built-in function. In this case, + // just make sure that the type referenced is compatible with the + // right-hand side type. The caller is responsible for adjusting + // lhsType so that the resulting expression does not have reference + // type. + if (const ReferenceType *lhsTypeRef = lhsType->getAs<ReferenceType>()) { + if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType)) { + Kind = CK_LValueBitCast; + return Compatible; + } + return Incompatible; + } + + // Allow scalar to ExtVector assignments, and assignments of an ExtVector type + // to the same ExtVector type. + if (lhsType->isExtVectorType()) { + if (rhsType->isExtVectorType()) + return Incompatible; + if (rhsType->isArithmeticType()) { + // CK_VectorSplat does T -> vector T, so first cast to the + // element type. + QualType elType = cast<ExtVectorType>(lhsType)->getElementType(); + if (elType != rhsType) { + Kind = PrepareScalarCast(*this, rhs, elType); + rhs = ImpCastExprToType(rhs.take(), elType, Kind); + } + Kind = CK_VectorSplat; + return Compatible; + } + } + + // Conversions to or from vector type. + if (lhsType->isVectorType() || rhsType->isVectorType()) { + if (lhsType->isVectorType() && rhsType->isVectorType()) { + // Allow assignments of an AltiVec vector type to an equivalent GCC + // vector type and vice versa + if (Context.areCompatibleVectorTypes(lhsType, rhsType)) { + Kind = CK_BitCast; + return Compatible; + } + + // If we are allowing lax vector conversions, and LHS and RHS are both + // vectors, the total size only needs to be the same. This is a bitcast; + // no bits are changed but the result type is different. + if (getLangOptions().LaxVectorConversions && + (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))) { + Kind = CK_BitCast; + return IncompatibleVectors; + } + } + return Incompatible; + } + + // Arithmetic conversions. + if (lhsType->isArithmeticType() && rhsType->isArithmeticType() && + !(getLangOptions().CPlusPlus && lhsType->isEnumeralType())) { + Kind = PrepareScalarCast(*this, rhs, lhsType); + return Compatible; + } + + // Conversions to normal pointers. + if (const PointerType *lhsPointer = dyn_cast<PointerType>(lhsType)) { + // U* -> T* + if (isa<PointerType>(rhsType)) { + Kind = CK_BitCast; + return checkPointerTypesForAssignment(*this, lhsType, rhsType); + } + + // int -> T* + if (rhsType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null? + return IntToPointer; + } + + // C pointers are not compatible with ObjC object pointers, + // with two exceptions: + if (isa<ObjCObjectPointerType>(rhsType)) { + // - conversions to void* + if (lhsPointer->getPointeeType()->isVoidType()) { + Kind = CK_AnyPointerToObjCPointerCast; + return Compatible; + } + + // - conversions from 'Class' to the redefinition type + if (rhsType->isObjCClassType() && + Context.hasSameType(lhsType, Context.ObjCClassRedefinitionType)) { + Kind = CK_BitCast; + return Compatible; + } + + Kind = CK_BitCast; + return IncompatiblePointer; + } + + // U^ -> void* + if (rhsType->getAs<BlockPointerType>()) { + if (lhsPointer->getPointeeType()->isVoidType()) { + Kind = CK_BitCast; + return Compatible; + } + } + + return Incompatible; + } + + // Conversions to block pointers. + if (isa<BlockPointerType>(lhsType)) { + // U^ -> T^ + if (rhsType->isBlockPointerType()) { + Kind = CK_AnyPointerToBlockPointerCast; + return checkBlockPointerTypesForAssignment(*this, lhsType, rhsType); + } + + // int or null -> T^ + if (rhsType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null + return IntToBlockPointer; + } + + // id -> T^ + if (getLangOptions().ObjC1 && rhsType->isObjCIdType()) { + Kind = CK_AnyPointerToBlockPointerCast; + return Compatible; + } + + // void* -> T^ + if (const PointerType *RHSPT = rhsType->getAs<PointerType>()) + if (RHSPT->getPointeeType()->isVoidType()) { + Kind = CK_AnyPointerToBlockPointerCast; + return Compatible; + } + + return Incompatible; + } + + // Conversions to Objective-C pointers. + if (isa<ObjCObjectPointerType>(lhsType)) { + // A* -> B* + if (rhsType->isObjCObjectPointerType()) { + Kind = CK_BitCast; + return checkObjCPointerTypesForAssignment(*this, lhsType, rhsType); + } + + // int or null -> A* + if (rhsType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null + return IntToPointer; + } + + // In general, C pointers are not compatible with ObjC object pointers, + // with two exceptions: + if (isa<PointerType>(rhsType)) { + // - conversions from 'void*' + if (rhsType->isVoidPointerType()) { + Kind = CK_AnyPointerToObjCPointerCast; + return Compatible; + } + + // - conversions to 'Class' from its redefinition type + if (lhsType->isObjCClassType() && + Context.hasSameType(rhsType, Context.ObjCClassRedefinitionType)) { + Kind = CK_BitCast; + return Compatible; + } + + Kind = CK_AnyPointerToObjCPointerCast; + return IncompatiblePointer; + } + + // T^ -> A* + if (rhsType->isBlockPointerType()) { + Kind = CK_AnyPointerToObjCPointerCast; + return Compatible; + } + + return Incompatible; + } + + // Conversions from pointers that are not covered by the above. + if (isa<PointerType>(rhsType)) { + // T* -> _Bool + if (lhsType == Context.BoolTy) { + Kind = CK_PointerToBoolean; + return Compatible; + } + + // T* -> int + if (lhsType->isIntegerType()) { + Kind = CK_PointerToIntegral; + return PointerToInt; + } + + return Incompatible; + } + + // Conversions from Objective-C pointers that are not covered by the above. + if (isa<ObjCObjectPointerType>(rhsType)) { + // T* -> _Bool + if (lhsType == Context.BoolTy) { + Kind = CK_PointerToBoolean; + return Compatible; + } + + // T* -> int + if (lhsType->isIntegerType()) { + Kind = CK_PointerToIntegral; + return PointerToInt; + } + + return Incompatible; + } + + // struct A -> struct B + if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) { + if (Context.typesAreCompatible(lhsType, rhsType)) { + Kind = CK_NoOp; + return Compatible; + } + } + + return Incompatible; +} + +/// \brief Constructs a transparent union from an expression that is +/// used to initialize the transparent union. +static void ConstructTransparentUnion(Sema &S, ASTContext &C, ExprResult &EResult, + QualType UnionType, FieldDecl *Field) { + // Build an initializer list that designates the appropriate member + // of the transparent union. + Expr *E = EResult.take(); + InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(), + &E, 1, + SourceLocation()); + Initializer->setType(UnionType); + Initializer->setInitializedFieldInUnion(Field); + + // Build a compound literal constructing a value of the transparent + // union type from this initializer list. + TypeSourceInfo *unionTInfo = C.getTrivialTypeSourceInfo(UnionType); + EResult = S.Owned( + new (C) CompoundLiteralExpr(SourceLocation(), unionTInfo, UnionType, + VK_RValue, Initializer, false)); +} + +Sema::AssignConvertType +Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, ExprResult &rExpr) { + QualType FromType = rExpr.get()->getType(); + + // If the ArgType is a Union type, we want to handle a potential + // transparent_union GCC extension. + const RecordType *UT = ArgType->getAsUnionType(); + if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) + return Incompatible; + + // The field to initialize within the transparent union. + RecordDecl *UD = UT->getDecl(); + FieldDecl *InitField = 0; + // It's compatible if the expression matches any of the fields. + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); + it != itend; ++it) { + if (it->getType()->isPointerType()) { + // If the transparent union contains a pointer type, we allow: + // 1) void pointer + // 2) null pointer constant + if (FromType->isPointerType()) + if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) { + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_BitCast); + InitField = *it; + break; + } + + if (rExpr.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), CK_NullToPointer); + InitField = *it; + break; + } + } + + CastKind Kind = CK_Invalid; + if (CheckAssignmentConstraints(it->getType(), rExpr, Kind) + == Compatible) { + rExpr = ImpCastExprToType(rExpr.take(), it->getType(), Kind); + InitField = *it; + break; + } + } + + if (!InitField) + return Incompatible; + + ConstructTransparentUnion(*this, Context, rExpr, ArgType, InitField); + return Compatible; +} + +Sema::AssignConvertType +Sema::CheckSingleAssignmentConstraints(QualType lhsType, ExprResult &rExpr) { + if (getLangOptions().CPlusPlus) { + if (!lhsType->isRecordType()) { + // C++ 5.17p3: If the left operand is not of class type, the + // expression is implicitly converted (C++ 4) to the + // cv-unqualified type of the left operand. + ExprResult Res = PerformImplicitConversion(rExpr.get(), + lhsType.getUnqualifiedType(), + AA_Assigning); + if (Res.isInvalid()) + return Incompatible; + rExpr = move(Res); + return Compatible; + } + + // FIXME: Currently, we fall through and treat C++ classes like C + // structures. + } + + // C99 6.5.16.1p1: the left operand is a pointer and the right is + // a null pointer constant. + if ((lhsType->isPointerType() || + lhsType->isObjCObjectPointerType() || + lhsType->isBlockPointerType()) + && rExpr.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + rExpr = ImpCastExprToType(rExpr.take(), lhsType, CK_NullToPointer); + return Compatible; + } + + // This check seems unnatural, however it is necessary to ensure the proper + // conversion of functions/arrays. If the conversion were done for all + // DeclExpr's (created by ActOnIdExpression), it would mess up the unary + // expressions that suppress this implicit conversion (&, sizeof). + // + // Suppress this for references: C++ 8.5.3p5. + if (!lhsType->isReferenceType()) { + rExpr = DefaultFunctionArrayLvalueConversion(rExpr.take()); + if (rExpr.isInvalid()) + return Incompatible; + } + + CastKind Kind = CK_Invalid; + Sema::AssignConvertType result = + CheckAssignmentConstraints(lhsType, rExpr, Kind); + + // C99 6.5.16.1p2: The value of the right operand is converted to the + // type of the assignment expression. + // CheckAssignmentConstraints allows the left-hand side to be a reference, + // so that we can use references in built-in functions even in C. + // The getNonReferenceType() call makes sure that the resulting expression + // does not have reference type. + if (result != Incompatible && rExpr.get()->getType() != lhsType) + rExpr = ImpCastExprToType(rExpr.take(), lhsType.getNonLValueExprType(Context), Kind); + return result; +} + +QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) { + Diag(Loc, diag::err_typecheck_invalid_operands) + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); +} + +QualType Sema::CheckVectorOperands(SourceLocation Loc, ExprResult &lex, ExprResult &rex) { + // For conversion purposes, we ignore any qualifiers. + // For example, "const float" and "float" are equivalent. + QualType lhsType = + Context.getCanonicalType(lex.get()->getType()).getUnqualifiedType(); + QualType rhsType = + Context.getCanonicalType(rex.get()->getType()).getUnqualifiedType(); + + // If the vector types are identical, return. + if (lhsType == rhsType) + return lhsType; + + // Handle the case of a vector & extvector type of the same size and element + // type. It would be nice if we only had one vector type someday. + if (getLangOptions().LaxVectorConversions) { + if (const VectorType *LV = lhsType->getAs<VectorType>()) { + if (const VectorType *RV = rhsType->getAs<VectorType>()) { + if (LV->getElementType() == RV->getElementType() && + LV->getNumElements() == RV->getNumElements()) { + if (lhsType->isExtVectorType()) { + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); + return lhsType; + } + + lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); + return rhsType; + } else if (Context.getTypeSize(lhsType) ==Context.getTypeSize(rhsType)){ + // If we are allowing lax vector conversions, and LHS and RHS are both + // vectors, the total size only needs to be the same. This is a + // bitcast; no bits are changed but the result type is different. + rex = ImpCastExprToType(rex.take(), lhsType, CK_BitCast); + return lhsType; + } + } + } + } + + // Handle the case of equivalent AltiVec and GCC vector types + if (lhsType->isVectorType() && rhsType->isVectorType() && + Context.areCompatibleVectorTypes(lhsType, rhsType)) { + lex = ImpCastExprToType(lex.take(), rhsType, CK_BitCast); + return rhsType; + } + + // Canonicalize the ExtVector to the LHS, remember if we swapped so we can + // swap back (so that we don't reverse the inputs to a subtract, for instance. + bool swapped = false; + if (rhsType->isExtVectorType()) { + swapped = true; + std::swap(rex, lex); + std::swap(rhsType, lhsType); + } + + // Handle the case of an ext vector and scalar. + if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) { + QualType EltTy = LV->getElementType(); + if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) { + int order = Context.getIntegerTypeOrder(EltTy, rhsType); + if (order > 0) + rex = ImpCastExprToType(rex.take(), EltTy, CK_IntegralCast); + if (order >= 0) { + rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat); + if (swapped) std::swap(rex, lex); + return lhsType; + } + } + if (EltTy->isRealFloatingType() && rhsType->isScalarType() && + rhsType->isRealFloatingType()) { + int order = Context.getFloatingTypeOrder(EltTy, rhsType); + if (order > 0) + rex = ImpCastExprToType(rex.take(), EltTy, CK_FloatingCast); + if (order >= 0) { + rex = ImpCastExprToType(rex.take(), lhsType, CK_VectorSplat); + if (swapped) std::swap(rex, lex); + return lhsType; + } + } + } + + // Vectors of different size or scalar and non-ext-vector are errors. + Diag(Loc, diag::err_typecheck_vector_not_convertable) + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); +} + +QualType Sema::CheckMultiplyDivideOperands( + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign, bool isDiv) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) + return CheckVectorOperands(Loc, lex, rex); + + QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); + + if (!lex.get()->getType()->isArithmeticType() || + !rex.get()->getType()->isArithmeticType()) + return InvalidOperands(Loc, lex, rex); + + // Check for division by zero. + if (isDiv && + rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_division_by_zero) + << rex.get()->getSourceRange()); + + return compType; +} + +QualType Sema::CheckRemainderOperands( + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + if (lex.get()->getType()->hasIntegerRepresentation() && + rex.get()->getType()->hasIntegerRepresentation()) + return CheckVectorOperands(Loc, lex, rex); + return InvalidOperands(Loc, lex, rex); + } + + QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); + + if (!lex.get()->getType()->isIntegerType() || !rex.get()->getType()->isIntegerType()) + return InvalidOperands(Loc, lex, rex); + + // Check for remainder by zero. + if (rex.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(Loc, rex.get(), PDiag(diag::warn_remainder_by_zero) + << rex.get()->getSourceRange()); + + return compType; +} + +QualType Sema::CheckAdditionOperands( // C99 6.5.6 + ExprResult &lex, ExprResult &rex, SourceLocation Loc, QualType* CompLHSTy) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + QualType compType = CheckVectorOperands(Loc, lex, rex); + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); + + // handle the common case first (both operands are arithmetic). + if (lex.get()->getType()->isArithmeticType() && + rex.get()->getType()->isArithmeticType()) { + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + // Put any potential pointer into PExp + Expr* PExp = lex.get(), *IExp = rex.get(); + if (IExp->getType()->isAnyPointerType()) + std::swap(PExp, IExp); + + if (PExp->getType()->isAnyPointerType()) { + + if (IExp->getType()->isIntegerType()) { + QualType PointeeTy = PExp->getType()->getPointeeType(); + + // Check for arithmetic on pointers to incomplete types. + if (PointeeTy->isVoidType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_void_type) + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); + } + + // GNU extension: arithmetic on pointer to void + Diag(Loc, diag::ext_gnu_void_ptr) + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } else if (PointeeTy->isFunctionType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) + << lex.get()->getType() << lex.get()->getSourceRange(); + return QualType(); + } + + // GNU extension: arithmetic on pointer to function + Diag(Loc, diag::ext_gnu_ptr_func_arith) + << lex.get()->getType() << lex.get()->getSourceRange(); + } else { + // Check if we require a complete type. + if (((PExp->getType()->isPointerType() && + !PExp->getType()->isDependentType()) || + PExp->getType()->isObjCObjectPointerType()) && + RequireCompleteType(Loc, PointeeTy, + PDiag(diag::err_typecheck_arithmetic_incomplete_type) + << PExp->getSourceRange() + << PExp->getType())) + return QualType(); + } + // Diagnose bad cases where we step over interface counts. + if (PointeeTy->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { + Diag(Loc, diag::err_arithmetic_nonfragile_interface) + << PointeeTy << PExp->getSourceRange(); + return QualType(); + } + + if (CompLHSTy) { + QualType LHSTy = Context.isPromotableBitField(lex.get()); + if (LHSTy.isNull()) { + LHSTy = lex.get()->getType(); + if (LHSTy->isPromotableIntegerType()) + LHSTy = Context.getPromotedIntegerType(LHSTy); + } + *CompLHSTy = LHSTy; + } + return PExp->getType(); + } + } + + return InvalidOperands(Loc, lex, rex); +} + +// C99 6.5.6 +QualType Sema::CheckSubtractionOperands(ExprResult &lex, ExprResult &rex, + SourceLocation Loc, QualType* CompLHSTy) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + QualType compType = CheckVectorOperands(Loc, lex, rex); + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + QualType compType = UsualArithmeticConversions(lex, rex, CompLHSTy); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); + + // Enforce type constraints: C99 6.5.6p3. + + // Handle the common case first (both operands are arithmetic). + if (lex.get()->getType()->isArithmeticType() && + rex.get()->getType()->isArithmeticType()) { + if (CompLHSTy) *CompLHSTy = compType; + return compType; + } + + // Either ptr - int or ptr - ptr. + if (lex.get()->getType()->isAnyPointerType()) { + QualType lpointee = lex.get()->getType()->getPointeeType(); + + // The LHS must be an completely-defined object type. + + bool ComplainAboutVoid = false; + Expr *ComplainAboutFunc = 0; + if (lpointee->isVoidType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_void_type) + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); + } + + // GNU C extension: arithmetic on pointer to void + ComplainAboutVoid = true; + } else if (lpointee->isFunctionType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) + << lex.get()->getType() << lex.get()->getSourceRange(); + return QualType(); + } + + // GNU C extension: arithmetic on pointer to function + ComplainAboutFunc = lex.get(); + } else if (!lpointee->isDependentType() && + RequireCompleteType(Loc, lpointee, + PDiag(diag::err_typecheck_sub_ptr_object) + << lex.get()->getSourceRange() + << lex.get()->getType())) + return QualType(); + + // Diagnose bad cases where we step over interface counts. + if (lpointee->isObjCObjectType() && LangOpts.ObjCNonFragileABI) { + Diag(Loc, diag::err_arithmetic_nonfragile_interface) + << lpointee << lex.get()->getSourceRange(); + return QualType(); + } + + // The result type of a pointer-int computation is the pointer type. + if (rex.get()->getType()->isIntegerType()) { + if (ComplainAboutVoid) + Diag(Loc, diag::ext_gnu_void_ptr) + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + if (ComplainAboutFunc) + Diag(Loc, diag::ext_gnu_ptr_func_arith) + << ComplainAboutFunc->getType() + << ComplainAboutFunc->getSourceRange(); + + if (CompLHSTy) *CompLHSTy = lex.get()->getType(); + return lex.get()->getType(); + } + + // Handle pointer-pointer subtractions. + if (const PointerType *RHSPTy = rex.get()->getType()->getAs<PointerType>()) { + QualType rpointee = RHSPTy->getPointeeType(); + + // RHS must be a completely-type object type. + // Handle the GNU void* extension. + if (rpointee->isVoidType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_void_type) + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); + } + + ComplainAboutVoid = true; + } else if (rpointee->isFunctionType()) { + if (getLangOptions().CPlusPlus) { + Diag(Loc, diag::err_typecheck_pointer_arith_function_type) + << rex.get()->getType() << rex.get()->getSourceRange(); + return QualType(); + } + + // GNU extension: arithmetic on pointer to function + if (!ComplainAboutFunc) + ComplainAboutFunc = rex.get(); + } else if (!rpointee->isDependentType() && + RequireCompleteType(Loc, rpointee, + PDiag(diag::err_typecheck_sub_ptr_object) + << rex.get()->getSourceRange() + << rex.get()->getType())) + return QualType(); + + if (getLangOptions().CPlusPlus) { + // Pointee types must be the same: C++ [expr.add] + if (!Context.hasSameUnqualifiedType(lpointee, rpointee)) { + Diag(Loc, diag::err_typecheck_sub_ptr_compatible) + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); + } + } else { + // Pointee types must be compatible C99 6.5.6p3 + if (!Context.typesAreCompatible( + Context.getCanonicalType(lpointee).getUnqualifiedType(), + Context.getCanonicalType(rpointee).getUnqualifiedType())) { + Diag(Loc, diag::err_typecheck_sub_ptr_compatible) + << lex.get()->getType() << rex.get()->getType() + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); + } + } + + if (ComplainAboutVoid) + Diag(Loc, diag::ext_gnu_void_ptr) + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + if (ComplainAboutFunc) + Diag(Loc, diag::ext_gnu_ptr_func_arith) + << ComplainAboutFunc->getType() + << ComplainAboutFunc->getSourceRange(); + + if (CompLHSTy) *CompLHSTy = lex.get()->getType(); + return Context.getPointerDiffType(); + } + } + + return InvalidOperands(Loc, lex, rex); +} + +static bool isScopedEnumerationType(QualType T) { + if (const EnumType *ET = dyn_cast<EnumType>(T)) + return ET->getDecl()->isScoped(); + return false; +} + +static void DiagnoseBadShiftValues(Sema& S, ExprResult &lex, ExprResult &rex, + SourceLocation Loc, unsigned Opc, + QualType LHSTy) { + llvm::APSInt Right; + // Check right/shifter operand + if (rex.get()->isValueDependent() || !rex.get()->isIntegerConstantExpr(Right, S.Context)) + return; + + if (Right.isNegative()) { + S.DiagRuntimeBehavior(Loc, rex.get(), + S.PDiag(diag::warn_shift_negative) + << rex.get()->getSourceRange()); + return; + } + llvm::APInt LeftBits(Right.getBitWidth(), + S.Context.getTypeSize(lex.get()->getType())); + if (Right.uge(LeftBits)) { + S.DiagRuntimeBehavior(Loc, rex.get(), + S.PDiag(diag::warn_shift_gt_typewidth) + << rex.get()->getSourceRange()); + return; + } + if (Opc != BO_Shl) + return; + + // When left shifting an ICE which is signed, we can check for overflow which + // according to C++ has undefined behavior ([expr.shift] 5.8/2). Unsigned + // integers have defined behavior modulo one more than the maximum value + // representable in the result type, so never warn for those. + llvm::APSInt Left; + if (lex.get()->isValueDependent() || !lex.get()->isIntegerConstantExpr(Left, S.Context) || + LHSTy->hasUnsignedIntegerRepresentation()) + return; + llvm::APInt ResultBits = + static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits(); + if (LeftBits.uge(ResultBits)) + return; + llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue()); + Result = Result.shl(Right); + + // If we are only missing a sign bit, this is less likely to result in actual + // bugs -- if the result is cast back to an unsigned type, it will have the + // expected value. Thus we place this behind a different warning that can be + // turned off separately if needed. + if (LeftBits == ResultBits - 1) { + S.Diag(Loc, diag::warn_shift_result_overrides_sign_bit) + << Result.toString(10) << LHSTy + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return; + } + + S.Diag(Loc, diag::warn_shift_result_gt_typewidth) + << Result.toString(10) << Result.getMinSignedBits() << LHSTy + << Left.getBitWidth() << lex.get()->getSourceRange() << rex.get()->getSourceRange(); +} + +// C99 6.5.7 +QualType Sema::CheckShiftOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, + unsigned Opc, bool isCompAssign) { + // C99 6.5.7p2: Each of the operands shall have integer type. + if (!lex.get()->getType()->hasIntegerRepresentation() || + !rex.get()->getType()->hasIntegerRepresentation()) + return InvalidOperands(Loc, lex, rex); + + // C++0x: Don't allow scoped enums. FIXME: Use something better than + // hasIntegerRepresentation() above instead of this. + if (isScopedEnumerationType(lex.get()->getType()) || + isScopedEnumerationType(rex.get()->getType())) { + return InvalidOperands(Loc, lex, rex); + } + + // Vector shifts promote their scalar inputs to vector type. + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) + return CheckVectorOperands(Loc, lex, rex); + + // Shifts don't perform usual arithmetic conversions, they just do integer + // promotions on each operand. C99 6.5.7p3 + + // For the LHS, do usual unary conversions, but then reset them away + // if this is a compound assignment. + ExprResult old_lex = lex; + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + QualType LHSTy = lex.get()->getType(); + if (isCompAssign) lex = old_lex; + + // The RHS is simpler. + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); + + // Sanity-check shift operands + DiagnoseBadShiftValues(*this, lex, rex, Loc, Opc, LHSTy); + + // "The type of the result is that of the promoted left operand." + return LHSTy; +} + +static bool IsWithinTemplateSpecialization(Decl *D) { + if (DeclContext *DC = D->getDeclContext()) { + if (isa<ClassTemplateSpecializationDecl>(DC)) + return true; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) + return FD->isFunctionTemplateSpecialization(); + } + return false; +} + +// C99 6.5.8, C++ [expr.rel] +QualType Sema::CheckCompareOperands(ExprResult &lex, ExprResult &rex, SourceLocation Loc, + unsigned OpaqueOpc, bool isRelational) { + BinaryOperatorKind Opc = (BinaryOperatorKind) OpaqueOpc; + + // Handle vector comparisons separately. + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) + return CheckVectorCompareOperands(lex, rex, Loc, isRelational); + + QualType lType = lex.get()->getType(); + QualType rType = rex.get()->getType(); + + Expr *LHSStripped = lex.get()->IgnoreParenImpCasts(); + Expr *RHSStripped = rex.get()->IgnoreParenImpCasts(); + QualType LHSStrippedType = LHSStripped->getType(); + QualType RHSStrippedType = RHSStripped->getType(); + + + + // Two different enums will raise a warning when compared. + if (const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>()) { + if (const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>()) { + if (LHSEnumType->getDecl()->getIdentifier() && + RHSEnumType->getDecl()->getIdentifier() && + !Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) { + Diag(Loc, diag::warn_comparison_of_mixed_enum_types) + << LHSStrippedType << RHSStrippedType + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + } + } + + if (!lType->hasFloatingRepresentation() && + !(lType->isBlockPointerType() && isRelational) && + !lex.get()->getLocStart().isMacroID() && + !rex.get()->getLocStart().isMacroID()) { + // For non-floating point types, check for self-comparisons of the form + // x == x, x != x, x < x, etc. These always evaluate to a constant, and + // often indicate logic errors in the program. + // + // NOTE: Don't warn about comparison expressions resulting from macro + // expansion. Also don't warn about comparisons which are only self + // comparisons within a template specialization. The warnings should catch + // obvious cases in the definition of the template anyways. The idea is to + // warn when the typed comparison operator will always evaluate to the same + // result. + if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) { + if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) { + if (DRL->getDecl() == DRR->getDecl() && + !IsWithinTemplateSpecialization(DRL->getDecl())) { + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) + << 0 // self- + << (Opc == BO_EQ + || Opc == BO_LE + || Opc == BO_GE)); + } else if (lType->isArrayType() && rType->isArrayType() && + !DRL->getDecl()->getType()->isReferenceType() && + !DRR->getDecl()->getType()->isReferenceType()) { + // what is it always going to eval to? + char always_evals_to; + switch(Opc) { + case BO_EQ: // e.g. array1 == array2 + always_evals_to = 0; // false + break; + case BO_NE: // e.g. array1 != array2 + always_evals_to = 1; // true + break; + default: + // best we can say is 'a constant' + always_evals_to = 2; // e.g. array1 <= array2 + break; + } + DiagRuntimeBehavior(Loc, 0, PDiag(diag::warn_comparison_always) + << 1 // array + << always_evals_to); + } + } + } + + if (isa<CastExpr>(LHSStripped)) + LHSStripped = LHSStripped->IgnoreParenCasts(); + if (isa<CastExpr>(RHSStripped)) + RHSStripped = RHSStripped->IgnoreParenCasts(); + + // Warn about comparisons against a string constant (unless the other + // operand is null), the user probably wants strcmp. + Expr *literalString = 0; + Expr *literalStringStripped = 0; + if ((isa<StringLiteral>(LHSStripped) || isa<ObjCEncodeExpr>(LHSStripped)) && + !RHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + literalString = lex.get(); + literalStringStripped = LHSStripped; + } else if ((isa<StringLiteral>(RHSStripped) || + isa<ObjCEncodeExpr>(RHSStripped)) && + !LHSStripped->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull)) { + literalString = rex.get(); + literalStringStripped = RHSStripped; + } + + if (literalString) { + std::string resultComparison; + switch (Opc) { + case BO_LT: resultComparison = ") < 0"; break; + case BO_GT: resultComparison = ") > 0"; break; + case BO_LE: resultComparison = ") <= 0"; break; + case BO_GE: resultComparison = ") >= 0"; break; + case BO_EQ: resultComparison = ") == 0"; break; + case BO_NE: resultComparison = ") != 0"; break; + default: assert(false && "Invalid comparison operator"); + } + + DiagRuntimeBehavior(Loc, 0, + PDiag(diag::warn_stringcompare) + << isa<ObjCEncodeExpr>(literalStringStripped) + << literalString->getSourceRange()); + } + } + + // C99 6.5.8p3 / C99 6.5.9p4 + if (lex.get()->getType()->isArithmeticType() && rex.get()->getType()->isArithmeticType()) { + UsualArithmeticConversions(lex, rex); + if (lex.isInvalid() || rex.isInvalid()) + return QualType(); + } + else { + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); + } + + lType = lex.get()->getType(); + rType = rex.get()->getType(); + + // The result of comparisons is 'bool' in C++, 'int' in C. + QualType ResultTy = Context.getLogicalOperationType(); + + if (isRelational) { + if (lType->isRealType() && rType->isRealType()) + return ResultTy; + } else { + // Check for comparisons of floating point operands using != and ==. + if (lType->hasFloatingRepresentation()) + CheckFloatComparison(Loc, lex.get(), rex.get()); + + if (lType->isArithmeticType() && rType->isArithmeticType()) + return ResultTy; + } + + bool LHSIsNull = lex.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + bool RHSIsNull = rex.get()->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + + // All of the following pointer-related warnings are GCC extensions, except + // when handling null pointer constants. + if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2 + QualType LCanPointeeTy = + Context.getCanonicalType(lType->getAs<PointerType>()->getPointeeType()); + QualType RCanPointeeTy = + Context.getCanonicalType(rType->getAs<PointerType>()->getPointeeType()); + + if (getLangOptions().CPlusPlus) { + if (LCanPointeeTy == RCanPointeeTy) + return ResultTy; + if (!isRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + // This is a gcc extension compatibility comparison. + // In a SFINAE context, we treat this as a hard error to maintain + // conformance with the C++ standard. + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + Diag(Loc, + isSFINAEContext()? + diag::err_typecheck_comparison_of_fptr_to_void + : diag::ext_typecheck_comparison_of_fptr_to_void) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + + if (isSFINAEContext()) + return QualType(); + + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); + return ResultTy; + } + } + + // C++ [expr.rel]p2: + // [...] Pointer conversions (4.10) and qualification + // conversions (4.4) are performed on pointer operands (or on + // a pointer operand and a null pointer constant) to bring + // them to their composite pointer type. [...] + // + // C++ [expr.eq]p1 uses the same notion for (in)equality + // comparisons of pointers. + bool NonStandardCompositeType = false; + QualType T = FindCompositePointerType(Loc, lex, rex, + isSFINAEContext()? 0 : &NonStandardCompositeType); + if (T.isNull()) { + Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); + } else if (NonStandardCompositeType) { + Diag(Loc, + diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) + << lType << rType << T + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + + lex = ImpCastExprToType(lex.take(), T, CK_BitCast); + rex = ImpCastExprToType(rex.take(), T, CK_BitCast); + return ResultTy; + } + // C99 6.5.9p2 and C99 6.5.8p2 + if (Context.typesAreCompatible(LCanPointeeTy.getUnqualifiedType(), + RCanPointeeTy.getUnqualifiedType())) { + // Valid unless a relational comparison of function pointers + if (isRelational && LCanPointeeTy->isFunctionType()) { + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + } else if (!isRelational && + (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { + // Valid unless comparison between non-null pointer and function pointer + if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) + && !LHSIsNull && !RHSIsNull) { + Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + } else { + // Invalid + Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + if (LCanPointeeTy != RCanPointeeTy) { + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); + } + return ResultTy; + } + + if (getLangOptions().CPlusPlus) { + // Comparison of nullptr_t with itself. + if (lType->isNullPtrType() && rType->isNullPtrType()) + return ResultTy; + + // Comparison of pointers with null pointer constants and equality + // comparisons of member pointers to null pointer constants. + if (RHSIsNull && + ((lType->isAnyPointerType() || lType->isNullPtrType()) || + (!isRelational && lType->isMemberPointerType()))) { + rex = ImpCastExprToType(rex.take(), lType, + lType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_NullToPointer); + return ResultTy; + } + if (LHSIsNull && + ((rType->isAnyPointerType() || rType->isNullPtrType()) || + (!isRelational && rType->isMemberPointerType()))) { + lex = ImpCastExprToType(lex.take(), rType, + rType->isMemberPointerType() + ? CK_NullToMemberPointer + : CK_NullToPointer); + return ResultTy; + } + + // Comparison of member pointers. + if (!isRelational && + lType->isMemberPointerType() && rType->isMemberPointerType()) { + // C++ [expr.eq]p2: + // In addition, pointers to members can be compared, or a pointer to + // member and a null pointer constant. Pointer to member conversions + // (4.11) and qualification conversions (4.4) are performed to bring + // them to a common type. If one operand is a null pointer constant, + // the common type is the type of the other operand. Otherwise, the + // common type is a pointer to member type similar (4.4) to the type + // of one of the operands, with a cv-qualification signature (4.4) + // that is the union of the cv-qualification signatures of the operand + // types. + bool NonStandardCompositeType = false; + QualType T = FindCompositePointerType(Loc, lex, rex, + isSFINAEContext()? 0 : &NonStandardCompositeType); + if (T.isNull()) { + Diag(Loc, diag::err_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + return QualType(); + } else if (NonStandardCompositeType) { + Diag(Loc, + diag::ext_typecheck_comparison_of_distinct_pointers_nonstandard) + << lType << rType << T + << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + + lex = ImpCastExprToType(lex.take(), T, CK_BitCast); + rex = ImpCastExprToType(rex.take(), T, CK_BitCast); + return ResultTy; + } + + // Handle scoped enumeration types specifically, since they don't promote + // to integers. + if (lex.get()->getType()->isEnumeralType() && + Context.hasSameUnqualifiedType(lex.get()->getType(), rex.get()->getType())) + return ResultTy; + } + + // Handle block pointer types. + if (!isRelational && lType->isBlockPointerType() && rType->isBlockPointerType()) { + QualType lpointee = lType->getAs<BlockPointerType>()->getPointeeType(); + QualType rpointee = rType->getAs<BlockPointerType>()->getPointeeType(); + + if (!LHSIsNull && !RHSIsNull && + !Context.typesAreCompatible(lpointee, rpointee)) { + Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); + return ResultTy; + } + + // Allow block pointers to be compared with null pointer constants. + if (!isRelational + && ((lType->isBlockPointerType() && rType->isPointerType()) + || (lType->isPointerType() && rType->isBlockPointerType()))) { + if (!LHSIsNull && !RHSIsNull) { + if (!((rType->isPointerType() && rType->castAs<PointerType>() + ->getPointeeType()->isVoidType()) + || (lType->isPointerType() && lType->castAs<PointerType>() + ->getPointeeType()->isVoidType()))) + Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); + return ResultTy; + } + + if (lType->isObjCObjectPointerType() || rType->isObjCObjectPointerType()) { + const PointerType *LPT = lType->getAs<PointerType>(); + const PointerType *RPT = rType->getAs<PointerType>(); + if (LPT || RPT) { + bool LPtrToVoid = LPT ? LPT->getPointeeType()->isVoidType() : false; + bool RPtrToVoid = RPT ? RPT->getPointeeType()->isVoidType() : false; + + if (!LPtrToVoid && !RPtrToVoid && + !Context.typesAreCompatible(lType, rType)) { + Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + } + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); + return ResultTy; + } + if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) { + if (!Context.areComparableObjCPointerTypes(lType, rType)) + Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + if (LHSIsNull && !RHSIsNull) + lex = ImpCastExprToType(lex.take(), rType, CK_BitCast); + else + rex = ImpCastExprToType(rex.take(), lType, CK_BitCast); + return ResultTy; + } + } + if ((lType->isAnyPointerType() && rType->isIntegerType()) || + (lType->isIntegerType() && rType->isAnyPointerType())) { + unsigned DiagID = 0; + bool isError = false; + if ((LHSIsNull && lType->isIntegerType()) || + (RHSIsNull && rType->isIntegerType())) { + if (isRelational && !getLangOptions().CPlusPlus) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; + } else if (isRelational && !getLangOptions().CPlusPlus) + DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; + else if (getLangOptions().CPlusPlus) { + DiagID = diag::err_typecheck_comparison_of_pointer_integer; + isError = true; + } else + DiagID = diag::ext_typecheck_comparison_of_pointer_integer; + + if (DiagID) { + Diag(Loc, DiagID) + << lType << rType << lex.get()->getSourceRange() << rex.get()->getSourceRange(); + if (isError) + return QualType(); + } + + if (lType->isIntegerType()) + lex = ImpCastExprToType(lex.take(), rType, + LHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); + else + rex = ImpCastExprToType(rex.take(), lType, + RHSIsNull ? CK_NullToPointer : CK_IntegralToPointer); + return ResultTy; + } + + // Handle block pointers. + if (!isRelational && RHSIsNull + && lType->isBlockPointerType() && rType->isIntegerType()) { + rex = ImpCastExprToType(rex.take(), lType, CK_NullToPointer); + return ResultTy; + } + if (!isRelational && LHSIsNull + && lType->isIntegerType() && rType->isBlockPointerType()) { + lex = ImpCastExprToType(lex.take(), rType, CK_NullToPointer); + return ResultTy; + } + + return InvalidOperands(Loc, lex, rex); +} + +/// CheckVectorCompareOperands - vector comparisons are a clang extension that +/// operates on extended vector types. Instead of producing an IntTy result, +/// like a scalar comparison, a vector comparison produces a vector of integer +/// types. +QualType Sema::CheckVectorCompareOperands(ExprResult &lex, ExprResult &rex, + SourceLocation Loc, + bool isRelational) { + // Check to make sure we're operating on vectors of the same type and width, + // Allowing one side to be a scalar of element type. + QualType vType = CheckVectorOperands(Loc, lex, rex); + if (vType.isNull()) + return vType; + + QualType lType = lex.get()->getType(); + QualType rType = rex.get()->getType(); + + // If AltiVec, the comparison results in a numeric type, i.e. + // bool for C++, int for C + if (vType->getAs<VectorType>()->getVectorKind() == VectorType::AltiVecVector) + return Context.getLogicalOperationType(); + + // For non-floating point types, check for self-comparisons of the form + // x == x, x != x, x < x, etc. These always evaluate to a constant, and + // often indicate logic errors in the program. + if (!lType->hasFloatingRepresentation()) { + if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex.get()->IgnoreParens())) + if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex.get()->IgnoreParens())) + if (DRL->getDecl() == DRR->getDecl()) + DiagRuntimeBehavior(Loc, 0, + PDiag(diag::warn_comparison_always) + << 0 // self- + << 2 // "a constant" + ); + } + + // Check for comparisons of floating point operands using != and ==. + if (!isRelational && lType->hasFloatingRepresentation()) { + assert (rType->hasFloatingRepresentation()); + CheckFloatComparison(Loc, lex.get(), rex.get()); + } + + // Return the type for the comparison, which is the same as vector type for + // integer vectors, or an integer type of identical size and number of + // elements for floating point vectors. + if (lType->hasIntegerRepresentation()) + return lType; + + const VectorType *VTy = lType->getAs<VectorType>(); + unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); + if (TypeSize == Context.getTypeSize(Context.IntTy)) + return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); + if (TypeSize == Context.getTypeSize(Context.LongTy)) + return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); + + assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && + "Unhandled vector element size in vector compare"); + return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); +} + +inline QualType Sema::CheckBitwiseOperands( + ExprResult &lex, ExprResult &rex, SourceLocation Loc, bool isCompAssign) { + if (lex.get()->getType()->isVectorType() || rex.get()->getType()->isVectorType()) { + if (lex.get()->getType()->hasIntegerRepresentation() && + rex.get()->getType()->hasIntegerRepresentation()) + return CheckVectorOperands(Loc, lex, rex); + + return InvalidOperands(Loc, lex, rex); + } + + ExprResult lexResult = Owned(lex), rexResult = Owned(rex); + QualType compType = UsualArithmeticConversions(lexResult, rexResult, isCompAssign); + if (lexResult.isInvalid() || rexResult.isInvalid()) + return QualType(); + lex = lexResult.take(); + rex = rexResult.take(); + + if (lex.get()->getType()->isIntegralOrUnscopedEnumerationType() && + rex.get()->getType()->isIntegralOrUnscopedEnumerationType()) + return compType; + return InvalidOperands(Loc, lex, rex); +} + +inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] + ExprResult &lex, ExprResult &rex, SourceLocation Loc, unsigned Opc) { + + // Diagnose cases where the user write a logical and/or but probably meant a + // bitwise one. We do this when the LHS is a non-bool integer and the RHS + // is a constant. + if (lex.get()->getType()->isIntegerType() && !lex.get()->getType()->isBooleanType() && + rex.get()->getType()->isIntegerType() && !rex.get()->isValueDependent() && + // Don't warn in macros. + !Loc.isMacroID()) { + // If the RHS can be constant folded, and if it constant folds to something + // that isn't 0 or 1 (which indicate a potential logical operation that + // happened to fold to true/false) then warn. + // Parens on the RHS are ignored. + Expr::EvalResult Result; + if (rex.get()->Evaluate(Result, Context) && !Result.HasSideEffects) + if ((getLangOptions().Bool && !rex.get()->getType()->isBooleanType()) || + (Result.Val.getInt() != 0 && Result.Val.getInt() != 1)) { + Diag(Loc, diag::warn_logical_instead_of_bitwise) + << rex.get()->getSourceRange() + << (Opc == BO_LAnd ? "&&" : "||") + << (Opc == BO_LAnd ? "&" : "|"); + } + } + + if (!Context.getLangOptions().CPlusPlus) { + lex = UsualUnaryConversions(lex.take()); + if (lex.isInvalid()) + return QualType(); + + rex = UsualUnaryConversions(rex.take()); + if (rex.isInvalid()) + return QualType(); + + if (!lex.get()->getType()->isScalarType() || !rex.get()->getType()->isScalarType()) + return InvalidOperands(Loc, lex, rex); + + return Context.IntTy; + } + + // The following is safe because we only use this method for + // non-overloadable operands. + + // C++ [expr.log.and]p1 + // C++ [expr.log.or]p1 + // The operands are both contextually converted to type bool. + ExprResult lexRes = PerformContextuallyConvertToBool(lex.get()); + if (lexRes.isInvalid()) + return InvalidOperands(Loc, lex, rex); + lex = move(lexRes); + + ExprResult rexRes = PerformContextuallyConvertToBool(rex.get()); + if (rexRes.isInvalid()) + return InvalidOperands(Loc, lex, rex); + rex = move(rexRes); + + // C++ [expr.log.and]p2 + // C++ [expr.log.or]p2 + // The result is a bool. + return Context.BoolTy; +} + +/// IsReadonlyProperty - Verify that otherwise a valid l-value expression +/// is a read-only property; return true if so. A readonly property expression +/// depends on various declarations and thus must be treated specially. +/// +static bool IsReadonlyProperty(Expr *E, Sema &S) { + if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { + const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); + if (PropExpr->isImplicitProperty()) return false; + + ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); + QualType BaseType = PropExpr->isSuperReceiver() ? + PropExpr->getSuperReceiverType() : + PropExpr->getBase()->getType(); + + if (const ObjCObjectPointerType *OPT = + BaseType->getAsObjCInterfacePointerType()) + if (ObjCInterfaceDecl *IFace = OPT->getInterfaceDecl()) + if (S.isPropertyReadonly(PDecl, IFace)) + return true; + } + return false; +} + +static bool IsConstProperty(Expr *E, Sema &S) { + if (E->getStmtClass() == Expr::ObjCPropertyRefExprClass) { + const ObjCPropertyRefExpr* PropExpr = cast<ObjCPropertyRefExpr>(E); + if (PropExpr->isImplicitProperty()) return false; + + ObjCPropertyDecl *PDecl = PropExpr->getExplicitProperty(); + QualType T = PDecl->getType(); + if (T->isReferenceType()) + T = T->getAs<ReferenceType>()->getPointeeType(); + CanQualType CT = S.Context.getCanonicalType(T); + return CT.isConstQualified(); + } + return false; +} + +static bool IsReadonlyMessage(Expr *E, Sema &S) { + if (E->getStmtClass() != Expr::MemberExprClass) + return false; + const MemberExpr *ME = cast<MemberExpr>(E); + NamedDecl *Member = ME->getMemberDecl(); + if (isa<FieldDecl>(Member)) { + Expr *Base = ME->getBase()->IgnoreParenImpCasts(); + if (Base->getStmtClass() != Expr::ObjCMessageExprClass) + return false; + return cast<ObjCMessageExpr>(Base)->getMethodDecl() != 0; + } + return false; +} + +/// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not, +/// emit an error and return true. If so, return false. +static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { + SourceLocation OrigLoc = Loc; + Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(S.Context, + &Loc); + if (IsLV == Expr::MLV_Valid && IsReadonlyProperty(E, S)) + IsLV = Expr::MLV_ReadonlyProperty; + else if (Expr::MLV_ConstQualified && IsConstProperty(E, S)) + IsLV = Expr::MLV_Valid; + else if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) + IsLV = Expr::MLV_InvalidMessageExpression; + if (IsLV == Expr::MLV_Valid) + return false; + + unsigned Diag = 0; + bool NeedType = false; + switch (IsLV) { // C99 6.5.16p2 + case Expr::MLV_ConstQualified: Diag = diag::err_typecheck_assign_const; break; + case Expr::MLV_ArrayType: + Diag = diag::err_typecheck_array_not_modifiable_lvalue; + NeedType = true; + break; + case Expr::MLV_NotObjectType: + Diag = diag::err_typecheck_non_object_not_modifiable_lvalue; + NeedType = true; + break; + case Expr::MLV_LValueCast: + Diag = diag::err_typecheck_lvalue_casts_not_supported; + break; + case Expr::MLV_Valid: + llvm_unreachable("did not take early return for MLV_Valid"); + case Expr::MLV_InvalidExpression: + case Expr::MLV_MemberFunction: + case Expr::MLV_ClassTemporary: + Diag = diag::err_typecheck_expression_not_modifiable_lvalue; + break; + case Expr::MLV_IncompleteType: + case Expr::MLV_IncompleteVoidType: + return S.RequireCompleteType(Loc, E->getType(), + S.PDiag(diag::err_typecheck_incomplete_type_not_modifiable_lvalue) + << E->getSourceRange()); + case Expr::MLV_DuplicateVectorComponents: + Diag = diag::err_typecheck_duplicate_vector_components_not_mlvalue; + break; + case Expr::MLV_NotBlockQualified: + Diag = diag::err_block_decl_ref_not_modifiable_lvalue; + break; + case Expr::MLV_ReadonlyProperty: + Diag = diag::error_readonly_property_assignment; + break; + case Expr::MLV_NoSetterProperty: + Diag = diag::error_nosetter_property_assignment; + break; + case Expr::MLV_InvalidMessageExpression: + Diag = diag::error_readonly_message_assignment; + break; + case Expr::MLV_SubObjCPropertySetting: + Diag = diag::error_no_subobject_property_setting; + break; + } + + SourceRange Assign; + if (Loc != OrigLoc) + Assign = SourceRange(OrigLoc, OrigLoc); + if (NeedType) + S.Diag(Loc, Diag) << E->getType() << E->getSourceRange() << Assign; + else + S.Diag(Loc, Diag) << E->getSourceRange() << Assign; + return true; +} + + + +// C99 6.5.16.1 +QualType Sema::CheckAssignmentOperands(Expr *LHS, ExprResult &RHS, + SourceLocation Loc, + QualType CompoundType) { + // Verify that LHS is a modifiable lvalue, and emit error if not. + if (CheckForModifiableLvalue(LHS, Loc, *this)) + return QualType(); + + QualType LHSType = LHS->getType(); + QualType RHSType = CompoundType.isNull() ? RHS.get()->getType() : CompoundType; + AssignConvertType ConvTy; + if (CompoundType.isNull()) { + QualType LHSTy(LHSType); + // Simple assignment "x = y". + if (LHS->getObjectKind() == OK_ObjCProperty) { + ExprResult LHSResult = Owned(LHS); + ConvertPropertyForLValue(LHSResult, RHS, LHSTy); + if (LHSResult.isInvalid()) + return QualType(); + LHS = LHSResult.take(); + } + ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); + if (RHS.isInvalid()) + return QualType(); + // Special case of NSObject attributes on c-style pointer types. + if (ConvTy == IncompatiblePointer && + ((Context.isObjCNSObjectType(LHSType) && + RHSType->isObjCObjectPointerType()) || + (Context.isObjCNSObjectType(RHSType) && + LHSType->isObjCObjectPointerType()))) + ConvTy = Compatible; + + if (ConvTy == Compatible && + getLangOptions().ObjCNonFragileABI && + LHSType->isObjCObjectType()) + Diag(Loc, diag::err_assignment_requires_nonfragile_object) + << LHSType; + + // If the RHS is a unary plus or minus, check to see if they = and + are + // right next to each other. If so, the user may have typo'd "x =+ 4" + // instead of "x += 4". + Expr *RHSCheck = RHS.get(); + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RHSCheck)) + RHSCheck = ICE->getSubExpr(); + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(RHSCheck)) { + if ((UO->getOpcode() == UO_Plus || + UO->getOpcode() == UO_Minus) && + Loc.isFileID() && UO->getOperatorLoc().isFileID() && + // Only if the two operators are exactly adjacent. + Loc.getFileLocWithOffset(1) == UO->getOperatorLoc() && + // And there is a space or other character before the subexpr of the + // unary +/-. We don't want to warn on "x=-1". + Loc.getFileLocWithOffset(2) != UO->getSubExpr()->getLocStart() && + UO->getSubExpr()->getLocStart().isFileID()) { + Diag(Loc, diag::warn_not_compound_assign) + << (UO->getOpcode() == UO_Plus ? "+" : "-") + << SourceRange(UO->getOperatorLoc(), UO->getOperatorLoc()); + } + } + } else { + // Compound assignment "x += y" + ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType); + } + + if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType, + RHS.get(), AA_Assigning)) + return QualType(); + + CheckForNullPointerDereference(*this, LHS); + // Check for trivial buffer overflows. + CheckArrayAccess(LHS->IgnoreParenCasts()); + + // C99 6.5.16p3: The type of an assignment expression is the type of the + // left operand unless the left operand has qualified type, in which case + // it is the unqualified version of the type of the left operand. + // C99 6.5.16.1p2: In simple assignment, the value of the right operand + // is converted to the type of the assignment expression (above). + // C++ 5.17p1: the type of the assignment expression is that of its left + // operand. + return (getLangOptions().CPlusPlus + ? LHSType : LHSType.getUnqualifiedType()); +} + +// C99 6.5.17 +static QualType CheckCommaOperands(Sema &S, ExprResult &LHS, ExprResult &RHS, + SourceLocation Loc) { + S.DiagnoseUnusedExprResult(LHS.get()); + + LHS = S.CheckPlaceholderExpr(LHS.take()); + RHS = S.CheckPlaceholderExpr(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + + // C's comma performs lvalue conversion (C99 6.3.2.1) on both its + // operands, but not unary promotions. + // C++'s comma does not do any conversions at all (C++ [expr.comma]p1). + + // So we treat the LHS as a ignored value, and in C++ we allow the + // containing site to determine what should be done with the RHS. + LHS = S.IgnoredValueConversions(LHS.take()); + if (LHS.isInvalid()) + return QualType(); + + if (!S.getLangOptions().CPlusPlus) { + RHS = S.DefaultFunctionArrayLvalueConversion(RHS.take()); + if (RHS.isInvalid()) + return QualType(); + if (!RHS.get()->getType()->isVoidType()) + S.RequireCompleteType(Loc, RHS.get()->getType(), diag::err_incomplete_type); + } + + return RHS.get()->getType(); +} + +/// CheckIncrementDecrementOperand - unlike most "Check" methods, this routine +/// doesn't need to call UsualUnaryConversions or UsualArithmeticConversions. +static QualType CheckIncrementDecrementOperand(Sema &S, Expr *Op, + ExprValueKind &VK, + SourceLocation OpLoc, + bool isInc, bool isPrefix) { + if (Op->isTypeDependent()) + return S.Context.DependentTy; + + QualType ResType = Op->getType(); + assert(!ResType.isNull() && "no type for increment/decrement expression"); + + if (S.getLangOptions().CPlusPlus && ResType->isBooleanType()) { + // Decrement of bool is not allowed. + if (!isInc) { + S.Diag(OpLoc, diag::err_decrement_bool) << Op->getSourceRange(); + return QualType(); + } + // Increment of bool sets it to true, but is deprecated. + S.Diag(OpLoc, diag::warn_increment_bool) << Op->getSourceRange(); + } else if (ResType->isRealType()) { + // OK! + } else if (ResType->isAnyPointerType()) { + QualType PointeeTy = ResType->getPointeeType(); + + // C99 6.5.2.4p2, 6.5.6p2 + if (PointeeTy->isVoidType()) { + if (S.getLangOptions().CPlusPlus) { + S.Diag(OpLoc, diag::err_typecheck_pointer_arith_void_type) + << Op->getSourceRange(); + return QualType(); + } + + // Pointer to void is a GNU extension in C. + S.Diag(OpLoc, diag::ext_gnu_void_ptr) << Op->getSourceRange(); + } else if (PointeeTy->isFunctionType()) { + if (S.getLangOptions().CPlusPlus) { + S.Diag(OpLoc, diag::err_typecheck_pointer_arith_function_type) + << Op->getType() << Op->getSourceRange(); + return QualType(); + } + + S.Diag(OpLoc, diag::ext_gnu_ptr_func_arith) + << ResType << Op->getSourceRange(); + } else if (S.RequireCompleteType(OpLoc, PointeeTy, + S.PDiag(diag::err_typecheck_arithmetic_incomplete_type) + << Op->getSourceRange() + << ResType)) + return QualType(); + // Diagnose bad cases where we step over interface counts. + else if (PointeeTy->isObjCObjectType() && S.LangOpts.ObjCNonFragileABI) { + S.Diag(OpLoc, diag::err_arithmetic_nonfragile_interface) + << PointeeTy << Op->getSourceRange(); + return QualType(); + } + } else if (ResType->isAnyComplexType()) { + // C99 does not support ++/-- on complex types, we allow as an extension. + S.Diag(OpLoc, diag::ext_integer_increment_complex) + << ResType << Op->getSourceRange(); + } else if (ResType->isPlaceholderType()) { + ExprResult PR = S.CheckPlaceholderExpr(Op); + if (PR.isInvalid()) return QualType(); + return CheckIncrementDecrementOperand(S, PR.take(), VK, OpLoc, + isInc, isPrefix); + } else if (S.getLangOptions().AltiVec && ResType->isVectorType()) { + // OK! ( C/C++ Language Extensions for CBEA(Version 2.6) 10.3 ) + } else { + S.Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement) + << ResType << int(isInc) << Op->getSourceRange(); + return QualType(); + } + // At this point, we know we have a real, complex or pointer type. + // Now make sure the operand is a modifiable lvalue. + if (CheckForModifiableLvalue(Op, OpLoc, S)) + return QualType(); + // In C++, a prefix increment is the same type as the operand. Otherwise + // (in C or with postfix), the increment is the unqualified type of the + // operand. + if (isPrefix && S.getLangOptions().CPlusPlus) { + VK = VK_LValue; + return ResType; + } else { + VK = VK_RValue; + return ResType.getUnqualifiedType(); + } +} + +ExprResult Sema::ConvertPropertyForRValue(Expr *E) { + assert(E->getValueKind() == VK_LValue && + E->getObjectKind() == OK_ObjCProperty); + const ObjCPropertyRefExpr *PRE = E->getObjCProperty(); + + QualType T = E->getType(); + QualType ReceiverType; + if (PRE->isObjectReceiver()) + ReceiverType = PRE->getBase()->getType(); + else if (PRE->isSuperReceiver()) + ReceiverType = PRE->getSuperReceiverType(); + else + ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver()); + + ExprValueKind VK = VK_RValue; + if (PRE->isImplicitProperty()) { + if (ObjCMethodDecl *GetterMethod = + PRE->getImplicitPropertyGetter()) { + T = getMessageSendResultType(ReceiverType, GetterMethod, + PRE->isClassReceiver(), + PRE->isSuperReceiver()); + VK = Expr::getValueKindForType(GetterMethod->getResultType()); + } + else { + Diag(PRE->getLocation(), diag::err_getter_not_found) + << PRE->getBase()->getType(); + } + } + + E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, + E, 0, VK); + + ExprResult Result = MaybeBindToTemporary(E); + if (!Result.isInvalid()) + E = Result.take(); + + return Owned(E); +} + +void Sema::ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, QualType &LHSTy) { + assert(LHS.get()->getValueKind() == VK_LValue && + LHS.get()->getObjectKind() == OK_ObjCProperty); + const ObjCPropertyRefExpr *PropRef = LHS.get()->getObjCProperty(); + + if (PropRef->isImplicitProperty()) { + // If using property-dot syntax notation for assignment, and there is a + // setter, RHS expression is being passed to the setter argument. So, + // type conversion (and comparison) is RHS to setter's argument type. + if (const ObjCMethodDecl *SetterMD = PropRef->getImplicitPropertySetter()) { + ObjCMethodDecl::param_iterator P = SetterMD->param_begin(); + LHSTy = (*P)->getType(); + + // Otherwise, if the getter returns an l-value, just call that. + } else { + QualType Result = PropRef->getImplicitPropertyGetter()->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(Result); + if (VK == VK_LValue) { + LHS = ImplicitCastExpr::Create(Context, LHS.get()->getType(), + CK_GetObjCProperty, LHS.take(), 0, VK); + return; + } + } + } + + if (getLangOptions().CPlusPlus && LHSTy->isRecordType()) { + InitializedEntity Entity = + InitializedEntity::InitializeParameter(Context, LHSTy); + ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), RHS); + if (!ArgE.isInvalid()) + RHS = ArgE; + } +} + + +/// getPrimaryDecl - Helper function for CheckAddressOfOperand(). +/// This routine allows us to typecheck complex/recursive expressions +/// where the declaration is needed for type checking. We only need to +/// handle cases when the expression references a function designator +/// or is an lvalue. Here are some examples: +/// - &(x) => x +/// - &*****f => f for f a function designator. +/// - &s.xx => s +/// - &s.zz[1].yy -> s, if zz is an array +/// - *(x + 1) -> x, if x is an array +/// - &"123"[2] -> 0 +/// - & __real__ x -> x +static ValueDecl *getPrimaryDecl(Expr *E) { + switch (E->getStmtClass()) { + case Stmt::DeclRefExprClass: + return cast<DeclRefExpr>(E)->getDecl(); + case Stmt::MemberExprClass: + // If this is an arrow operator, the address is an offset from + // the base's value, so the object the base refers to is + // irrelevant. + if (cast<MemberExpr>(E)->isArrow()) + return 0; + // Otherwise, the expression refers to a part of the base + return getPrimaryDecl(cast<MemberExpr>(E)->getBase()); + case Stmt::ArraySubscriptExprClass: { + // FIXME: This code shouldn't be necessary! We should catch the implicit + // promotion of register arrays earlier. + Expr* Base = cast<ArraySubscriptExpr>(E)->getBase(); + if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(Base)) { + if (ICE->getSubExpr()->getType()->isArrayType()) + return getPrimaryDecl(ICE->getSubExpr()); + } + return 0; + } + case Stmt::UnaryOperatorClass: { + UnaryOperator *UO = cast<UnaryOperator>(E); + + switch(UO->getOpcode()) { + case UO_Real: + case UO_Imag: + case UO_Extension: + return getPrimaryDecl(UO->getSubExpr()); + default: + return 0; + } + } + case Stmt::ParenExprClass: + return getPrimaryDecl(cast<ParenExpr>(E)->getSubExpr()); + case Stmt::ImplicitCastExprClass: + // If the result of an implicit cast is an l-value, we care about + // the sub-expression; otherwise, the result here doesn't matter. + return getPrimaryDecl(cast<ImplicitCastExpr>(E)->getSubExpr()); + default: + return 0; + } +} + +/// CheckAddressOfOperand - The operand of & must be either a function +/// designator or an lvalue designating an object. If it is an lvalue, the +/// object cannot be declared with storage class register or be a bit field. +/// Note: The usual conversions are *not* applied to the operand of the & +/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue. +/// In C++, the operand might be an overloaded function name, in which case +/// we allow the '&' but retain the overloaded-function type. +static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp, + SourceLocation OpLoc) { + if (OrigOp->isTypeDependent()) + return S.Context.DependentTy; + if (OrigOp->getType() == S.Context.OverloadTy) + return S.Context.OverloadTy; + if (OrigOp->getType() == S.Context.UnknownAnyTy) + return S.Context.UnknownAnyTy; + if (OrigOp->getType() == S.Context.BoundMemberTy) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp->getSourceRange(); + return QualType(); + } + + assert(!OrigOp->getType()->isPlaceholderType()); + + // Make sure to ignore parentheses in subsequent checks + Expr *op = OrigOp->IgnoreParens(); + + if (S.getLangOptions().C99) { + // Implement C99-only parts of addressof rules. + if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) { + if (uOp->getOpcode() == UO_Deref) + // Per C99 6.5.3.2, the address of a deref always returns a valid result + // (assuming the deref expression is valid). + return uOp->getSubExpr()->getType(); + } + // Technically, there should be a check for array subscript + // expressions here, but the result of one is always an lvalue anyway. + } + ValueDecl *dcl = getPrimaryDecl(op); + Expr::LValueClassification lval = op->ClassifyLValue(S.Context); + + if (lval == Expr::LV_ClassTemporary) { + bool sfinae = S.isSFINAEContext(); + S.Diag(OpLoc, sfinae ? diag::err_typecheck_addrof_class_temporary + : diag::ext_typecheck_addrof_class_temporary) + << op->getType() << op->getSourceRange(); + if (sfinae) + return QualType(); + } else if (isa<ObjCSelectorExpr>(op)) { + return S.Context.getPointerType(op->getType()); + } else if (lval == Expr::LV_MemberFunction) { + // If it's an instance method, make a member pointer. + // The expression must have exactly the form &A::foo. + + // If the underlying expression isn't a decl ref, give up. + if (!isa<DeclRefExpr>(op)) { + S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function) + << OrigOp->getSourceRange(); + return QualType(); + } + DeclRefExpr *DRE = cast<DeclRefExpr>(op); + CXXMethodDecl *MD = cast<CXXMethodDecl>(DRE->getDecl()); + + // The id-expression was parenthesized. + if (OrigOp != DRE) { + S.Diag(OpLoc, diag::err_parens_pointer_member_function) + << OrigOp->getSourceRange(); + + // The method was named without a qualifier. + } else if (!DRE->getQualifier()) { + S.Diag(OpLoc, diag::err_unqualified_pointer_member_function) + << op->getSourceRange(); + } + + return S.Context.getMemberPointerType(op->getType(), + S.Context.getTypeDeclType(MD->getParent()).getTypePtr()); + } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { + // C99 6.5.3.2p1 + // The operand must be either an l-value or a function designator + if (!op->getType()->isFunctionType()) { + // FIXME: emit more specific diag... + S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) + << op->getSourceRange(); + return QualType(); + } + } else if (op->getObjectKind() == OK_BitField) { // C99 6.5.3.2p1 + // The operand cannot be a bit-field + S.Diag(OpLoc, diag::err_typecheck_address_of) + << "bit-field" << op->getSourceRange(); + return QualType(); + } else if (op->getObjectKind() == OK_VectorComponent) { + // The operand cannot be an element of a vector + S.Diag(OpLoc, diag::err_typecheck_address_of) + << "vector element" << op->getSourceRange(); + return QualType(); + } else if (op->getObjectKind() == OK_ObjCProperty) { + // cannot take address of a property expression. + S.Diag(OpLoc, diag::err_typecheck_address_of) + << "property expression" << op->getSourceRange(); + return QualType(); + } else if (dcl) { // C99 6.5.3.2p1 + // We have an lvalue with a decl. Make sure the decl is not declared + // with the register storage-class specifier. + if (const VarDecl *vd = dyn_cast<VarDecl>(dcl)) { + // in C++ it is not error to take address of a register + // variable (c++03 7.1.1P3) + if (vd->getStorageClass() == SC_Register && + !S.getLangOptions().CPlusPlus) { + S.Diag(OpLoc, diag::err_typecheck_address_of) + << "register variable" << op->getSourceRange(); + return QualType(); + } + } else if (isa<FunctionTemplateDecl>(dcl)) { + return S.Context.OverloadTy; + } else if (isa<FieldDecl>(dcl) || isa<IndirectFieldDecl>(dcl)) { + // Okay: we can take the address of a field. + // Could be a pointer to member, though, if there is an explicit + // scope qualifier for the class. + if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) { + DeclContext *Ctx = dcl->getDeclContext(); + if (Ctx && Ctx->isRecord()) { + if (dcl->getType()->isReferenceType()) { + S.Diag(OpLoc, + diag::err_cannot_form_pointer_to_member_of_reference_type) + << dcl->getDeclName() << dcl->getType(); + return QualType(); + } + + while (cast<RecordDecl>(Ctx)->isAnonymousStructOrUnion()) + Ctx = Ctx->getParent(); + return S.Context.getMemberPointerType(op->getType(), + S.Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr()); + } + } + } else if (!isa<FunctionDecl>(dcl)) + assert(0 && "Unknown/unexpected decl type"); + } + + if (lval == Expr::LV_IncompleteVoidType) { + // Taking the address of a void variable is technically illegal, but we + // allow it in cases which are otherwise valid. + // Example: "extern void x; void* y = &x;". + S.Diag(OpLoc, diag::ext_typecheck_addrof_void) << op->getSourceRange(); + } + + // If the operand has type "type", the result has type "pointer to type". + if (op->getType()->isObjCObjectType()) + return S.Context.getObjCObjectPointerType(op->getType()); + return S.Context.getPointerType(op->getType()); +} + +/// CheckIndirectionOperand - Type check unary indirection (prefix '*'). +static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK, + SourceLocation OpLoc) { + if (Op->isTypeDependent()) + return S.Context.DependentTy; + + ExprResult ConvResult = S.UsualUnaryConversions(Op); + if (ConvResult.isInvalid()) + return QualType(); + Op = ConvResult.take(); + QualType OpTy = Op->getType(); + QualType Result; + + if (isa<CXXReinterpretCastExpr>(Op)) { + QualType OpOrigType = Op->IgnoreParenCasts()->getType(); + S.CheckCompatibleReinterpretCast(OpOrigType, OpTy, /*IsDereference*/true, + Op->getSourceRange()); + } + + // Note that per both C89 and C99, indirection is always legal, even if OpTy + // is an incomplete type or void. It would be possible to warn about + // dereferencing a void pointer, but it's completely well-defined, and such a + // warning is unlikely to catch any mistakes. + if (const PointerType *PT = OpTy->getAs<PointerType>()) + Result = PT->getPointeeType(); + else if (const ObjCObjectPointerType *OPT = + OpTy->getAs<ObjCObjectPointerType>()) + Result = OPT->getPointeeType(); + else { + ExprResult PR = S.CheckPlaceholderExpr(Op); + if (PR.isInvalid()) return QualType(); + if (PR.take() != Op) + return CheckIndirectionOperand(S, PR.take(), VK, OpLoc); + } + + if (Result.isNull()) { + S.Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer) + << OpTy << Op->getSourceRange(); + return QualType(); + } + + // Dereferences are usually l-values... + VK = VK_LValue; + + // ...except that certain expressions are never l-values in C. + if (!S.getLangOptions().CPlusPlus && + IsCForbiddenLValueType(S.Context, Result)) + VK = VK_RValue; + + return Result; +} + +static inline BinaryOperatorKind ConvertTokenKindToBinaryOpcode( + tok::TokenKind Kind) { + BinaryOperatorKind Opc; + switch (Kind) { + default: assert(0 && "Unknown binop!"); + case tok::periodstar: Opc = BO_PtrMemD; break; + case tok::arrowstar: Opc = BO_PtrMemI; break; + case tok::star: Opc = BO_Mul; break; + case tok::slash: Opc = BO_Div; break; + case tok::percent: Opc = BO_Rem; break; + case tok::plus: Opc = BO_Add; break; + case tok::minus: Opc = BO_Sub; break; + case tok::lessless: Opc = BO_Shl; break; + case tok::greatergreater: Opc = BO_Shr; break; + case tok::lessequal: Opc = BO_LE; break; + case tok::less: Opc = BO_LT; break; + case tok::greaterequal: Opc = BO_GE; break; + case tok::greater: Opc = BO_GT; break; + case tok::exclaimequal: Opc = BO_NE; break; + case tok::equalequal: Opc = BO_EQ; break; + case tok::amp: Opc = BO_And; break; + case tok::caret: Opc = BO_Xor; break; + case tok::pipe: Opc = BO_Or; break; + case tok::ampamp: Opc = BO_LAnd; break; + case tok::pipepipe: Opc = BO_LOr; break; + case tok::equal: Opc = BO_Assign; break; + case tok::starequal: Opc = BO_MulAssign; break; + case tok::slashequal: Opc = BO_DivAssign; break; + case tok::percentequal: Opc = BO_RemAssign; break; + case tok::plusequal: Opc = BO_AddAssign; break; + case tok::minusequal: Opc = BO_SubAssign; break; + case tok::lesslessequal: Opc = BO_ShlAssign; break; + case tok::greatergreaterequal: Opc = BO_ShrAssign; break; + case tok::ampequal: Opc = BO_AndAssign; break; + case tok::caretequal: Opc = BO_XorAssign; break; + case tok::pipeequal: Opc = BO_OrAssign; break; + case tok::comma: Opc = BO_Comma; break; + } + return Opc; +} + +static inline UnaryOperatorKind ConvertTokenKindToUnaryOpcode( + tok::TokenKind Kind) { + UnaryOperatorKind Opc; + switch (Kind) { + default: assert(0 && "Unknown unary op!"); + case tok::plusplus: Opc = UO_PreInc; break; + case tok::minusminus: Opc = UO_PreDec; break; + case tok::amp: Opc = UO_AddrOf; break; + case tok::star: Opc = UO_Deref; break; + case tok::plus: Opc = UO_Plus; break; + case tok::minus: Opc = UO_Minus; break; + case tok::tilde: Opc = UO_Not; break; + case tok::exclaim: Opc = UO_LNot; break; + case tok::kw___real: Opc = UO_Real; break; + case tok::kw___imag: Opc = UO_Imag; break; + case tok::kw___extension__: Opc = UO_Extension; break; + } + return Opc; +} + +/// DiagnoseSelfAssignment - Emits a warning if a value is assigned to itself. +/// This warning is only emitted for builtin assignment operations. It is also +/// suppressed in the event of macro expansions. +static void DiagnoseSelfAssignment(Sema &S, Expr *lhs, Expr *rhs, + SourceLocation OpLoc) { + if (!S.ActiveTemplateInstantiations.empty()) + return; + if (OpLoc.isInvalid() || OpLoc.isMacroID()) + return; + lhs = lhs->IgnoreParenImpCasts(); + rhs = rhs->IgnoreParenImpCasts(); + const DeclRefExpr *LeftDeclRef = dyn_cast<DeclRefExpr>(lhs); + const DeclRefExpr *RightDeclRef = dyn_cast<DeclRefExpr>(rhs); + if (!LeftDeclRef || !RightDeclRef || + LeftDeclRef->getLocation().isMacroID() || + RightDeclRef->getLocation().isMacroID()) + return; + const ValueDecl *LeftDecl = + cast<ValueDecl>(LeftDeclRef->getDecl()->getCanonicalDecl()); + const ValueDecl *RightDecl = + cast<ValueDecl>(RightDeclRef->getDecl()->getCanonicalDecl()); + if (LeftDecl != RightDecl) + return; + if (LeftDecl->getType().isVolatileQualified()) + return; + if (const ReferenceType *RefTy = LeftDecl->getType()->getAs<ReferenceType>()) + if (RefTy->getPointeeType().isVolatileQualified()) + return; + + S.Diag(OpLoc, diag::warn_self_assignment) + << LeftDeclRef->getType() + << lhs->getSourceRange() << rhs->getSourceRange(); +} + +/// CreateBuiltinBinOp - Creates a new built-in binary operation with +/// operator @p Opc at location @c TokLoc. This routine only supports +/// built-in operations; ActOnBinOp handles overloaded operators. +ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *lhsExpr, Expr *rhsExpr) { + ExprResult lhs = Owned(lhsExpr), rhs = Owned(rhsExpr); + QualType ResultTy; // Result type of the binary operator. + // The following two variables are used for compound assignment operators + QualType CompLHSTy; // Type of LHS after promotions for computation + QualType CompResultTy; // Type of computation result + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + + // Check if a 'foo<int>' involved in a binary op, identifies a single + // function unambiguously (i.e. an lvalue ala 13.4) + // But since an assignment can trigger target based overload, exclude it in + // our blind search. i.e: + // template<class T> void f(); template<class T, class U> void f(U); + // f<int> == 0; // resolve f<int> blindly + // void (*p)(int); p = f<int>; // resolve f<int> using target + if (Opc != BO_Assign) { + ExprResult resolvedLHS = CheckPlaceholderExpr(lhs.get()); + if (!resolvedLHS.isUsable()) return ExprError(); + lhs = move(resolvedLHS); + + ExprResult resolvedRHS = CheckPlaceholderExpr(rhs.get()); + if (!resolvedRHS.isUsable()) return ExprError(); + rhs = move(resolvedRHS); + } + + switch (Opc) { + case BO_Assign: + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, QualType()); + if (getLangOptions().CPlusPlus && + lhs.get()->getObjectKind() != OK_ObjCProperty) { + VK = lhs.get()->getValueKind(); + OK = lhs.get()->getObjectKind(); + } + if (!ResultTy.isNull()) + DiagnoseSelfAssignment(*this, lhs.get(), rhs.get(), OpLoc); + break; + case BO_PtrMemD: + case BO_PtrMemI: + ResultTy = CheckPointerToMemberOperands(lhs, rhs, VK, OpLoc, + Opc == BO_PtrMemI); + break; + case BO_Mul: + case BO_Div: + ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, false, + Opc == BO_Div); + break; + case BO_Rem: + ResultTy = CheckRemainderOperands(lhs, rhs, OpLoc); + break; + case BO_Add: + ResultTy = CheckAdditionOperands(lhs, rhs, OpLoc); + break; + case BO_Sub: + ResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc); + break; + case BO_Shl: + case BO_Shr: + ResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc); + break; + case BO_LE: + case BO_LT: + case BO_GE: + case BO_GT: + ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, true); + break; + case BO_EQ: + case BO_NE: + ResultTy = CheckCompareOperands(lhs, rhs, OpLoc, Opc, false); + break; + case BO_And: + case BO_Xor: + case BO_Or: + ResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc); + break; + case BO_LAnd: + case BO_LOr: + ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc, Opc); + break; + case BO_MulAssign: + case BO_DivAssign: + CompResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc, true, + Opc == BO_DivAssign); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); + break; + case BO_RemAssign: + CompResultTy = CheckRemainderOperands(lhs, rhs, OpLoc, true); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); + break; + case BO_AddAssign: + CompResultTy = CheckAdditionOperands(lhs, rhs, OpLoc, &CompLHSTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); + break; + case BO_SubAssign: + CompResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc, &CompLHSTy); + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); + break; + case BO_ShlAssign: + case BO_ShrAssign: + CompResultTy = CheckShiftOperands(lhs, rhs, OpLoc, Opc, true); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); + break; + case BO_AndAssign: + case BO_XorAssign: + case BO_OrAssign: + CompResultTy = CheckBitwiseOperands(lhs, rhs, OpLoc, true); + CompLHSTy = CompResultTy; + if (!CompResultTy.isNull() && !lhs.isInvalid() && !rhs.isInvalid()) + ResultTy = CheckAssignmentOperands(lhs.get(), rhs, OpLoc, CompResultTy); + break; + case BO_Comma: + ResultTy = CheckCommaOperands(*this, lhs, rhs, OpLoc); + if (getLangOptions().CPlusPlus && !rhs.isInvalid()) { + VK = rhs.get()->getValueKind(); + OK = rhs.get()->getObjectKind(); + } + break; + } + if (ResultTy.isNull() || lhs.isInvalid() || rhs.isInvalid()) + return ExprError(); + if (CompResultTy.isNull()) + return Owned(new (Context) BinaryOperator(lhs.take(), rhs.take(), Opc, + ResultTy, VK, OK, OpLoc)); + if (getLangOptions().CPlusPlus && lhs.get()->getObjectKind() != OK_ObjCProperty) { + VK = VK_LValue; + OK = lhs.get()->getObjectKind(); + } + return Owned(new (Context) CompoundAssignOperator(lhs.take(), rhs.take(), Opc, + ResultTy, VK, OK, CompLHSTy, + CompResultTy, OpLoc)); +} + +/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison +/// operators are mixed in a way that suggests that the programmer forgot that +/// comparison operators have higher precedence. The most typical example of +/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1". +static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, + SourceLocation OpLoc,Expr *lhs,Expr *rhs){ + typedef BinaryOperator BinOp; + BinOp::Opcode lhsopc = static_cast<BinOp::Opcode>(-1), + rhsopc = static_cast<BinOp::Opcode>(-1); + if (BinOp *BO = dyn_cast<BinOp>(lhs)) + lhsopc = BO->getOpcode(); + if (BinOp *BO = dyn_cast<BinOp>(rhs)) + rhsopc = BO->getOpcode(); + + // Subs are not binary operators. + if (lhsopc == -1 && rhsopc == -1) + return; + + // Bitwise operations are sometimes used as eager logical ops. + // Don't diagnose this. + if ((BinOp::isComparisonOp(lhsopc) || BinOp::isBitwiseOp(lhsopc)) && + (BinOp::isComparisonOp(rhsopc) || BinOp::isBitwiseOp(rhsopc))) + return; + + if (BinOp::isComparisonOp(lhsopc)) + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::warn_precedence_bitwise_rel) + << SourceRange(lhs->getLocStart(), OpLoc) + << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc), + Self.PDiag(diag::note_precedence_bitwise_silence) + << BinOp::getOpcodeStr(lhsopc), + lhs->getSourceRange(), + Self.PDiag(diag::note_precedence_bitwise_first) + << BinOp::getOpcodeStr(Opc), + SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd())); + else if (BinOp::isComparisonOp(rhsopc)) + SuggestParentheses(Self, OpLoc, + Self.PDiag(diag::warn_precedence_bitwise_rel) + << SourceRange(OpLoc, rhs->getLocEnd()) + << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc), + Self.PDiag(diag::note_precedence_bitwise_silence) + << BinOp::getOpcodeStr(rhsopc), + rhs->getSourceRange(), + Self.PDiag(diag::note_precedence_bitwise_first) + << BinOp::getOpcodeStr(Opc), + SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart())); +} + +/// \brief It accepts a '&&' expr that is inside a '||' one. +/// Emit a diagnostic together with a fixit hint that wraps the '&&' expression +/// in parentheses. +static void +EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc, + BinaryOperator *Bop) { + assert(Bop->getOpcode() == BO_LAnd); + SuggestParentheses(Self, Bop->getOperatorLoc(), + Self.PDiag(diag::warn_logical_and_in_logical_or) + << Bop->getSourceRange() << OpLoc, + Self.PDiag(diag::note_logical_and_in_logical_or_silence), + Bop->getSourceRange(), + Self.PDiag(0), SourceRange()); +} + +/// \brief Returns true if the given expression can be evaluated as a constant +/// 'true'. +static bool EvaluatesAsTrue(Sema &S, Expr *E) { + bool Res; + return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res; +} + +/// \brief Returns true if the given expression can be evaluated as a constant +/// 'false'. +static bool EvaluatesAsFalse(Sema &S, Expr *E) { + bool Res; + return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res; +} + +/// \brief Look for '&&' in the left hand of a '||' expr. +static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc, + Expr *OrLHS, Expr *OrRHS) { + if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrLHS)) { + if (Bop->getOpcode() == BO_LAnd) { + // If it's "a && b || 0" don't warn since the precedence doesn't matter. + if (EvaluatesAsFalse(S, OrRHS)) + return; + // If it's "1 && a || b" don't warn since the precedence doesn't matter. + if (!EvaluatesAsTrue(S, Bop->getLHS())) + return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop); + } else if (Bop->getOpcode() == BO_LOr) { + if (BinaryOperator *RBop = dyn_cast<BinaryOperator>(Bop->getRHS())) { + // If it's "a || b && 1 || c" we didn't warn earlier for + // "a || b && 1", but warn now. + if (RBop->getOpcode() == BO_LAnd && EvaluatesAsTrue(S, RBop->getRHS())) + return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, RBop); + } + } + } +} + +/// \brief Look for '&&' in the right hand of a '||' expr. +static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc, + Expr *OrLHS, Expr *OrRHS) { + if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrRHS)) { + if (Bop->getOpcode() == BO_LAnd) { + // If it's "0 || a && b" don't warn since the precedence doesn't matter. + if (EvaluatesAsFalse(S, OrLHS)) + return; + // If it's "a || b && 1" don't warn since the precedence doesn't matter. + if (!EvaluatesAsTrue(S, Bop->getRHS())) + return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop); + } + } +} + +/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky +/// precedence. +static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, + SourceLocation OpLoc, Expr *lhs, Expr *rhs){ + // Diagnose "arg1 'bitwise' arg2 'eq' arg3". + if (BinaryOperator::isBitwiseOp(Opc)) + return DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs); + + // Warn about arg1 || arg2 && arg3, as GCC 4.3+ does. + // We don't warn for 'assert(a || b && "bad")' since this is safe. + if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) { + DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, lhs, rhs); + DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, lhs, rhs); + } +} + +// Binary Operators. 'Tok' is the token for the operator. +ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, + tok::TokenKind Kind, + Expr *lhs, Expr *rhs) { + BinaryOperatorKind Opc = ConvertTokenKindToBinaryOpcode(Kind); + assert((lhs != 0) && "ActOnBinOp(): missing left expression"); + assert((rhs != 0) && "ActOnBinOp(): missing right expression"); + + // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0" + DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs); + + return BuildBinOp(S, TokLoc, Opc, lhs, rhs); +} + +ExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *lhs, Expr *rhs) { + if (getLangOptions().CPlusPlus) { + bool UseBuiltinOperator; + + if (lhs->isTypeDependent() || rhs->isTypeDependent()) { + UseBuiltinOperator = false; + } else if (Opc == BO_Assign && lhs->getObjectKind() == OK_ObjCProperty) { + UseBuiltinOperator = true; + } else { + UseBuiltinOperator = !lhs->getType()->isOverloadableType() && + !rhs->getType()->isOverloadableType(); + } + + if (!UseBuiltinOperator) { + // Find all of the overloaded operators visible from this + // point. We perform both an operator-name lookup from the local + // scope and an argument-dependent lookup based on the types of + // the arguments. + UnresolvedSet<16> Functions; + OverloadedOperatorKind OverOp + = BinaryOperator::getOverloadedOperator(Opc); + if (S && OverOp != OO_None) + LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(), + Functions); + + // Build the (potentially-overloaded, potentially-dependent) + // binary operation. + return CreateOverloadedBinOp(OpLoc, Opc, Functions, lhs, rhs); + } + } + + // Build a built-in binary operation. + return CreateBuiltinBinOp(OpLoc, Opc, lhs, rhs); +} + +ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, + UnaryOperatorKind Opc, + Expr *InputExpr) { + ExprResult Input = Owned(InputExpr); + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType resultType; + switch (Opc) { + case UO_PreInc: + case UO_PreDec: + case UO_PostInc: + case UO_PostDec: + resultType = CheckIncrementDecrementOperand(*this, Input.get(), VK, OpLoc, + Opc == UO_PreInc || + Opc == UO_PostInc, + Opc == UO_PreInc || + Opc == UO_PreDec); + break; + case UO_AddrOf: + resultType = CheckAddressOfOperand(*this, Input.get(), OpLoc); + break; + case UO_Deref: { + ExprResult resolved = CheckPlaceholderExpr(Input.get()); + if (!resolved.isUsable()) return ExprError(); + Input = move(resolved); + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc); + break; + } + case UO_Plus: + case UO_Minus: + Input = UsualUnaryConversions(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); + if (resultType->isDependentType()) + break; + if (resultType->isArithmeticType() || // C99 6.5.3.3p1 + resultType->isVectorType()) + break; + else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6-7 + resultType->isEnumeralType()) + break; + else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6 + Opc == UO_Plus && + resultType->isPointerType()) + break; + else if (resultType->isPlaceholderType()) { + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); + } + + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + + case UO_Not: // bitwise complement + Input = UsualUnaryConversions(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); + if (resultType->isDependentType()) + break; + // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. + if (resultType->isComplexType() || resultType->isComplexIntegerType()) + // C99 does not support '~' for complex conjugation. + Diag(OpLoc, diag::ext_integer_complement_complex) + << resultType << Input.get()->getSourceRange(); + else if (resultType->hasIntegerRepresentation()) + break; + else if (resultType->isPlaceholderType()) { + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + break; + + case UO_LNot: // logical negation + // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). + Input = DefaultFunctionArrayLvalueConversion(Input.take()); + if (Input.isInvalid()) return ExprError(); + resultType = Input.get()->getType(); + if (resultType->isDependentType()) + break; + if (resultType->isScalarType()) { + // C99 6.5.3.3p1: ok, fallthrough; + if (Context.getLangOptions().CPlusPlus) { + // C++03 [expr.unary.op]p8, C++0x [expr.unary.op]p9: + // operand contextually converted to bool. + Input = ImpCastExprToType(Input.take(), Context.BoolTy, + ScalarTypeToBooleanCastKind(resultType)); + } + } else if (resultType->isPlaceholderType()) { + Input = CheckPlaceholderExpr(Input.take()); + if (Input.isInvalid()) return ExprError(); + return CreateBuiltinUnaryOp(OpLoc, Opc, Input.take()); + } else { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + + // LNot always has type int. C99 6.5.3.3p5. + // In C++, it's bool. C++ 5.3.1p8 + resultType = Context.getLogicalOperationType(); + break; + case UO_Real: + case UO_Imag: + resultType = CheckRealImagOperand(*this, Input, OpLoc, Opc == UO_Real); + // _Real and _Imag map ordinary l-values into ordinary l-values. + if (Input.isInvalid()) return ExprError(); + if (Input.get()->getValueKind() != VK_RValue && + Input.get()->getObjectKind() == OK_Ordinary) + VK = Input.get()->getValueKind(); + break; + case UO_Extension: + resultType = Input.get()->getType(); + VK = Input.get()->getValueKind(); + OK = Input.get()->getObjectKind(); + break; + } + if (resultType.isNull() || Input.isInvalid()) + return ExprError(); + + return Owned(new (Context) UnaryOperator(Input.take(), Opc, resultType, + VK, OK, OpLoc)); +} + +ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, + UnaryOperatorKind Opc, + Expr *Input) { + if (getLangOptions().CPlusPlus && Input->getType()->isOverloadableType() && + UnaryOperator::getOverloadedOperator(Opc) != OO_None) { + // Find all of the overloaded operators visible from this + // point. We perform both an operator-name lookup from the local + // scope and an argument-dependent lookup based on the types of + // the arguments. + UnresolvedSet<16> Functions; + OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc); + if (S && OverOp != OO_None) + LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(), + Functions); + + return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, Input); + } + + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); +} + +// Unary Operators. 'Tok' is the token for the operator. +ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Op, Expr *Input) { + return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input); +} + +/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". +ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, + LabelDecl *TheDecl) { + TheDecl->setUsed(); + // Create the AST node. The address of a label always has type 'void*'. + return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl, + Context.getPointerType(Context.VoidTy))); +} + +ExprResult +Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, + SourceLocation RPLoc) { // "({..})" + assert(SubStmt && isa<CompoundStmt>(SubStmt) && "Invalid action invocation!"); + CompoundStmt *Compound = cast<CompoundStmt>(SubStmt); + + bool isFileScope + = (getCurFunctionOrMethodDecl() == 0) && (getCurBlock() == 0); + if (isFileScope) + return ExprError(Diag(LPLoc, diag::err_stmtexpr_file_scope)); + + // FIXME: there are a variety of strange constraints to enforce here, for + // example, it is not possible to goto into a stmt expression apparently. + // More semantic analysis is needed. + + // If there are sub stmts in the compound stmt, take the type of the last one + // as the type of the stmtexpr. + QualType Ty = Context.VoidTy; + bool StmtExprMayBindToTemp = false; + if (!Compound->body_empty()) { + Stmt *LastStmt = Compound->body_back(); + LabelStmt *LastLabelStmt = 0; + // If LastStmt is a label, skip down through into the body. + while (LabelStmt *Label = dyn_cast<LabelStmt>(LastStmt)) { + LastLabelStmt = Label; + LastStmt = Label->getSubStmt(); + } + if (Expr *LastE = dyn_cast<Expr>(LastStmt)) { + // Do function/array conversion on the last expression, but not + // lvalue-to-rvalue. However, initialize an unqualified type. + ExprResult LastExpr = DefaultFunctionArrayConversion(LastE); + if (LastExpr.isInvalid()) + return ExprError(); + Ty = LastExpr.get()->getType().getUnqualifiedType(); + + if (!Ty->isDependentType() && !LastExpr.get()->isTypeDependent()) { + LastExpr = PerformCopyInitialization( + InitializedEntity::InitializeResult(LPLoc, + Ty, + false), + SourceLocation(), + LastExpr); + if (LastExpr.isInvalid()) + return ExprError(); + if (LastExpr.get() != 0) { + if (!LastLabelStmt) + Compound->setLastStmt(LastExpr.take()); + else + LastLabelStmt->setSubStmt(LastExpr.take()); + StmtExprMayBindToTemp = true; + } + } + } + } + + // FIXME: Check that expression type is complete/non-abstract; statement + // expressions are not lvalues. + Expr *ResStmtExpr = new (Context) StmtExpr(Compound, Ty, LPLoc, RPLoc); + if (StmtExprMayBindToTemp) + return MaybeBindToTemporary(ResStmtExpr); + return Owned(ResStmtExpr); +} + +ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, + TypeSourceInfo *TInfo, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc) { + QualType ArgTy = TInfo->getType(); + bool Dependent = ArgTy->isDependentType(); + SourceRange TypeRange = TInfo->getTypeLoc().getLocalSourceRange(); + + // We must have at least one component that refers to the type, and the first + // one is known to be a field designator. Verify that the ArgTy represents + // a struct/union/class. + if (!Dependent && !ArgTy->isRecordType()) + return ExprError(Diag(BuiltinLoc, diag::err_offsetof_record_type) + << ArgTy << TypeRange); + + // Type must be complete per C99 7.17p3 because a declaring a variable + // with an incomplete type would be ill-formed. + if (!Dependent + && RequireCompleteType(BuiltinLoc, ArgTy, + PDiag(diag::err_offsetof_incomplete_type) + << TypeRange)) + return ExprError(); + + // offsetof with non-identifier designators (e.g. "offsetof(x, a.b[c])") are a + // GCC extension, diagnose them. + // FIXME: This diagnostic isn't actually visible because the location is in + // a system header! + if (NumComponents != 1) + Diag(BuiltinLoc, diag::ext_offsetof_extended_field_designator) + << SourceRange(CompPtr[1].LocStart, CompPtr[NumComponents-1].LocEnd); + + bool DidWarnAboutNonPOD = false; + QualType CurrentType = ArgTy; + typedef OffsetOfExpr::OffsetOfNode OffsetOfNode; + llvm::SmallVector<OffsetOfNode, 4> Comps; + llvm::SmallVector<Expr*, 4> Exprs; + for (unsigned i = 0; i != NumComponents; ++i) { + const OffsetOfComponent &OC = CompPtr[i]; + if (OC.isBrackets) { + // Offset of an array sub-field. TODO: Should we allow vector elements? + if (!CurrentType->isDependentType()) { + const ArrayType *AT = Context.getAsArrayType(CurrentType); + if(!AT) + return ExprError(Diag(OC.LocEnd, diag::err_offsetof_array_type) + << CurrentType); + CurrentType = AT->getElementType(); + } else + CurrentType = Context.DependentTy; + + // The expression must be an integral expression. + // FIXME: An integral constant expression? + Expr *Idx = static_cast<Expr*>(OC.U.E); + if (!Idx->isTypeDependent() && !Idx->isValueDependent() && + !Idx->getType()->isIntegerType()) + return ExprError(Diag(Idx->getLocStart(), + diag::err_typecheck_subscript_not_integer) + << Idx->getSourceRange()); + + // Record this array index. + Comps.push_back(OffsetOfNode(OC.LocStart, Exprs.size(), OC.LocEnd)); + Exprs.push_back(Idx); + continue; + } + + // Offset of a field. + if (CurrentType->isDependentType()) { + // We have the offset of a field, but we can't look into the dependent + // type. Just record the identifier of the field. + Comps.push_back(OffsetOfNode(OC.LocStart, OC.U.IdentInfo, OC.LocEnd)); + CurrentType = Context.DependentTy; + continue; + } + + // We need to have a complete type to look into. + if (RequireCompleteType(OC.LocStart, CurrentType, + diag::err_offsetof_incomplete_type)) + return ExprError(); + + // Look for the designated field. + const RecordType *RC = CurrentType->getAs<RecordType>(); + if (!RC) + return ExprError(Diag(OC.LocEnd, diag::err_offsetof_record_type) + << CurrentType); + RecordDecl *RD = RC->getDecl(); + + // C++ [lib.support.types]p5: + // The macro offsetof accepts a restricted set of type arguments in this + // International Standard. type shall be a POD structure or a POD union + // (clause 9). + if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { + if (!CRD->isPOD() && !DidWarnAboutNonPOD && + DiagRuntimeBehavior(BuiltinLoc, 0, + PDiag(diag::warn_offsetof_non_pod_type) + << SourceRange(CompPtr[0].LocStart, OC.LocEnd) + << CurrentType)) + DidWarnAboutNonPOD = true; + } + + // Look for the field. + LookupResult R(*this, OC.U.IdentInfo, OC.LocStart, LookupMemberName); + LookupQualifiedName(R, RD); + FieldDecl *MemberDecl = R.getAsSingle<FieldDecl>(); + IndirectFieldDecl *IndirectMemberDecl = 0; + if (!MemberDecl) { + if ((IndirectMemberDecl = R.getAsSingle<IndirectFieldDecl>())) + MemberDecl = IndirectMemberDecl->getAnonField(); + } + + if (!MemberDecl) + return ExprError(Diag(BuiltinLoc, diag::err_no_member) + << OC.U.IdentInfo << RD << SourceRange(OC.LocStart, + OC.LocEnd)); + + // C99 7.17p3: + // (If the specified member is a bit-field, the behavior is undefined.) + // + // We diagnose this as an error. + if (MemberDecl->getBitWidth()) { + Diag(OC.LocEnd, diag::err_offsetof_bitfield) + << MemberDecl->getDeclName() + << SourceRange(BuiltinLoc, RParenLoc); + Diag(MemberDecl->getLocation(), diag::note_bitfield_decl); + return ExprError(); + } + + RecordDecl *Parent = MemberDecl->getParent(); + if (IndirectMemberDecl) + Parent = cast<RecordDecl>(IndirectMemberDecl->getDeclContext()); + + // If the member was found in a base class, introduce OffsetOfNodes for + // the base class indirections. + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + if (IsDerivedFrom(CurrentType, Context.getTypeDeclType(Parent), Paths)) { + CXXBasePath &Path = Paths.front(); + for (CXXBasePath::iterator B = Path.begin(), BEnd = Path.end(); + B != BEnd; ++B) + Comps.push_back(OffsetOfNode(B->Base)); + } + + if (IndirectMemberDecl) { + for (IndirectFieldDecl::chain_iterator FI = + IndirectMemberDecl->chain_begin(), + FEnd = IndirectMemberDecl->chain_end(); FI != FEnd; FI++) { + assert(isa<FieldDecl>(*FI)); + Comps.push_back(OffsetOfNode(OC.LocStart, + cast<FieldDecl>(*FI), OC.LocEnd)); + } + } else + Comps.push_back(OffsetOfNode(OC.LocStart, MemberDecl, OC.LocEnd)); + + CurrentType = MemberDecl->getType().getNonReferenceType(); + } + + return Owned(OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, + TInfo, Comps.data(), Comps.size(), + Exprs.data(), Exprs.size(), RParenLoc)); +} + +ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, + SourceLocation BuiltinLoc, + SourceLocation TypeLoc, + ParsedType argty, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RPLoc) { + + TypeSourceInfo *ArgTInfo; + QualType ArgTy = GetTypeFromParser(argty, &ArgTInfo); + if (ArgTy.isNull()) + return ExprError(); + + if (!ArgTInfo) + ArgTInfo = Context.getTrivialTypeSourceInfo(ArgTy, TypeLoc); + + return BuildBuiltinOffsetOf(BuiltinLoc, ArgTInfo, CompPtr, NumComponents, + RPLoc); +} + + +ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, + Expr *CondExpr, + Expr *LHSExpr, Expr *RHSExpr, + SourceLocation RPLoc) { + assert((CondExpr && LHSExpr && RHSExpr) && "Missing type argument(s)"); + + ExprValueKind VK = VK_RValue; + ExprObjectKind OK = OK_Ordinary; + QualType resType; + bool ValueDependent = false; + if (CondExpr->isTypeDependent() || CondExpr->isValueDependent()) { + resType = Context.DependentTy; + ValueDependent = true; + } else { + // The conditional expression is required to be a constant expression. + llvm::APSInt condEval(32); + SourceLocation ExpLoc; + if (!CondExpr->isIntegerConstantExpr(condEval, Context, &ExpLoc)) + return ExprError(Diag(ExpLoc, + diag::err_typecheck_choose_expr_requires_constant) + << CondExpr->getSourceRange()); + + // If the condition is > zero, then the AST type is the same as the LSHExpr. + Expr *ActiveExpr = condEval.getZExtValue() ? LHSExpr : RHSExpr; + + resType = ActiveExpr->getType(); + ValueDependent = ActiveExpr->isValueDependent(); + VK = ActiveExpr->getValueKind(); + OK = ActiveExpr->getObjectKind(); + } + + return Owned(new (Context) ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, + resType, VK, OK, RPLoc, + resType->isDependentType(), + ValueDependent)); +} + +//===----------------------------------------------------------------------===// +// Clang Extensions. +//===----------------------------------------------------------------------===// + +/// ActOnBlockStart - This callback is invoked when a block literal is started. +void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { + BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); + PushBlockScope(BlockScope, Block); + CurContext->addDecl(Block); + if (BlockScope) + PushDeclContext(BlockScope, Block); + else + CurContext = Block; +} + +void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { + assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!"); + assert(ParamInfo.getContext() == Declarator::BlockLiteralContext); + BlockScopeInfo *CurBlock = getCurBlock(); + + TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope); + QualType T = Sig->getType(); + + // GetTypeForDeclarator always produces a function type for a block + // literal signature. Furthermore, it is always a FunctionProtoType + // unless the function was written with a typedef. + assert(T->isFunctionType() && + "GetTypeForDeclarator made a non-function block signature"); + + // Look for an explicit signature in that function type. + FunctionProtoTypeLoc ExplicitSignature; + + TypeLoc tmp = Sig->getTypeLoc().IgnoreParens(); + if (isa<FunctionProtoTypeLoc>(tmp)) { + ExplicitSignature = cast<FunctionProtoTypeLoc>(tmp); + + // Check whether that explicit signature was synthesized by + // GetTypeForDeclarator. If so, don't save that as part of the + // written signature. + if (ExplicitSignature.getLocalRangeBegin() == + ExplicitSignature.getLocalRangeEnd()) { + // This would be much cheaper if we stored TypeLocs instead of + // TypeSourceInfos. + TypeLoc Result = ExplicitSignature.getResultLoc(); + unsigned Size = Result.getFullDataSize(); + Sig = Context.CreateTypeSourceInfo(Result.getType(), Size); + Sig->getTypeLoc().initializeFullCopy(Result, Size); + + ExplicitSignature = FunctionProtoTypeLoc(); + } + } + + CurBlock->TheDecl->setSignatureAsWritten(Sig); + CurBlock->FunctionType = T; + + const FunctionType *Fn = T->getAs<FunctionType>(); + QualType RetTy = Fn->getResultType(); + bool isVariadic = + (isa<FunctionProtoType>(Fn) && cast<FunctionProtoType>(Fn)->isVariadic()); + + CurBlock->TheDecl->setIsVariadic(isVariadic); + + // Don't allow returning a objc interface by value. + if (RetTy->isObjCObjectType()) { + Diag(ParamInfo.getSourceRange().getBegin(), + diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; + return; + } + + // Context.DependentTy is used as a placeholder for a missing block + // return type. TODO: what should we do with declarators like: + // ^ * { ... } + // If the answer is "apply template argument deduction".... + if (RetTy != Context.DependentTy) + CurBlock->ReturnType = RetTy; + + // Push block parameters from the declarator if we had them. + llvm::SmallVector<ParmVarDecl*, 8> Params; + if (ExplicitSignature) { + for (unsigned I = 0, E = ExplicitSignature.getNumArgs(); I != E; ++I) { + ParmVarDecl *Param = ExplicitSignature.getArg(I); + if (Param->getIdentifier() == 0 && + !Param->isImplicit() && + !Param->isInvalidDecl() && + !getLangOptions().CPlusPlus) + Diag(Param->getLocation(), diag::err_parameter_name_omitted); + Params.push_back(Param); + } + + // Fake up parameter variables if we have a typedef, like + // ^ fntype { ... } + } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) { + for (FunctionProtoType::arg_type_iterator + I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) { + ParmVarDecl *Param = + BuildParmVarDeclForTypedef(CurBlock->TheDecl, + ParamInfo.getSourceRange().getBegin(), + *I); + Params.push_back(Param); + } + } + + // Set the parameters on the block decl. + if (!Params.empty()) { + CurBlock->TheDecl->setParams(Params.data(), Params.size()); + CheckParmsForFunctionDef(CurBlock->TheDecl->param_begin(), + CurBlock->TheDecl->param_end(), + /*CheckParameterNames=*/false); + } + + // Finally we can process decl attributes. + ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); + + if (!isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) { + Diag(ParamInfo.getAttributes()->getLoc(), + diag::warn_attribute_sentinel_not_variadic) << 1; + // FIXME: remove the attribute. + } + + // Put the parameter variables in scope. We can bail out immediately + // if we don't have any. + if (Params.empty()) + return; + + for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(), + E = CurBlock->TheDecl->param_end(); AI != E; ++AI) { + (*AI)->setOwningFunction(CurBlock->TheDecl); + + // If this has an identifier, add it to the scope stack. + if ((*AI)->getIdentifier()) { + CheckShadow(CurBlock->TheScope, *AI); + + PushOnScopeChains(*AI, CurBlock->TheScope); + } + } +} + +/// ActOnBlockError - If there is an error parsing a block, this callback +/// is invoked to pop the information about the block from the action impl. +void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { + // Pop off CurBlock, handle nested blocks. + PopDeclContext(); + PopFunctionOrBlockScope(); +} + +/// ActOnBlockStmtExpr - This is called when the body of a block statement +/// literal was successfully completed. ^(int x){...} +ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, + Stmt *Body, Scope *CurScope) { + // If blocks are disabled, emit an error. + if (!LangOpts.Blocks) + Diag(CaretLoc, diag::err_blocks_disable); + + BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back()); + + PopDeclContext(); + + QualType RetTy = Context.VoidTy; + if (!BSI->ReturnType.isNull()) + RetTy = BSI->ReturnType; + + bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>(); + QualType BlockTy; + + // Set the captured variables on the block. + BSI->TheDecl->setCaptures(Context, BSI->Captures.begin(), BSI->Captures.end(), + BSI->CapturesCXXThis); + + // If the user wrote a function type in some form, try to use that. + if (!BSI->FunctionType.isNull()) { + const FunctionType *FTy = BSI->FunctionType->getAs<FunctionType>(); + + FunctionType::ExtInfo Ext = FTy->getExtInfo(); + if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true); + + // Turn protoless block types into nullary block types. + if (isa<FunctionNoProtoType>(FTy)) { + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = Ext; + BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); + + // Otherwise, if we don't need to change anything about the function type, + // preserve its sugar structure. + } else if (FTy->getResultType() == RetTy && + (!NoReturn || FTy->getNoReturnAttr())) { + BlockTy = BSI->FunctionType; + + // Otherwise, make the minimal modifications to the function type. + } else { + const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.TypeQuals = 0; // FIXME: silently? + EPI.ExtInfo = Ext; + BlockTy = Context.getFunctionType(RetTy, + FPT->arg_type_begin(), + FPT->getNumArgs(), + EPI); + } + + // If we don't have a function type, just build one from nothing. + } else { + FunctionProtoType::ExtProtoInfo EPI; + EPI.ExtInfo = FunctionType::ExtInfo(NoReturn, false, 0, CC_Default); + BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); + } + + DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), + BSI->TheDecl->param_end()); + BlockTy = Context.getBlockPointerType(BlockTy); + + // If needed, diagnose invalid gotos and switches in the block. + if (getCurFunction()->NeedsScopeChecking() && !hasAnyErrorsInThisFunction()) + DiagnoseInvalidJumps(cast<CompoundStmt>(Body)); + + BSI->TheDecl->setBody(cast<CompoundStmt>(Body)); + + BlockExpr *Result = new (Context) BlockExpr(BSI->TheDecl, BlockTy); + + const AnalysisBasedWarnings::Policy &WP = AnalysisWarnings.getDefaultPolicy(); + PopFunctionOrBlockScope(&WP, Result->getBlockDecl(), Result); + return Owned(Result); +} + +ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, + Expr *expr, ParsedType type, + SourceLocation RPLoc) { + TypeSourceInfo *TInfo; + GetTypeFromParser(type, &TInfo); + return BuildVAArgExpr(BuiltinLoc, expr, TInfo, RPLoc); +} + +ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, + Expr *E, TypeSourceInfo *TInfo, + SourceLocation RPLoc) { + Expr *OrigExpr = E; + + // Get the va_list type + QualType VaListType = Context.getBuiltinVaListType(); + if (VaListType->isArrayType()) { + // Deal with implicit array decay; for example, on x86-64, + // va_list is an array, but it's supposed to decay to + // a pointer for va_arg. + VaListType = Context.getArrayDecayedType(VaListType); + // Make sure the input expression also decays appropriately. + ExprResult Result = UsualUnaryConversions(E); + if (Result.isInvalid()) + return ExprError(); + E = Result.take(); + } else { + // Otherwise, the va_list argument must be an l-value because + // it is modified by va_arg. + if (!E->isTypeDependent() && + CheckForModifiableLvalue(E, BuiltinLoc, *this)) + return ExprError(); + } + + if (!E->isTypeDependent() && + !Context.hasSameType(VaListType, E->getType())) { + return ExprError(Diag(E->getLocStart(), + diag::err_first_argument_to_va_arg_not_of_type_va_list) + << OrigExpr->getType() << E->getSourceRange()); + } + + // FIXME: Check that type is complete/non-abstract + // FIXME: Warn if a non-POD type is passed in. + + QualType T = TInfo->getType().getNonLValueExprType(Context); + return Owned(new (Context) VAArgExpr(BuiltinLoc, E, TInfo, RPLoc, T)); +} + +ExprResult Sema::ActOnGNUNullExpr(SourceLocation TokenLoc) { + // The type of __null will be int or long, depending on the size of + // pointers on the target. + QualType Ty; + unsigned pw = Context.Target.getPointerWidth(0); + if (pw == Context.Target.getIntWidth()) + Ty = Context.IntTy; + else if (pw == Context.Target.getLongWidth()) + Ty = Context.LongTy; + else if (pw == Context.Target.getLongLongWidth()) + Ty = Context.LongLongTy; + else { + assert(!"I don't know size of pointer!"); + Ty = Context.IntTy; + } + + return Owned(new (Context) GNUNullExpr(Ty, TokenLoc)); +} + +static void MakeObjCStringLiteralFixItHint(Sema& SemaRef, QualType DstType, + Expr *SrcExpr, FixItHint &Hint) { + if (!SemaRef.getLangOptions().ObjC1) + return; + + const ObjCObjectPointerType *PT = DstType->getAs<ObjCObjectPointerType>(); + if (!PT) + return; + + // Check if the destination is of type 'id'. + if (!PT->isObjCIdType()) { + // Check if the destination is the 'NSString' interface. + const ObjCInterfaceDecl *ID = PT->getInterfaceDecl(); + if (!ID || !ID->getIdentifier()->isStr("NSString")) + return; + } + + // Strip off any parens and casts. + StringLiteral *SL = dyn_cast<StringLiteral>(SrcExpr->IgnoreParenCasts()); + if (!SL || SL->isWide()) + return; + + Hint = FixItHint::CreateInsertion(SL->getLocStart(), "@"); +} + +bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, + SourceLocation Loc, + QualType DstType, QualType SrcType, + Expr *SrcExpr, AssignmentAction Action, + bool *Complained) { + if (Complained) + *Complained = false; + + // Decode the result (notice that AST's are still created for extensions). + bool CheckInferredResultType = false; + bool isInvalid = false; + unsigned DiagKind; + FixItHint Hint; + + switch (ConvTy) { + default: assert(0 && "Unknown conversion type"); + case Compatible: return false; + case PointerToInt: + DiagKind = diag::ext_typecheck_convert_pointer_int; + break; + case IntToPointer: + DiagKind = diag::ext_typecheck_convert_int_pointer; + break; + case IncompatiblePointer: + MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint); + DiagKind = diag::ext_typecheck_convert_incompatible_pointer; + CheckInferredResultType = DstType->isObjCObjectPointerType() && + SrcType->isObjCObjectPointerType(); + break; + case IncompatiblePointerSign: + DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign; + break; + case FunctionVoidPointer: + DiagKind = diag::ext_typecheck_convert_pointer_void_func; + break; + case IncompatiblePointerDiscardsQualifiers: { + // Perform array-to-pointer decay if necessary. + if (SrcType->isArrayType()) SrcType = Context.getArrayDecayedType(SrcType); + + Qualifiers lhq = SrcType->getPointeeType().getQualifiers(); + Qualifiers rhq = DstType->getPointeeType().getQualifiers(); + if (lhq.getAddressSpace() != rhq.getAddressSpace()) { + DiagKind = diag::err_typecheck_incompatible_address_space; + break; + } + + llvm_unreachable("unknown error case for discarding qualifiers!"); + // fallthrough + } + case CompatiblePointerDiscardsQualifiers: + // If the qualifiers lost were because we were applying the + // (deprecated) C++ conversion from a string literal to a char* + // (or wchar_t*), then there was no error (C++ 4.2p2). FIXME: + // Ideally, this check would be performed in + // checkPointerTypesForAssignment. However, that would require a + // bit of refactoring (so that the second argument is an + // expression, rather than a type), which should be done as part + // of a larger effort to fix checkPointerTypesForAssignment for + // C++ semantics. + if (getLangOptions().CPlusPlus && + IsStringLiteralToNonConstPointerConversion(SrcExpr, DstType)) + return false; + DiagKind = diag::ext_typecheck_convert_discards_qualifiers; + break; + case IncompatibleNestedPointerQualifiers: + DiagKind = diag::ext_nested_pointer_qualifier_mismatch; + break; + case IntToBlockPointer: + DiagKind = diag::err_int_to_block_pointer; + break; + case IncompatibleBlockPointer: + DiagKind = diag::err_typecheck_convert_incompatible_block_pointer; + break; + case IncompatibleObjCQualifiedId: + // FIXME: Diagnose the problem in ObjCQualifiedIdTypesAreCompatible, since + // it can give a more specific diagnostic. + DiagKind = diag::warn_incompatible_qualified_id; + break; + case IncompatibleVectors: + DiagKind = diag::warn_incompatible_vectors; + break; + case Incompatible: + DiagKind = diag::err_typecheck_convert_incompatible; + isInvalid = true; + break; + } + + QualType FirstType, SecondType; + switch (Action) { + case AA_Assigning: + case AA_Initializing: + // The destination type comes first. + FirstType = DstType; + SecondType = SrcType; + break; + + case AA_Returning: + case AA_Passing: + case AA_Converting: + case AA_Sending: + case AA_Casting: + // The source type comes first. + FirstType = SrcType; + SecondType = DstType; + break; + } + + Diag(Loc, DiagKind) << FirstType << SecondType << Action + << SrcExpr->getSourceRange() << Hint; + if (CheckInferredResultType) + EmitRelatedResultTypeNote(SrcExpr); + + if (Complained) + *Complained = true; + return isInvalid; +} + +bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ + llvm::APSInt ICEResult; + if (E->isIntegerConstantExpr(ICEResult, Context)) { + if (Result) + *Result = ICEResult; + return false; + } + + Expr::EvalResult EvalResult; + + if (!E->Evaluate(EvalResult, Context) || !EvalResult.Val.isInt() || + EvalResult.HasSideEffects) { + Diag(E->getExprLoc(), diag::err_expr_not_ice) << E->getSourceRange(); + + if (EvalResult.Diag) { + // We only show the note if it's not the usual "invalid subexpression" + // or if it's actually in a subexpression. + if (EvalResult.Diag != diag::note_invalid_subexpr_in_ice || + E->IgnoreParens() != EvalResult.DiagExpr->IgnoreParens()) + Diag(EvalResult.DiagLoc, EvalResult.Diag); + } + + return true; + } + + Diag(E->getExprLoc(), diag::ext_expr_not_ice) << + E->getSourceRange(); + + if (EvalResult.Diag && + Diags.getDiagnosticLevel(diag::ext_expr_not_ice, EvalResult.DiagLoc) + != Diagnostic::Ignored) + Diag(EvalResult.DiagLoc, EvalResult.Diag); + + if (Result) + *Result = EvalResult.Val.getInt(); + return false; +} + +void +Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { + ExprEvalContexts.push_back( + ExpressionEvaluationContextRecord(NewContext, ExprTemporaries.size())); +} + +void +Sema::PopExpressionEvaluationContext() { + // Pop the current expression evaluation context off the stack. + ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back(); + ExprEvalContexts.pop_back(); + + if (Rec.Context == PotentiallyPotentiallyEvaluated) { + if (Rec.PotentiallyReferenced) { + // Mark any remaining declarations in the current position of the stack + // as "referenced". If they were not meant to be referenced, semantic + // analysis would have eliminated them (e.g., in ActOnCXXTypeId). + for (PotentiallyReferencedDecls::iterator + I = Rec.PotentiallyReferenced->begin(), + IEnd = Rec.PotentiallyReferenced->end(); + I != IEnd; ++I) + MarkDeclarationReferenced(I->first, I->second); + } + + if (Rec.PotentiallyDiagnosed) { + // Emit any pending diagnostics. + for (PotentiallyEmittedDiagnostics::iterator + I = Rec.PotentiallyDiagnosed->begin(), + IEnd = Rec.PotentiallyDiagnosed->end(); + I != IEnd; ++I) + Diag(I->first, I->second); + } + } + + // When are coming out of an unevaluated context, clear out any + // temporaries that we may have created as part of the evaluation of + // the expression in that context: they aren't relevant because they + // will never be constructed. + if (Rec.Context == Unevaluated && + ExprTemporaries.size() > Rec.NumTemporaries) + ExprTemporaries.erase(ExprTemporaries.begin() + Rec.NumTemporaries, + ExprTemporaries.end()); + + // Destroy the popped expression evaluation record. + Rec.Destroy(); +} + +/// \brief Note that the given declaration was referenced in the source code. +/// +/// This routine should be invoke whenever a given declaration is referenced +/// in the source code, and where that reference occurred. If this declaration +/// reference means that the the declaration is used (C++ [basic.def.odr]p2, +/// C99 6.9p3), then the declaration will be marked as used. +/// +/// \param Loc the location where the declaration was referenced. +/// +/// \param D the declaration that has been referenced by the source code. +void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { + assert(D && "No declaration?"); + + D->setReferenced(); + + if (D->isUsed(false)) + return; + + // Mark a parameter or variable declaration "used", regardless of whether we're in a + // template or not. The reason for this is that unevaluated expressions + // (e.g. (void)sizeof()) constitute a use for warning purposes (-Wunused-variables and + // -Wunused-parameters) + if (isa<ParmVarDecl>(D) || + (isa<VarDecl>(D) && D->getDeclContext()->isFunctionOrMethod())) { + D->setUsed(); + return; + } + + if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) + return; + + // Do not mark anything as "used" within a dependent context; wait for + // an instantiation. + if (CurContext->isDependentContext()) + return; + + switch (ExprEvalContexts.back().Context) { + case Unevaluated: + // We are in an expression that is not potentially evaluated; do nothing. + return; + + case PotentiallyEvaluated: + // We are in a potentially-evaluated expression, so this declaration is + // "used"; handle this below. + break; + + case PotentiallyPotentiallyEvaluated: + // We are in an expression that may be potentially evaluated; queue this + // declaration reference until we know whether the expression is + // potentially evaluated. + ExprEvalContexts.back().addReferencedDecl(Loc, D); + return; + + case PotentiallyEvaluatedIfUsed: + // Referenced declarations will only be used if the construct in the + // containing expression is used. + return; + } + + // Note that this declaration has been used. + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { + if (Constructor->isDefaulted() && Constructor->isDefaultConstructor()) { + if (Constructor->isTrivial()) + return; + if (!Constructor->isUsed(false)) + DefineImplicitDefaultConstructor(Loc, Constructor); + } else if (Constructor->isDefaulted() && + Constructor->isCopyConstructor()) { + if (!Constructor->isUsed(false)) + DefineImplicitCopyConstructor(Loc, Constructor); + } + + MarkVTableUsed(Loc, Constructor->getParent()); + } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { + if (Destructor->isDefaulted() && !Destructor->isUsed(false)) + DefineImplicitDestructor(Loc, Destructor); + if (Destructor->isVirtual()) + MarkVTableUsed(Loc, Destructor->getParent()); + } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) { + if (MethodDecl->isDefaulted() && MethodDecl->isOverloadedOperator() && + MethodDecl->getOverloadedOperator() == OO_Equal) { + if (!MethodDecl->isUsed(false)) + DefineImplicitCopyAssignment(Loc, MethodDecl); + } else if (MethodDecl->isVirtual()) + MarkVTableUsed(Loc, MethodDecl->getParent()); + } + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + // Recursive functions should be marked when used from another function. + if (CurContext == Function) return; + + // Implicit instantiation of function templates and member functions of + // class templates. + if (Function->isImplicitlyInstantiable()) { + bool AlreadyInstantiated = false; + if (FunctionTemplateSpecializationInfo *SpecInfo + = Function->getTemplateSpecializationInfo()) { + if (SpecInfo->getPointOfInstantiation().isInvalid()) + SpecInfo->setPointOfInstantiation(Loc); + else if (SpecInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) + AlreadyInstantiated = true; + } else if (MemberSpecializationInfo *MSInfo + = Function->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) + MSInfo->setPointOfInstantiation(Loc); + else if (MSInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) + AlreadyInstantiated = true; + } + + if (!AlreadyInstantiated) { + if (isa<CXXRecordDecl>(Function->getDeclContext()) && + cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass()) + PendingLocalImplicitInstantiations.push_back(std::make_pair(Function, + Loc)); + else + PendingInstantiations.push_back(std::make_pair(Function, Loc)); + } + } else { + // Walk redefinitions, as some of them may be instantiable. + for (FunctionDecl::redecl_iterator i(Function->redecls_begin()), + e(Function->redecls_end()); i != e; ++i) { + if (!i->isUsed(false) && i->isImplicitlyInstantiable()) + MarkDeclarationReferenced(Loc, *i); + } + } + + // Keep track of used but undefined functions. + if (!Function->isPure() && !Function->hasBody() && + Function->getLinkage() != ExternalLinkage) { + SourceLocation &old = UndefinedInternals[Function->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; + } + + Function->setUsed(true); + return; + } + + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + // Implicit instantiation of static data members of class templates. + if (Var->isStaticDataMember() && + Var->getInstantiatedFromStaticDataMember()) { + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + if (MSInfo->getPointOfInstantiation().isInvalid() && + MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { + MSInfo->setPointOfInstantiation(Loc); + // This is a modification of an existing AST node. Notify listeners. + if (ASTMutationListener *L = getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); + PendingInstantiations.push_back(std::make_pair(Var, Loc)); + } + } + + // Keep track of used but undefined variables. We make a hole in + // the warning for static const data members with in-line + // initializers. + if (Var->hasDefinition() == VarDecl::DeclarationOnly + && Var->getLinkage() != ExternalLinkage + && !(Var->isStaticDataMember() && Var->hasInit())) { + SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()]; + if (old.isInvalid()) old = Loc; + } + + D->setUsed(true); + return; + } +} + +namespace { + // Mark all of the declarations referenced + // FIXME: Not fully implemented yet! We need to have a better understanding + // of when we're entering + class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> { + Sema &S; + SourceLocation Loc; + + public: + typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited; + + MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { } + + bool TraverseTemplateArgument(const TemplateArgument &Arg); + bool TraverseRecordType(RecordType *T); + }; +} + +bool MarkReferencedDecls::TraverseTemplateArgument( + const TemplateArgument &Arg) { + if (Arg.getKind() == TemplateArgument::Declaration) { + S.MarkDeclarationReferenced(Loc, Arg.getAsDecl()); + } + + return Inherited::TraverseTemplateArgument(Arg); +} + +bool MarkReferencedDecls::TraverseRecordType(RecordType *T) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { + const TemplateArgumentList &Args = Spec->getTemplateArgs(); + return TraverseTemplateArguments(Args.data(), Args.size()); + } + + return true; +} + +void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { + MarkReferencedDecls Marker(*this, Loc); + Marker.TraverseType(Context.getCanonicalType(T)); +} + +namespace { + /// \brief Helper class that marks all of the declarations referenced by + /// potentially-evaluated subexpressions as "referenced". + class EvaluatedExprMarker : public EvaluatedExprVisitor<EvaluatedExprMarker> { + Sema &S; + + public: + typedef EvaluatedExprVisitor<EvaluatedExprMarker> Inherited; + + explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { } + + void VisitDeclRefExpr(DeclRefExpr *E) { + S.MarkDeclarationReferenced(E->getLocation(), E->getDecl()); + } + + void VisitMemberExpr(MemberExpr *E) { + S.MarkDeclarationReferenced(E->getMemberLoc(), E->getMemberDecl()); + Inherited::VisitMemberExpr(E); + } + + void VisitCXXNewExpr(CXXNewExpr *E) { + if (E->getConstructor()) + S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor()); + if (E->getOperatorNew()) + S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorNew()); + if (E->getOperatorDelete()) + S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete()); + Inherited::VisitCXXNewExpr(E); + } + + void VisitCXXDeleteExpr(CXXDeleteExpr *E) { + if (E->getOperatorDelete()) + S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete()); + QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType()); + if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); + S.MarkDeclarationReferenced(E->getLocStart(), + S.LookupDestructor(Record)); + } + + Inherited::VisitCXXDeleteExpr(E); + } + + void VisitCXXConstructExpr(CXXConstructExpr *E) { + S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor()); + Inherited::VisitCXXConstructExpr(E); + } + + void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { + S.MarkDeclarationReferenced(E->getLocation(), E->getDecl()); + } + + void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + Visit(E->getExpr()); + } + }; +} + +/// \brief Mark any declarations that appear within this expression or any +/// potentially-evaluated subexpressions as "referenced". +void Sema::MarkDeclarationsReferencedInExpr(Expr *E) { + EvaluatedExprMarker(*this).Visit(E); +} + +/// \brief Emit a diagnostic that describes an effect on the run-time behavior +/// of the program being compiled. +/// +/// This routine emits the given diagnostic when the code currently being +/// type-checked is "potentially evaluated", meaning that there is a +/// possibility that the code will actually be executable. Code in sizeof() +/// expressions, code used only during overload resolution, etc., are not +/// potentially evaluated. This routine will suppress such diagnostics or, +/// in the absolutely nutty case of potentially potentially evaluated +/// expressions (C++ typeid), queue the diagnostic to potentially emit it +/// later. +/// +/// This routine should be used for all diagnostics that describe the run-time +/// behavior of a program, such as passing a non-POD value through an ellipsis. +/// Failure to do so will likely result in spurious diagnostics or failures +/// during overload resolution or within sizeof/alignof/typeof/typeid. +bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *stmt, + const PartialDiagnostic &PD) { + switch (ExprEvalContexts.back().Context ) { + case Unevaluated: + // The argument will never be evaluated, so don't complain. + break; + + case PotentiallyEvaluated: + case PotentiallyEvaluatedIfUsed: + if (stmt && getCurFunctionOrMethodDecl()) { + FunctionScopes.back()->PossiblyUnreachableDiags. + push_back(sema::PossiblyUnreachableDiag(PD, Loc, stmt)); + } + else + Diag(Loc, PD); + + return true; + + case PotentiallyPotentiallyEvaluated: + ExprEvalContexts.back().addDiagnostic(Loc, PD); + break; + } + + return false; +} + +bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, + CallExpr *CE, FunctionDecl *FD) { + if (ReturnType->isVoidType() || !ReturnType->isIncompleteType()) + return false; + + PartialDiagnostic Note = + FD ? PDiag(diag::note_function_with_incomplete_return_type_declared_here) + << FD->getDeclName() : PDiag(); + SourceLocation NoteLoc = FD ? FD->getLocation() : SourceLocation(); + + if (RequireCompleteType(Loc, ReturnType, + FD ? + PDiag(diag::err_call_function_incomplete_return) + << CE->getSourceRange() << FD->getDeclName() : + PDiag(diag::err_call_incomplete_return) + << CE->getSourceRange(), + std::make_pair(NoteLoc, Note))) + return true; + + return false; +} + +// Diagnose the s/=/==/ and s/\|=/!=/ typos. Note that adding parentheses +// will prevent this condition from triggering, which is what we want. +void Sema::DiagnoseAssignmentAsCondition(Expr *E) { + SourceLocation Loc; + + unsigned diagnostic = diag::warn_condition_is_assignment; + bool IsOrAssign = false; + + if (isa<BinaryOperator>(E)) { + BinaryOperator *Op = cast<BinaryOperator>(E); + if (Op->getOpcode() != BO_Assign && Op->getOpcode() != BO_OrAssign) + return; + + IsOrAssign = Op->getOpcode() == BO_OrAssign; + + // Greylist some idioms by putting them into a warning subcategory. + if (ObjCMessageExpr *ME + = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) { + Selector Sel = ME->getSelector(); + + // self = [<foo> init...] + if (isSelfExpr(Op->getLHS()) && Sel.getNameForSlot(0).startswith("init")) + diagnostic = diag::warn_condition_is_idiomatic_assignment; + + // <foo> = [<bar> nextObject] + else if (Sel.isUnarySelector() && Sel.getNameForSlot(0) == "nextObject") + diagnostic = diag::warn_condition_is_idiomatic_assignment; + } + + Loc = Op->getOperatorLoc(); + } else if (isa<CXXOperatorCallExpr>(E)) { + CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E); + if (Op->getOperator() != OO_Equal && Op->getOperator() != OO_PipeEqual) + return; + + IsOrAssign = Op->getOperator() == OO_PipeEqual; + Loc = Op->getOperatorLoc(); + } else { + // Not an assignment. + return; + } + + Diag(Loc, diagnostic) << E->getSourceRange(); + + SourceLocation Open = E->getSourceRange().getBegin(); + SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); + Diag(Loc, diag::note_condition_assign_silence) + << FixItHint::CreateInsertion(Open, "(") + << FixItHint::CreateInsertion(Close, ")"); + + if (IsOrAssign) + Diag(Loc, diag::note_condition_or_assign_to_comparison) + << FixItHint::CreateReplacement(Loc, "!="); + else + Diag(Loc, diag::note_condition_assign_to_comparison) + << FixItHint::CreateReplacement(Loc, "=="); +} + +/// \brief Redundant parentheses over an equality comparison can indicate +/// that the user intended an assignment used as condition. +void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) { + // Don't warn if the parens came from a macro. + SourceLocation parenLoc = parenE->getLocStart(); + if (parenLoc.isInvalid() || parenLoc.isMacroID()) + return; + // Don't warn for dependent expressions. + if (parenE->isTypeDependent()) + return; + + Expr *E = parenE->IgnoreParens(); + + if (BinaryOperator *opE = dyn_cast<BinaryOperator>(E)) + if (opE->getOpcode() == BO_EQ && + opE->getLHS()->IgnoreParenImpCasts()->isModifiableLvalue(Context) + == Expr::MLV_Valid) { + SourceLocation Loc = opE->getOperatorLoc(); + + Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange(); + Diag(Loc, diag::note_equality_comparison_silence) + << FixItHint::CreateRemoval(parenE->getSourceRange().getBegin()) + << FixItHint::CreateRemoval(parenE->getSourceRange().getEnd()); + Diag(Loc, diag::note_equality_comparison_to_assign) + << FixItHint::CreateReplacement(Loc, "="); + } +} + +ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) { + DiagnoseAssignmentAsCondition(E); + if (ParenExpr *parenE = dyn_cast<ParenExpr>(E)) + DiagnoseEqualityWithExtraParens(parenE); + + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + + if (!E->isTypeDependent()) { + if (getLangOptions().CPlusPlus) + return CheckCXXBooleanCondition(E); // C++ 6.4p4 + + ExprResult ERes = DefaultFunctionArrayLvalueConversion(E); + if (ERes.isInvalid()) + return ExprError(); + E = ERes.take(); + + QualType T = E->getType(); + if (!T->isScalarType()) { // C99 6.8.4.1p1 + Diag(Loc, diag::err_typecheck_statement_requires_scalar) + << T << E->getSourceRange(); + return ExprError(); + } + } + + return Owned(E); +} + +ExprResult Sema::ActOnBooleanCondition(Scope *S, SourceLocation Loc, + Expr *Sub) { + if (!Sub) + return ExprError(); + + return CheckBooleanCondition(Sub, Loc); +} + +namespace { + /// A visitor for rebuilding a call to an __unknown_any expression + /// to have an appropriate type. + struct RebuildUnknownAnyFunction + : StmtVisitor<RebuildUnknownAnyFunction, ExprResult> { + + Sema &S; + + RebuildUnknownAnyFunction(Sema &S) : S(S) {} + + ExprResult VisitStmt(Stmt *S) { + llvm_unreachable("unexpected statement!"); + return ExprError(); + } + + ExprResult VisitExpr(Expr *expr) { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_call) + << expr->getSourceRange(); + return ExprError(); + } + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template <class T> ExprResult rebuildSugarExpr(T *expr) { + ExprResult subResult = Visit(expr->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + + Expr *subExpr = subResult.take(); + expr->setSubExpr(subExpr); + expr->setType(subExpr->getType()); + expr->setValueKind(subExpr->getValueKind()); + assert(expr->getObjectKind() == OK_Ordinary); + return expr; + } + + ExprResult VisitParenExpr(ParenExpr *paren) { + return rebuildSugarExpr(paren); + } + + ExprResult VisitUnaryExtension(UnaryOperator *op) { + return rebuildSugarExpr(op); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *op) { + ExprResult subResult = Visit(op->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + + Expr *subExpr = subResult.take(); + op->setSubExpr(subExpr); + op->setType(S.Context.getPointerType(subExpr->getType())); + assert(op->getValueKind() == VK_RValue); + assert(op->getObjectKind() == OK_Ordinary); + return op; + } + + ExprResult resolveDecl(Expr *expr, ValueDecl *decl) { + if (!isa<FunctionDecl>(decl)) return VisitExpr(expr); + + expr->setType(decl->getType()); + + assert(expr->getValueKind() == VK_RValue); + if (S.getLangOptions().CPlusPlus && + !(isa<CXXMethodDecl>(decl) && + cast<CXXMethodDecl>(decl)->isInstance())) + expr->setValueKind(VK_LValue); + + return expr; + } + + ExprResult VisitMemberExpr(MemberExpr *mem) { + return resolveDecl(mem, mem->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *ref) { + return resolveDecl(ref, ref->getDecl()); + } + }; +} + +/// Given a function expression of unknown-any type, try to rebuild it +/// to have a function type. +static ExprResult rebuildUnknownAnyFunction(Sema &S, Expr *fn) { + ExprResult result = RebuildUnknownAnyFunction(S).Visit(fn); + if (result.isInvalid()) return ExprError(); + return S.DefaultFunctionArrayConversion(result.take()); +} + +namespace { + /// A visitor for rebuilding an expression of type __unknown_anytype + /// into one which resolves the type directly on the referring + /// expression. Strict preservation of the original source + /// structure is not a goal. + struct RebuildUnknownAnyExpr + : StmtVisitor<RebuildUnknownAnyExpr, ExprResult> { + + Sema &S; + + /// The current destination type. + QualType DestType; + + RebuildUnknownAnyExpr(Sema &S, QualType castType) + : S(S), DestType(castType) {} + + ExprResult VisitStmt(Stmt *S) { + llvm_unreachable("unexpected statement!"); + return ExprError(); + } + + ExprResult VisitExpr(Expr *expr) { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_expr) + << expr->getSourceRange(); + return ExprError(); + } + + ExprResult VisitCallExpr(CallExpr *call); + ExprResult VisitObjCMessageExpr(ObjCMessageExpr *message); + + /// Rebuild an expression which simply semantically wraps another + /// expression which it shares the type and value kind of. + template <class T> ExprResult rebuildSugarExpr(T *expr) { + ExprResult subResult = Visit(expr->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + Expr *subExpr = subResult.take(); + expr->setSubExpr(subExpr); + expr->setType(subExpr->getType()); + expr->setValueKind(subExpr->getValueKind()); + assert(expr->getObjectKind() == OK_Ordinary); + return expr; + } + + ExprResult VisitParenExpr(ParenExpr *paren) { + return rebuildSugarExpr(paren); + } + + ExprResult VisitUnaryExtension(UnaryOperator *op) { + return rebuildSugarExpr(op); + } + + ExprResult VisitUnaryAddrOf(UnaryOperator *op) { + const PointerType *ptr = DestType->getAs<PointerType>(); + if (!ptr) { + S.Diag(op->getOperatorLoc(), diag::err_unknown_any_addrof) + << op->getSourceRange(); + return ExprError(); + } + assert(op->getValueKind() == VK_RValue); + assert(op->getObjectKind() == OK_Ordinary); + op->setType(DestType); + + // Build the sub-expression as if it were an object of the pointee type. + DestType = ptr->getPointeeType(); + ExprResult subResult = Visit(op->getSubExpr()); + if (subResult.isInvalid()) return ExprError(); + op->setSubExpr(subResult.take()); + return op; + } + + ExprResult VisitImplicitCastExpr(ImplicitCastExpr *ice); + + ExprResult resolveDecl(Expr *expr, ValueDecl *decl); + + ExprResult VisitMemberExpr(MemberExpr *mem) { + return resolveDecl(mem, mem->getMemberDecl()); + } + + ExprResult VisitDeclRefExpr(DeclRefExpr *ref) { + return resolveDecl(ref, ref->getDecl()); + } + }; +} + +/// Rebuilds a call expression which yielded __unknown_anytype. +ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *call) { + Expr *callee = call->getCallee(); + + enum FnKind { + FK_MemberFunction, + FK_FunctionPointer, + FK_BlockPointer + }; + + FnKind kind; + QualType type = callee->getType(); + if (type == S.Context.BoundMemberTy) { + assert(isa<CXXMemberCallExpr>(call) || isa<CXXOperatorCallExpr>(call)); + kind = FK_MemberFunction; + type = Expr::findBoundMemberType(callee); + } else if (const PointerType *ptr = type->getAs<PointerType>()) { + type = ptr->getPointeeType(); + kind = FK_FunctionPointer; + } else { + type = type->castAs<BlockPointerType>()->getPointeeType(); + kind = FK_BlockPointer; + } + const FunctionType *fnType = type->castAs<FunctionType>(); + + // Verify that this is a legal result type of a function. + if (DestType->isArrayType() || DestType->isFunctionType()) { + unsigned diagID = diag::err_func_returning_array_function; + if (kind == FK_BlockPointer) + diagID = diag::err_block_returning_array_function; + + S.Diag(call->getExprLoc(), diagID) + << DestType->isFunctionType() << DestType; + return ExprError(); + } + + // Otherwise, go ahead and set DestType as the call's result. + call->setType(DestType.getNonLValueExprType(S.Context)); + call->setValueKind(Expr::getValueKindForType(DestType)); + assert(call->getObjectKind() == OK_Ordinary); + + // Rebuild the function type, replacing the result type with DestType. + if (const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(fnType)) + DestType = S.Context.getFunctionType(DestType, + proto->arg_type_begin(), + proto->getNumArgs(), + proto->getExtProtoInfo()); + else + DestType = S.Context.getFunctionNoProtoType(DestType, + fnType->getExtInfo()); + + // Rebuild the appropriate pointer-to-function type. + switch (kind) { + case FK_MemberFunction: + // Nothing to do. + break; + + case FK_FunctionPointer: + DestType = S.Context.getPointerType(DestType); + break; + + case FK_BlockPointer: + DestType = S.Context.getBlockPointerType(DestType); + break; + } + + // Finally, we can recurse. + ExprResult calleeResult = Visit(callee); + if (!calleeResult.isUsable()) return ExprError(); + call->setCallee(calleeResult.take()); + + // Bind a temporary if necessary. + return S.MaybeBindToTemporary(call); +} + +ExprResult RebuildUnknownAnyExpr::VisitObjCMessageExpr(ObjCMessageExpr *msg) { + ObjCMethodDecl *method = msg->getMethodDecl(); + assert(method && "__unknown_anytype message without result type?"); + + // Verify that this is a legal result type of a call. + if (DestType->isArrayType() || DestType->isFunctionType()) { + S.Diag(msg->getExprLoc(), diag::err_func_returning_array_function) + << DestType->isFunctionType() << DestType; + return ExprError(); + } + + assert(method->getResultType() == S.Context.UnknownAnyTy); + method->setResultType(DestType); + + // Change the type of the message. + msg->setType(DestType.getNonReferenceType()); + msg->setValueKind(Expr::getValueKindForType(DestType)); + + return S.MaybeBindToTemporary(msg); +} + +ExprResult RebuildUnknownAnyExpr::VisitImplicitCastExpr(ImplicitCastExpr *ice) { + // The only case we should ever see here is a function-to-pointer decay. + assert(ice->getCastKind() == CK_FunctionToPointerDecay); + assert(ice->getValueKind() == VK_RValue); + assert(ice->getObjectKind() == OK_Ordinary); + + ice->setType(DestType); + + // Rebuild the sub-expression as the pointee (function) type. + DestType = DestType->castAs<PointerType>()->getPointeeType(); + + ExprResult result = Visit(ice->getSubExpr()); + if (!result.isUsable()) return ExprError(); + + ice->setSubExpr(result.take()); + return S.Owned(ice); +} + +ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, ValueDecl *decl) { + ExprValueKind valueKind = VK_LValue; + QualType type = DestType; + + // We know how to make this work for certain kinds of decls: + + // - functions + if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { + // This is true because FunctionDecls must always have function + // type, so we can't be resolving the entire thing at once. + assert(type->isFunctionType()); + + if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(fn)) + if (method->isInstance()) { + valueKind = VK_RValue; + type = S.Context.BoundMemberTy; + } + + // Function references aren't l-values in C. + if (!S.getLangOptions().CPlusPlus) + valueKind = VK_RValue; + + // - variables + } else if (isa<VarDecl>(decl)) { + if (const ReferenceType *refTy = type->getAs<ReferenceType>()) { + type = refTy->getPointeeType(); + } else if (type->isFunctionType()) { + S.Diag(expr->getExprLoc(), diag::err_unknown_any_var_function_type) + << decl << expr->getSourceRange(); + return ExprError(); + } + + // - nothing else + } else { + S.Diag(expr->getExprLoc(), diag::err_unsupported_unknown_any_decl) + << decl << expr->getSourceRange(); + return ExprError(); + } + + decl->setType(DestType); + expr->setType(type); + expr->setValueKind(valueKind); + return S.Owned(expr); +} + +/// Check a cast of an unknown-any type. We intentionally only +/// trigger this for C-style casts. +ExprResult Sema::checkUnknownAnyCast(SourceRange typeRange, QualType castType, + Expr *castExpr, CastKind &castKind, + ExprValueKind &VK, CXXCastPath &path) { + // Rewrite the casted expression from scratch. + ExprResult result = RebuildUnknownAnyExpr(*this, castType).Visit(castExpr); + if (!result.isUsable()) return ExprError(); + + castExpr = result.take(); + VK = castExpr->getValueKind(); + castKind = CK_NoOp; + + return castExpr; +} + +static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *e) { + Expr *orig = e; + unsigned diagID = diag::err_uncasted_use_of_unknown_any; + while (true) { + e = e->IgnoreParenImpCasts(); + if (CallExpr *call = dyn_cast<CallExpr>(e)) { + e = call->getCallee(); + diagID = diag::err_uncasted_call_of_unknown_any; + } else { + break; + } + } + + SourceLocation loc; + NamedDecl *d; + if (DeclRefExpr *ref = dyn_cast<DeclRefExpr>(e)) { + loc = ref->getLocation(); + d = ref->getDecl(); + } else if (MemberExpr *mem = dyn_cast<MemberExpr>(e)) { + loc = mem->getMemberLoc(); + d = mem->getMemberDecl(); + } else if (ObjCMessageExpr *msg = dyn_cast<ObjCMessageExpr>(e)) { + diagID = diag::err_uncasted_call_of_unknown_any; + loc = msg->getSelectorLoc(); + d = msg->getMethodDecl(); + assert(d && "unknown method returning __unknown_any?"); + } else { + S.Diag(e->getExprLoc(), diag::err_unsupported_unknown_any_expr) + << e->getSourceRange(); + return ExprError(); + } + + S.Diag(loc, diagID) << d << orig->getSourceRange(); + + // Never recoverable. + return ExprError(); +} + +/// Check for operands with placeholder types and complain if found. +/// Returns true if there was an error and no recovery was possible. +ExprResult Sema::CheckPlaceholderExpr(Expr *E) { + // Placeholder types are always *exactly* the appropriate builtin type. + QualType type = E->getType(); + + // Overloaded expressions. + if (type == Context.OverloadTy) + return ResolveAndFixSingleFunctionTemplateSpecialization(E, false, true, + E->getSourceRange(), + QualType(), + diag::err_ovl_unresolvable); + + // Bound member functions. + if (type == Context.BoundMemberTy) { + Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) + << E->getSourceRange(); + return ExprError(); + } + + // Expressions of unknown type. + if (type == Context.UnknownAnyTy) + return diagnoseUnknownAnyExpr(*this, E); + + assert(!type->isPlaceholderType()); + return Owned(E); +} + +bool Sema::CheckCaseExpression(Expr *expr) { + if (expr->isTypeDependent()) + return true; + if (expr->isValueDependent() || expr->isIntegerConstantExpr(Context)) + return expr->getType()->isIntegralOrEnumerationType(); + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp new file mode 100644 index 0000000..2f5a890 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -0,0 +1,4369 @@ +//===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for C++ expressions. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; +using namespace sema; + +ParsedType Sema::getDestructorName(SourceLocation TildeLoc, + IdentifierInfo &II, + SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + ParsedType ObjectTypePtr, + bool EnteringContext) { + // Determine where to perform name lookup. + + // FIXME: This area of the standard is very messy, and the current + // wording is rather unclear about which scopes we search for the + // destructor name; see core issues 399 and 555. Issue 399 in + // particular shows where the current description of destructor name + // lookup is completely out of line with existing practice, e.g., + // this appears to be ill-formed: + // + // namespace N { + // template <typename T> struct S { + // ~S(); + // }; + // } + // + // void f(N::S<int>* s) { + // s->N::S<int>::~S(); + // } + // + // See also PR6358 and PR6359. + // For this reason, we're currently only doing the C++03 version of this + // code; the C++0x version has to wait until we get a proper spec. + QualType SearchType; + DeclContext *LookupCtx = 0; + bool isDependent = false; + bool LookInScope = false; + + // If we have an object type, it's because we are in a + // pseudo-destructor-expression or a member access expression, and + // we know what type we're looking for. + if (ObjectTypePtr) + SearchType = GetTypeFromParser(ObjectTypePtr); + + if (SS.isSet()) { + NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); + + bool AlreadySearched = false; + bool LookAtPrefix = true; + // C++ [basic.lookup.qual]p6: + // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier, + // the type-names are looked up as types in the scope designated by the + // nested-name-specifier. In a qualified-id of the form: + // + // ::[opt] nested-name-specifier ~ class-name + // + // where the nested-name-specifier designates a namespace scope, and in + // a qualified-id of the form: + // + // ::opt nested-name-specifier class-name :: ~ class-name + // + // the class-names are looked up as types in the scope designated by + // the nested-name-specifier. + // + // Here, we check the first case (completely) and determine whether the + // code below is permitted to look at the prefix of the + // nested-name-specifier. + DeclContext *DC = computeDeclContext(SS, EnteringContext); + if (DC && DC->isFileContext()) { + AlreadySearched = true; + LookupCtx = DC; + isDependent = false; + } else if (DC && isa<CXXRecordDecl>(DC)) + LookAtPrefix = false; + + // The second case from the C++03 rules quoted further above. + NestedNameSpecifier *Prefix = 0; + if (AlreadySearched) { + // Nothing left to do. + } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) { + CXXScopeSpec PrefixSS; + PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data())); + LookupCtx = computeDeclContext(PrefixSS, EnteringContext); + isDependent = isDependentScopeSpecifier(PrefixSS); + } else if (ObjectTypePtr) { + LookupCtx = computeDeclContext(SearchType); + isDependent = SearchType->isDependentType(); + } else { + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = LookupCtx && LookupCtx->isDependentContext(); + } + + LookInScope = false; + } else if (ObjectTypePtr) { + // C++ [basic.lookup.classref]p3: + // If the unqualified-id is ~type-name, the type-name is looked up + // in the context of the entire postfix-expression. If the type T + // of the object expression is of a class type C, the type-name is + // also looked up in the scope of class C. At least one of the + // lookups shall find a name that refers to (possibly + // cv-qualified) T. + LookupCtx = computeDeclContext(SearchType); + isDependent = SearchType->isDependentType(); + assert((isDependent || !SearchType->isIncompleteType()) && + "Caller should have completed object type"); + + LookInScope = true; + } else { + // Perform lookup into the current scope (only). + LookInScope = true; + } + + TypeDecl *NonMatchingTypeDecl = 0; + LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName); + for (unsigned Step = 0; Step != 2; ++Step) { + // Look for the name first in the computed lookup context (if we + // have one) and, if that fails to find a match, in the scope (if + // we're allowed to look there). + Found.clear(); + if (Step == 0 && LookupCtx) + LookupQualifiedName(Found, LookupCtx); + else if (Step == 1 && LookInScope && S) + LookupName(Found, S); + else + continue; + + // FIXME: Should we be suppressing ambiguities here? + if (Found.isAmbiguous()) + return ParsedType(); + + if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) { + QualType T = Context.getTypeDeclType(Type); + + if (SearchType.isNull() || SearchType->isDependentType() || + Context.hasSameUnqualifiedType(T, SearchType)) { + // We found our type! + + return ParsedType::make(T); + } + + if (!SearchType.isNull()) + NonMatchingTypeDecl = Type; + } + + // If the name that we found is a class template name, and it is + // the same name as the template name in the last part of the + // nested-name-specifier (if present) or the object type, then + // this is the destructor for that class. + // FIXME: This is a workaround until we get real drafting for core + // issue 399, for which there isn't even an obvious direction. + if (ClassTemplateDecl *Template = Found.getAsSingle<ClassTemplateDecl>()) { + QualType MemberOfType; + if (SS.isSet()) { + if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) { + // Figure out the type of the context, if it has one. + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) + MemberOfType = Context.getTypeDeclType(Record); + } + } + if (MemberOfType.isNull()) + MemberOfType = SearchType; + + if (MemberOfType.isNull()) + continue; + + // We're referring into a class template specialization. If the + // class template we found is the same as the template being + // specialized, we found what we are looking for. + if (const RecordType *Record = MemberOfType->getAs<RecordType>()) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) { + if (Spec->getSpecializedTemplate()->getCanonicalDecl() == + Template->getCanonicalDecl()) + return ParsedType::make(MemberOfType); + } + + continue; + } + + // We're referring to an unresolved class template + // specialization. Determine whether we class template we found + // is the same as the template being specialized or, if we don't + // know which template is being specialized, that it at least + // has the same name. + if (const TemplateSpecializationType *SpecType + = MemberOfType->getAs<TemplateSpecializationType>()) { + TemplateName SpecName = SpecType->getTemplateName(); + + // The class template we found is the same template being + // specialized. + if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) { + if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl()) + return ParsedType::make(MemberOfType); + + continue; + } + + // The class template we found has the same name as the + // (dependent) template name being specialized. + if (DependentTemplateName *DepTemplate + = SpecName.getAsDependentTemplateName()) { + if (DepTemplate->isIdentifier() && + DepTemplate->getIdentifier() == Template->getIdentifier()) + return ParsedType::make(MemberOfType); + + continue; + } + } + } + } + + if (isDependent) { + // We didn't find our type, but that's okay: it's dependent + // anyway. + + // FIXME: What if we have no nested-name-specifier? + QualType T = CheckTypenameType(ETK_None, SourceLocation(), + SS.getWithLocInContext(Context), + II, NameLoc); + return ParsedType::make(T); + } + + if (NonMatchingTypeDecl) { + QualType T = Context.getTypeDeclType(NonMatchingTypeDecl); + Diag(NameLoc, diag::err_destructor_expr_type_mismatch) + << T << SearchType; + Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here) + << T; + } else if (ObjectTypePtr) + Diag(NameLoc, diag::err_ident_in_dtor_not_a_type) + << &II; + else + Diag(NameLoc, diag::err_destructor_class_name); + + return ParsedType(); +} + +/// \brief Build a C++ typeid expression with a type operand. +ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + // C++ [expr.typeid]p4: + // The top-level cv-qualifiers of the lvalue expression or the type-id + // that is the operand of typeid are always ignored. + // If the type of the type-id is a class type or a reference to a class + // type, the class shall be completely-defined. + Qualifiers Quals; + QualType T + = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(), + Quals); + if (T->getAs<RecordType>() && + RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) + return ExprError(); + + return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(), + Operand, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// \brief Build a C++ typeid expression with an expression operand. +ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *E, + SourceLocation RParenLoc) { + bool isUnevaluatedOperand = true; + if (E && !E->isTypeDependent()) { + QualType T = E->getType(); + if (const RecordType *RecordT = T->getAs<RecordType>()) { + CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl()); + // C++ [expr.typeid]p3: + // [...] If the type of the expression is a class type, the class + // shall be completely-defined. + if (RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) + return ExprError(); + + // C++ [expr.typeid]p3: + // When typeid is applied to an expression other than an glvalue of a + // polymorphic class type [...] [the] expression is an unevaluated + // operand. [...] + if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) { + isUnevaluatedOperand = false; + + // We require a vtable to query the type at run time. + MarkVTableUsed(TypeidLoc, RecordD); + } + } + + // C++ [expr.typeid]p4: + // [...] If the type of the type-id is a reference to a possibly + // cv-qualified type, the result of the typeid expression refers to a + // std::type_info object representing the cv-unqualified referenced + // type. + Qualifiers Quals; + QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals); + if (!Context.hasSameType(T, UnqualT)) { + T = UnqualT; + E = ImpCastExprToType(E, UnqualT, CK_NoOp, CastCategory(E)).take(); + } + } + + // If this is an unevaluated operand, clear out the set of + // declaration references we have been computing and eliminate any + // temporaries introduced in its computation. + if (isUnevaluatedOperand) + ExprEvalContexts.back().Context = Unevaluated; + + return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(), + E, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression); +ExprResult +Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + // Find the std::type_info type. + if (!getStdNamespace()) + return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); + + if (!CXXTypeInfoDecl) { + IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); + LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); + LookupQualifiedName(R, getStdNamespace()); + CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); + if (!CXXTypeInfoDecl) + return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); + } + + QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl); + + if (isType) { + // The operand is a type; handle it as such. + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), + &TInfo); + if (T.isNull()) + return ExprError(); + + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); + + return BuildCXXTypeId(TypeInfoType, OpLoc, TInfo, RParenLoc); + } + + // The operand is an expression. + return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); +} + +/// Retrieve the UuidAttr associated with QT. +static UuidAttr *GetUuidAttrOfType(QualType QT) { + // Optionally remove one level of pointer, reference or array indirection. + const Type *Ty = QT.getTypePtr();; + if (QT->isPointerType() || QT->isReferenceType()) + Ty = QT->getPointeeType().getTypePtr(); + else if (QT->isArrayType()) + Ty = cast<ArrayType>(QT)->getElementType().getTypePtr(); + + // Loop all record redeclaration looking for an uuid attribute. + CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); + for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), + E = RD->redecls_end(); I != E; ++I) { + if (UuidAttr *Uuid = I->getAttr<UuidAttr>()) + return Uuid; + } + + return 0; +} + +/// \brief Build a Microsoft __uuidof expression with a type operand. +ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + if (!Operand->getType()->isDependentType()) { + if (!GetUuidAttrOfType(Operand->getType())) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + } + + // FIXME: add __uuidof semantic analysis for type operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), + Operand, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// \brief Build a Microsoft __uuidof expression with an expression operand. +ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *E, + SourceLocation RParenLoc) { + if (!E->getType()->isDependentType()) { + if (!GetUuidAttrOfType(E->getType()) && + !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); + } + // FIXME: add __uuidof semantic analysis for type operand. + return Owned(new (Context) CXXUuidofExpr(TypeInfoType.withConst(), + E, + SourceRange(TypeidLoc, RParenLoc))); +} + +/// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression); +ExprResult +Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc, + bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + // If MSVCGuidDecl has not been cached, do the lookup. + if (!MSVCGuidDecl) { + IdentifierInfo *GuidII = &PP.getIdentifierTable().get("_GUID"); + LookupResult R(*this, GuidII, SourceLocation(), LookupTagName); + LookupQualifiedName(R, Context.getTranslationUnitDecl()); + MSVCGuidDecl = R.getAsSingle<RecordDecl>(); + if (!MSVCGuidDecl) + return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof)); + } + + QualType GuidType = Context.getTypeDeclType(MSVCGuidDecl); + + if (isType) { + // The operand is a type; handle it as such. + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), + &TInfo); + if (T.isNull()) + return ExprError(); + + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); + + return BuildCXXUuidof(GuidType, OpLoc, TInfo, RParenLoc); + } + + // The operand is an expression. + return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc); +} + +/// ActOnCXXBoolLiteral - Parse {true,false} literals. +ExprResult +Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { + assert((Kind == tok::kw_true || Kind == tok::kw_false) && + "Unknown C++ Boolean value!"); + return Owned(new (Context) CXXBoolLiteralExpr(Kind == tok::kw_true, + Context.BoolTy, OpLoc)); +} + +/// ActOnCXXNullPtrLiteral - Parse 'nullptr'. +ExprResult +Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { + return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc)); +} + +/// ActOnCXXThrow - Parse throw expressions. +ExprResult +Sema::ActOnCXXThrow(SourceLocation OpLoc, Expr *Ex) { + // Don't report an error if 'throw' is used in system headers. + if (!getLangOptions().CXXExceptions && + !getSourceManager().isInSystemHeader(OpLoc)) + Diag(OpLoc, diag::err_exceptions_disabled) << "throw"; + + if (Ex && !Ex->isTypeDependent()) { + ExprResult ExRes = CheckCXXThrowOperand(OpLoc, Ex); + if (ExRes.isInvalid()) + return ExprError(); + Ex = ExRes.take(); + } + return Owned(new (Context) CXXThrowExpr(Ex, Context.VoidTy, OpLoc)); +} + +/// CheckCXXThrowOperand - Validate the operand of a throw. +ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E) { + // C++ [except.throw]p3: + // A throw-expression initializes a temporary object, called the exception + // object, the type of which is determined by removing any top-level + // cv-qualifiers from the static type of the operand of throw and adjusting + // the type from "array of T" or "function returning T" to "pointer to T" + // or "pointer to function returning T", [...] + if (E->getType().hasQualifiers()) + E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp, + CastCategory(E)).take(); + + ExprResult Res = DefaultFunctionArrayConversion(E); + if (Res.isInvalid()) + return ExprError(); + E = Res.take(); + + // If the type of the exception would be an incomplete type or a pointer + // to an incomplete type other than (cv) void the program is ill-formed. + QualType Ty = E->getType(); + bool isPointer = false; + if (const PointerType* Ptr = Ty->getAs<PointerType>()) { + Ty = Ptr->getPointeeType(); + isPointer = true; + } + if (!isPointer || !Ty->isVoidType()) { + if (RequireCompleteType(ThrowLoc, Ty, + PDiag(isPointer ? diag::err_throw_incomplete_ptr + : diag::err_throw_incomplete) + << E->getSourceRange())) + return ExprError(); + + if (RequireNonAbstractType(ThrowLoc, E->getType(), + PDiag(diag::err_throw_abstract_type) + << E->getSourceRange())) + return ExprError(); + } + + // Initialize the exception result. This implicitly weeds out + // abstract types or types with inaccessible copy constructors. + const VarDecl *NRVOVariable = getCopyElisionCandidate(QualType(), E, false); + + // FIXME: Determine whether we can elide this copy per C++0x [class.copy]p32. + InitializedEntity Entity = + InitializedEntity::InitializeException(ThrowLoc, E->getType(), + /*NRVO=*/false); + Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable, + QualType(), E); + if (Res.isInvalid()) + return ExprError(); + E = Res.take(); + + // If the exception has class type, we need additional handling. + const RecordType *RecordTy = Ty->getAs<RecordType>(); + if (!RecordTy) + return Owned(E); + CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); + + // If we are throwing a polymorphic class type or pointer thereof, + // exception handling will make use of the vtable. + MarkVTableUsed(ThrowLoc, RD); + + // If a pointer is thrown, the referenced object will not be destroyed. + if (isPointer) + return Owned(E); + + // If the class has a non-trivial destructor, we must be able to call it. + if (RD->hasTrivialDestructor()) + return Owned(E); + + CXXDestructorDecl *Destructor + = const_cast<CXXDestructorDecl*>(LookupDestructor(RD)); + if (!Destructor) + return Owned(E); + + MarkDeclarationReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_exception) << Ty); + return Owned(E); +} + +QualType Sema::getAndCaptureCurrentThisType() { + // Ignore block scopes: we can capture through them. + // Ignore nested enum scopes: we'll diagnose non-constant expressions + // where they're invalid, and other uses are legitimate. + // Don't ignore nested class scopes: you can't use 'this' in a local class. + DeclContext *DC = CurContext; + unsigned NumBlocks = 0; + while (true) { + if (isa<BlockDecl>(DC)) { + DC = cast<BlockDecl>(DC)->getDeclContext(); + ++NumBlocks; + } else if (isa<EnumDecl>(DC)) + DC = cast<EnumDecl>(DC)->getDeclContext(); + else break; + } + + QualType ThisTy; + if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) { + if (method && method->isInstance()) + ThisTy = method->getThisType(Context); + } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { + // C++0x [expr.prim]p4: + // Otherwise, if a member-declarator declares a non-static data member + // of a class X, the expression this is a prvalue of type "pointer to X" + // within the optional brace-or-equal-initializer. + Scope *S = getScopeForContext(DC); + if (!S || S->getFlags() & Scope::ThisScope) + ThisTy = Context.getPointerType(Context.getRecordType(RD)); + } + + // Mark that we're closing on 'this' in all the block scopes we ignored. + if (!ThisTy.isNull()) + for (unsigned idx = FunctionScopes.size() - 1; + NumBlocks; --idx, --NumBlocks) + cast<BlockScopeInfo>(FunctionScopes[idx])->CapturesCXXThis = true; + + return ThisTy; +} + +ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { + /// C++ 9.3.2: In the body of a non-static member function, the keyword this + /// is a non-lvalue expression whose value is the address of the object for + /// which the function is called. + + QualType ThisTy = getAndCaptureCurrentThisType(); + if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use); + + return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false)); +} + +ExprResult +Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, + SourceLocation LParenLoc, + MultiExprArg exprs, + SourceLocation RParenLoc) { + if (!TypeRep) + return ExprError(); + + TypeSourceInfo *TInfo; + QualType Ty = GetTypeFromParser(TypeRep, &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); + + return BuildCXXTypeConstructExpr(TInfo, LParenLoc, exprs, RParenLoc); +} + +/// ActOnCXXTypeConstructExpr - Parse construction of a specified type. +/// Can be interpreted either as function-style casting ("int(x)") +/// or class type construction ("ClassType(x,y,z)") +/// or creation of a value-initialized type ("int()"). +ExprResult +Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, + SourceLocation LParenLoc, + MultiExprArg exprs, + SourceLocation RParenLoc) { + QualType Ty = TInfo->getType(); + unsigned NumExprs = exprs.size(); + Expr **Exprs = (Expr**)exprs.get(); + SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); + SourceRange FullRange = SourceRange(TyBeginLoc, RParenLoc); + + if (Ty->isDependentType() || + CallExpr::hasAnyTypeDependentArguments(Exprs, NumExprs)) { + exprs.release(); + + return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo, + LParenLoc, + Exprs, NumExprs, + RParenLoc)); + } + + if (Ty->isArrayType()) + return ExprError(Diag(TyBeginLoc, + diag::err_value_init_for_array_type) << FullRange); + if (!Ty->isVoidType() && + RequireCompleteType(TyBeginLoc, Ty, + PDiag(diag::err_invalid_incomplete_type_use) + << FullRange)) + return ExprError(); + + if (RequireNonAbstractType(TyBeginLoc, Ty, + diag::err_allocation_of_abstract_type)) + return ExprError(); + + + // C++ [expr.type.conv]p1: + // If the expression list is a single expression, the type conversion + // expression is equivalent (in definedness, and if defined in meaning) to the + // corresponding cast expression. + // + if (NumExprs == 1) { + CastKind Kind = CK_Invalid; + ExprValueKind VK = VK_RValue; + CXXCastPath BasePath; + ExprResult CastExpr = + CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0], + Kind, VK, BasePath, + /*FunctionalStyle=*/true); + if (CastExpr.isInvalid()) + return ExprError(); + Exprs[0] = CastExpr.take(); + + exprs.release(); + + return Owned(CXXFunctionalCastExpr::Create(Context, + Ty.getNonLValueExprType(Context), + VK, TInfo, TyBeginLoc, Kind, + Exprs[0], &BasePath, + RParenLoc)); + } + + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); + InitializationKind Kind + = NumExprs ? InitializationKind::CreateDirect(TyBeginLoc, + LParenLoc, RParenLoc) + : InitializationKind::CreateValue(TyBeginLoc, + LParenLoc, RParenLoc); + InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs)); + + // FIXME: Improve AST representation? + return move(Result); +} + +/// doesUsualArrayDeleteWantSize - Answers whether the usual +/// operator delete[] for the given type has a size_t parameter. +static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, + QualType allocType) { + const RecordType *record = + allocType->getBaseElementTypeUnsafe()->getAs<RecordType>(); + if (!record) return false; + + // Try to find an operator delete[] in class scope. + + DeclarationName deleteName = + S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); + LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName); + S.LookupQualifiedName(ops, record->getDecl()); + + // We're just doing this for information. + ops.suppressDiagnostics(); + + // Very likely: there's no operator delete[]. + if (ops.empty()) return false; + + // If it's ambiguous, it should be illegal to call operator delete[] + // on this thing, so it doesn't matter if we allocate extra space or not. + if (ops.isAmbiguous()) return false; + + LookupResult::Filter filter = ops.makeFilter(); + while (filter.hasNext()) { + NamedDecl *del = filter.next()->getUnderlyingDecl(); + + // C++0x [basic.stc.dynamic.deallocation]p2: + // A template instance is never a usual deallocation function, + // regardless of its signature. + if (isa<FunctionTemplateDecl>(del)) { + filter.erase(); + continue; + } + + // C++0x [basic.stc.dynamic.deallocation]p2: + // If class T does not declare [an operator delete[] with one + // parameter] but does declare a member deallocation function + // named operator delete[] with exactly two parameters, the + // second of which has type std::size_t, then this function + // is a usual deallocation function. + if (!cast<CXXMethodDecl>(del)->isUsualDeallocationFunction()) { + filter.erase(); + continue; + } + } + filter.done(); + + if (!ops.isSingleResult()) return false; + + const FunctionDecl *del = cast<FunctionDecl>(ops.getFoundDecl()); + return (del->getNumParams() == 2); +} + +/// ActOnCXXNew - Parsed a C++ 'new' expression (C++ 5.3.4), as in e.g.: +/// @code new (memory) int[size][4] @endcode +/// or +/// @code ::new Foo(23, "hello") @endcode +/// For the interpretation of this heap of arguments, consult the base version. +ExprResult +Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, SourceRange TypeIdParens, + Declarator &D, SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen) { + bool TypeContainsAuto = D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; + + Expr *ArraySize = 0; + // If the specified type is an array, unwrap it and save the expression. + if (D.getNumTypeObjects() > 0 && + D.getTypeObject(0).Kind == DeclaratorChunk::Array) { + DeclaratorChunk &Chunk = D.getTypeObject(0); + if (TypeContainsAuto) + return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto) + << D.getSourceRange()); + if (Chunk.Arr.hasStatic) + return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new) + << D.getSourceRange()); + if (!Chunk.Arr.NumElts) + return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) + << D.getSourceRange()); + + ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts); + D.DropFirstTypeObject(); + } + + // Every dimension shall be of constant size. + if (ArraySize) { + for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) { + if (D.getTypeObject(I).Kind != DeclaratorChunk::Array) + break; + + DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; + if (Expr *NumElts = (Expr *)Array.NumElts) { + if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() && + !NumElts->isIntegerConstantExpr(Context)) { + Diag(D.getTypeObject(I).Loc, diag::err_new_array_nonconst) + << NumElts->getSourceRange(); + return ExprError(); + } + } + } + } + + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0, /*OwnedDecl=*/0, + /*AllowAuto=*/true); + QualType AllocType = TInfo->getType(); + if (D.isInvalidType()) + return ExprError(); + + return BuildCXXNew(StartLoc, UseGlobal, + PlacementLParen, + move(PlacementArgs), + PlacementRParen, + TypeIdParens, + AllocType, + TInfo, + ArraySize, + ConstructorLParen, + move(ConstructorArgs), + ConstructorRParen, + TypeContainsAuto); +} + +ExprResult +Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + SourceRange TypeIdParens, + QualType AllocType, + TypeSourceInfo *AllocTypeInfo, + Expr *ArraySize, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen, + bool TypeMayContainAuto) { + SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); + + // C++0x [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. + if (TypeMayContainAuto && AllocType->getContainedAutoType()) { + if (ConstructorArgs.size() == 0) + return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) + << AllocType << TypeRange); + if (ConstructorArgs.size() != 1) { + Expr *FirstBad = ConstructorArgs.get()[1]; + return ExprError(Diag(FirstBad->getSourceRange().getBegin(), + diag::err_auto_new_ctor_multiple_expressions) + << AllocType << TypeRange); + } + TypeSourceInfo *DeducedType = 0; + if (!DeduceAutoType(AllocTypeInfo, ConstructorArgs.get()[0], DeducedType)) + return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) + << AllocType + << ConstructorArgs.get()[0]->getType() + << TypeRange + << ConstructorArgs.get()[0]->getSourceRange()); + if (!DeducedType) + return ExprError(); + + AllocTypeInfo = DeducedType; + AllocType = AllocTypeInfo->getType(); + } + + // Per C++0x [expr.new]p5, the type being constructed may be a + // typedef of an array type. + if (!ArraySize) { + if (const ConstantArrayType *Array + = Context.getAsConstantArrayType(AllocType)) { + ArraySize = IntegerLiteral::Create(Context, Array->getSize(), + Context.getSizeType(), + TypeRange.getEnd()); + AllocType = Array->getElementType(); + } + } + + if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange)) + return ExprError(); + + QualType ResultType = Context.getPointerType(AllocType); + + // C++ 5.3.4p6: "The expression in a direct-new-declarator shall have integral + // or enumeration type with a non-negative value." + if (ArraySize && !ArraySize->isTypeDependent()) { + + QualType SizeType = ArraySize->getType(); + + ExprResult ConvertedSize + = ConvertToIntegralOrEnumerationType(StartLoc, ArraySize, + PDiag(diag::err_array_size_not_integral), + PDiag(diag::err_array_size_incomplete_type) + << ArraySize->getSourceRange(), + PDiag(diag::err_array_size_explicit_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(diag::err_array_size_ambiguous_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(getLangOptions().CPlusPlus0x? 0 + : diag::ext_array_size_conversion)); + if (ConvertedSize.isInvalid()) + return ExprError(); + + ArraySize = ConvertedSize.take(); + SizeType = ArraySize->getType(); + if (!SizeType->isIntegralOrUnscopedEnumerationType()) + return ExprError(); + + // Let's see if this is a constant < 0. If so, we reject it out of hand. + // We don't care about special rules, so we tell the machinery it's not + // evaluated - it gives us a result in more cases. + if (!ArraySize->isValueDependent()) { + llvm::APSInt Value; + if (ArraySize->isIntegerConstantExpr(Value, Context, 0, false)) { + if (Value < llvm::APSInt( + llvm::APInt::getNullValue(Value.getBitWidth()), + Value.isUnsigned())) + return ExprError(Diag(ArraySize->getSourceRange().getBegin(), + diag::err_typecheck_negative_array_size) + << ArraySize->getSourceRange()); + + if (!AllocType->isDependentType()) { + unsigned ActiveSizeBits + = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { + Diag(ArraySize->getSourceRange().getBegin(), + diag::err_array_too_large) + << Value.toString(10) + << ArraySize->getSourceRange(); + return ExprError(); + } + } + } else if (TypeIdParens.isValid()) { + // Can't have dynamic array size when the type-id is in parentheses. + Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst) + << ArraySize->getSourceRange() + << FixItHint::CreateRemoval(TypeIdParens.getBegin()) + << FixItHint::CreateRemoval(TypeIdParens.getEnd()); + + TypeIdParens = SourceRange(); + } + } + + // Note that we do *not* convert the argument in any way. It can + // be signed, larger than size_t, whatever. + } + + FunctionDecl *OperatorNew = 0; + FunctionDecl *OperatorDelete = 0; + Expr **PlaceArgs = (Expr**)PlacementArgs.get(); + unsigned NumPlaceArgs = PlacementArgs.size(); + + if (!AllocType->isDependentType() && + !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) && + FindAllocationFunctions(StartLoc, + SourceRange(PlacementLParen, PlacementRParen), + UseGlobal, AllocType, ArraySize, PlaceArgs, + NumPlaceArgs, OperatorNew, OperatorDelete)) + return ExprError(); + + // If this is an array allocation, compute whether the usual array + // deallocation function for the type has a size_t parameter. + bool UsualArrayDeleteWantsSize = false; + if (ArraySize && !AllocType->isDependentType()) + UsualArrayDeleteWantsSize + = doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType); + + llvm::SmallVector<Expr *, 8> AllPlaceArgs; + if (OperatorNew) { + // Add default arguments, if any. + const FunctionProtoType *Proto = + OperatorNew->getType()->getAs<FunctionProtoType>(); + VariadicCallType CallType = + Proto->isVariadic() ? VariadicFunction : VariadicDoesNotApply; + + if (GatherArgumentsForCall(PlacementLParen, OperatorNew, + Proto, 1, PlaceArgs, NumPlaceArgs, + AllPlaceArgs, CallType)) + return ExprError(); + + NumPlaceArgs = AllPlaceArgs.size(); + if (NumPlaceArgs > 0) + PlaceArgs = &AllPlaceArgs[0]; + } + + bool Init = ConstructorLParen.isValid(); + // --- Choosing a constructor --- + CXXConstructorDecl *Constructor = 0; + Expr **ConsArgs = (Expr**)ConstructorArgs.get(); + unsigned NumConsArgs = ConstructorArgs.size(); + ASTOwningVector<Expr*> ConvertedConstructorArgs(*this); + + // Array 'new' can't have any initializers. + if (NumConsArgs && (ResultType->isArrayType() || ArraySize)) { + SourceRange InitRange(ConsArgs[0]->getLocStart(), + ConsArgs[NumConsArgs - 1]->getLocEnd()); + + Diag(StartLoc, diag::err_new_array_init_args) << InitRange; + return ExprError(); + } + + if (!AllocType->isDependentType() && + !Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) { + // C++0x [expr.new]p15: + // A new-expression that creates an object of type T initializes that + // object as follows: + InitializationKind Kind + // - If the new-initializer is omitted, the object is default- + // initialized (8.5); if no initialization is performed, + // the object has indeterminate value + = !Init? InitializationKind::CreateDefault(TypeRange.getBegin()) + // - Otherwise, the new-initializer is interpreted according to the + // initialization rules of 8.5 for direct-initialization. + : InitializationKind::CreateDirect(TypeRange.getBegin(), + ConstructorLParen, + ConstructorRParen); + + InitializedEntity Entity + = InitializedEntity::InitializeNew(StartLoc, AllocType); + InitializationSequence InitSeq(*this, Entity, Kind, ConsArgs, NumConsArgs); + ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, + move(ConstructorArgs)); + if (FullInit.isInvalid()) + return ExprError(); + + // FullInit is our initializer; walk through it to determine if it's a + // constructor call, which CXXNewExpr handles directly. + if (Expr *FullInitExpr = (Expr *)FullInit.get()) { + if (CXXBindTemporaryExpr *Binder + = dyn_cast<CXXBindTemporaryExpr>(FullInitExpr)) + FullInitExpr = Binder->getSubExpr(); + if (CXXConstructExpr *Construct + = dyn_cast<CXXConstructExpr>(FullInitExpr)) { + Constructor = Construct->getConstructor(); + for (CXXConstructExpr::arg_iterator A = Construct->arg_begin(), + AEnd = Construct->arg_end(); + A != AEnd; ++A) + ConvertedConstructorArgs.push_back(*A); + } else { + // Take the converted initializer. + ConvertedConstructorArgs.push_back(FullInit.release()); + } + } else { + // No initialization required. + } + + // Take the converted arguments and use them for the new expression. + NumConsArgs = ConvertedConstructorArgs.size(); + ConsArgs = (Expr **)ConvertedConstructorArgs.take(); + } + + // Mark the new and delete operators as referenced. + if (OperatorNew) + MarkDeclarationReferenced(StartLoc, OperatorNew); + if (OperatorDelete) + MarkDeclarationReferenced(StartLoc, OperatorDelete); + + // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16) + + PlacementArgs.release(); + ConstructorArgs.release(); + + return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, + PlaceArgs, NumPlaceArgs, TypeIdParens, + ArraySize, Constructor, Init, + ConsArgs, NumConsArgs, OperatorDelete, + UsualArrayDeleteWantsSize, + ResultType, AllocTypeInfo, + StartLoc, + Init ? ConstructorRParen : + TypeRange.getEnd(), + ConstructorLParen, ConstructorRParen)); +} + +/// CheckAllocatedType - Checks that a type is suitable as the allocated type +/// in a new-expression. +/// dimension off and stores the size expression in ArraySize. +bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, + SourceRange R) { + // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an + // abstract class type or array thereof. + if (AllocType->isFunctionType()) + return Diag(Loc, diag::err_bad_new_type) + << AllocType << 0 << R; + else if (AllocType->isReferenceType()) + return Diag(Loc, diag::err_bad_new_type) + << AllocType << 1 << R; + else if (!AllocType->isDependentType() && + RequireCompleteType(Loc, AllocType, + PDiag(diag::err_new_incomplete_type) + << R)) + return true; + else if (RequireNonAbstractType(Loc, AllocType, + diag::err_allocation_of_abstract_type)) + return true; + else if (AllocType->isVariablyModifiedType()) + return Diag(Loc, diag::err_variably_modified_new_type) + << AllocType; + else if (unsigned AddressSpace = AllocType.getAddressSpace()) + return Diag(Loc, diag::err_address_space_qualified_new) + << AllocType.getUnqualifiedType() << AddressSpace; + + return false; +} + +/// \brief Determine whether the given function is a non-placement +/// deallocation function. +static bool isNonPlacementDeallocationFunction(FunctionDecl *FD) { + if (FD->isInvalidDecl()) + return false; + + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) + return Method->isUsualDeallocationFunction(); + + return ((FD->getOverloadedOperator() == OO_Delete || + FD->getOverloadedOperator() == OO_Array_Delete) && + FD->getNumParams() == 1); +} + +/// FindAllocationFunctions - Finds the overloads of operator new and delete +/// that are appropriate for the allocation. +bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, + bool UseGlobal, QualType AllocType, + bool IsArray, Expr **PlaceArgs, + unsigned NumPlaceArgs, + FunctionDecl *&OperatorNew, + FunctionDecl *&OperatorDelete) { + // --- Choosing an allocation function --- + // C++ 5.3.4p8 - 14 & 18 + // 1) If UseGlobal is true, only look in the global scope. Else, also look + // in the scope of the allocated class. + // 2) If an array size is given, look for operator new[], else look for + // operator new. + // 3) The first argument is always size_t. Append the arguments from the + // placement form. + + llvm::SmallVector<Expr*, 8> AllocArgs(1 + NumPlaceArgs); + // We don't care about the actual value of this argument. + // FIXME: Should the Sema create the expression and embed it in the syntax + // tree? Or should the consumer just recalculate the value? + IntegerLiteral Size(Context, llvm::APInt::getNullValue( + Context.Target.getPointerWidth(0)), + Context.getSizeType(), + SourceLocation()); + AllocArgs[0] = &Size; + std::copy(PlaceArgs, PlaceArgs + NumPlaceArgs, AllocArgs.begin() + 1); + + // C++ [expr.new]p8: + // If the allocated type is a non-array type, the allocation + // function's name is operator new and the deallocation function's + // name is operator delete. If the allocated type is an array + // type, the allocation function's name is operator new[] and the + // deallocation function's name is operator delete[]. + DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName( + IsArray ? OO_Array_New : OO_New); + DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( + IsArray ? OO_Array_Delete : OO_Delete); + + QualType AllocElemType = Context.getBaseElementType(AllocType); + + if (AllocElemType->isRecordType() && !UseGlobal) { + CXXRecordDecl *Record + = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl()); + if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0], + AllocArgs.size(), Record, /*AllowMissing=*/true, + OperatorNew)) + return true; + } + if (!OperatorNew) { + // Didn't find a member overload. Look for a global one. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + if (FindAllocationOverload(StartLoc, Range, NewName, &AllocArgs[0], + AllocArgs.size(), TUDecl, /*AllowMissing=*/false, + OperatorNew)) + return true; + } + + // We don't need an operator delete if we're running under + // -fno-exceptions. + if (!getLangOptions().Exceptions) { + OperatorDelete = 0; + return false; + } + + // FindAllocationOverload can change the passed in arguments, so we need to + // copy them back. + if (NumPlaceArgs > 0) + std::copy(&AllocArgs[1], AllocArgs.end(), PlaceArgs); + + // C++ [expr.new]p19: + // + // If the new-expression begins with a unary :: operator, the + // deallocation function's name is looked up in the global + // scope. Otherwise, if the allocated type is a class type T or an + // array thereof, the deallocation function's name is looked up in + // the scope of T. If this lookup fails to find the name, or if + // the allocated type is not a class type or array thereof, the + // deallocation function's name is looked up in the global scope. + LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName); + if (AllocElemType->isRecordType() && !UseGlobal) { + CXXRecordDecl *RD + = cast<CXXRecordDecl>(AllocElemType->getAs<RecordType>()->getDecl()); + LookupQualifiedName(FoundDelete, RD); + } + if (FoundDelete.isAmbiguous()) + return true; // FIXME: clean up expressions? + + if (FoundDelete.empty()) { + DeclareGlobalNewDelete(); + LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl()); + } + + FoundDelete.suppressDiagnostics(); + + llvm::SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches; + + // Whether we're looking for a placement operator delete is dictated + // by whether we selected a placement operator new, not by whether + // we had explicit placement arguments. This matters for things like + // struct A { void *operator new(size_t, int = 0); ... }; + // A *a = new A() + bool isPlacementNew = (NumPlaceArgs > 0 || OperatorNew->param_size() != 1); + + if (isPlacementNew) { + // C++ [expr.new]p20: + // A declaration of a placement deallocation function matches the + // declaration of a placement allocation function if it has the + // same number of parameters and, after parameter transformations + // (8.3.5), all parameter types except the first are + // identical. [...] + // + // To perform this comparison, we compute the function type that + // the deallocation function should have, and use that type both + // for template argument deduction and for comparison purposes. + // + // FIXME: this comparison should ignore CC and the like. + QualType ExpectedFunctionType; + { + const FunctionProtoType *Proto + = OperatorNew->getType()->getAs<FunctionProtoType>(); + + llvm::SmallVector<QualType, 4> ArgTypes; + ArgTypes.push_back(Context.VoidPtrTy); + for (unsigned I = 1, N = Proto->getNumArgs(); I < N; ++I) + ArgTypes.push_back(Proto->getArgType(I)); + + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = Proto->isVariadic(); + + ExpectedFunctionType + = Context.getFunctionType(Context.VoidTy, ArgTypes.data(), + ArgTypes.size(), EPI); + } + + for (LookupResult::iterator D = FoundDelete.begin(), + DEnd = FoundDelete.end(); + D != DEnd; ++D) { + FunctionDecl *Fn = 0; + if (FunctionTemplateDecl *FnTmpl + = dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) { + // Perform template argument deduction to try to match the + // expected function type. + TemplateDeductionInfo Info(Context, StartLoc); + if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info)) + continue; + } else + Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl()); + + if (Context.hasSameType(Fn->getType(), ExpectedFunctionType)) + Matches.push_back(std::make_pair(D.getPair(), Fn)); + } + } else { + // C++ [expr.new]p20: + // [...] Any non-placement deallocation function matches a + // non-placement allocation function. [...] + for (LookupResult::iterator D = FoundDelete.begin(), + DEnd = FoundDelete.end(); + D != DEnd; ++D) { + if (FunctionDecl *Fn = dyn_cast<FunctionDecl>((*D)->getUnderlyingDecl())) + if (isNonPlacementDeallocationFunction(Fn)) + Matches.push_back(std::make_pair(D.getPair(), Fn)); + } + } + + // C++ [expr.new]p20: + // [...] If the lookup finds a single matching deallocation + // function, that function will be called; otherwise, no + // deallocation function will be called. + if (Matches.size() == 1) { + OperatorDelete = Matches[0].second; + + // C++0x [expr.new]p20: + // If the lookup finds the two-parameter form of a usual + // deallocation function (3.7.4.2) and that function, considered + // as a placement deallocation function, would have been + // selected as a match for the allocation function, the program + // is ill-formed. + if (NumPlaceArgs && getLangOptions().CPlusPlus0x && + isNonPlacementDeallocationFunction(OperatorDelete)) { + Diag(StartLoc, diag::err_placement_new_non_placement_delete) + << SourceRange(PlaceArgs[0]->getLocStart(), + PlaceArgs[NumPlaceArgs - 1]->getLocEnd()); + Diag(OperatorDelete->getLocation(), diag::note_previous_decl) + << DeleteName; + } else { + CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(), + Matches[0].first); + } + } + + return false; +} + +/// FindAllocationOverload - Find an fitting overload for the allocation +/// function in the specified scope. +bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, + DeclarationName Name, Expr** Args, + unsigned NumArgs, DeclContext *Ctx, + bool AllowMissing, FunctionDecl *&Operator, + bool Diagnose) { + LookupResult R(*this, Name, StartLoc, LookupOrdinaryName); + LookupQualifiedName(R, Ctx); + if (R.empty()) { + if (AllowMissing || !Diagnose) + return false; + return Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) + << Name << Range; + } + + if (R.isAmbiguous()) + return true; + + R.suppressDiagnostics(); + + OverloadCandidateSet Candidates(StartLoc); + for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end(); + Alloc != AllocEnd; ++Alloc) { + // Even member operator new/delete are implicitly treated as + // static, so don't use AddMemberCandidate. + NamedDecl *D = (*Alloc)->getUnderlyingDecl(); + + if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) { + AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(), + /*ExplicitTemplateArgs=*/0, Args, NumArgs, + Candidates, + /*SuppressUserConversions=*/false); + continue; + } + + FunctionDecl *Fn = cast<FunctionDecl>(D); + AddOverloadCandidate(Fn, Alloc.getPair(), Args, NumArgs, Candidates, + /*SuppressUserConversions=*/false); + } + + // Do the resolution. + OverloadCandidateSet::iterator Best; + switch (Candidates.BestViableFunction(*this, StartLoc, Best)) { + case OR_Success: { + // Got one! + FunctionDecl *FnDecl = Best->Function; + MarkDeclarationReferenced(StartLoc, FnDecl); + // The first argument is size_t, and the first parameter must be size_t, + // too. This is checked on declaration and can be assumed. (It can't be + // asserted on, though, since invalid decls are left in there.) + // Watch out for variadic allocator function. + unsigned NumArgsInFnDecl = FnDecl->getNumParams(); + for (unsigned i = 0; (i < NumArgs && i < NumArgsInFnDecl); ++i) { + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(i)); + + if (!Diagnose && !CanPerformCopyInitialization(Entity, Owned(Args[i]))) + return true; + + ExprResult Result + = PerformCopyInitialization(Entity, SourceLocation(), Owned(Args[i])); + if (Result.isInvalid()) + return true; + + Args[i] = Result.takeAs<Expr>(); + } + Operator = FnDecl; + CheckAllocationAccess(StartLoc, Range, R.getNamingClass(), Best->FoundDecl, + Diagnose); + return false; + } + + case OR_No_Viable_Function: + if (Diagnose) { + Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) + << Name << Range; + Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + } + return true; + + case OR_Ambiguous: + if (Diagnose) { + Diag(StartLoc, diag::err_ovl_ambiguous_call) + << Name << Range; + Candidates.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); + } + return true; + + case OR_Deleted: { + if (Diagnose) { + Diag(StartLoc, diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << Name + << getDeletedOrUnavailableSuffix(Best->Function) + << Range; + Candidates.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + } + return true; + } + } + assert(false && "Unreachable, bad result from BestViableFunction"); + return true; +} + + +/// DeclareGlobalNewDelete - Declare the global forms of operator new and +/// delete. These are: +/// @code +/// // C++03: +/// void* operator new(std::size_t) throw(std::bad_alloc); +/// void* operator new[](std::size_t) throw(std::bad_alloc); +/// void operator delete(void *) throw(); +/// void operator delete[](void *) throw(); +/// // C++0x: +/// void* operator new(std::size_t); +/// void* operator new[](std::size_t); +/// void operator delete(void *); +/// void operator delete[](void *); +/// @endcode +/// C++0x operator delete is implicitly noexcept. +/// Note that the placement and nothrow forms of new are *not* implicitly +/// declared. Their use requires including \<new\>. +void Sema::DeclareGlobalNewDelete() { + if (GlobalNewDeleteDeclared) + return; + + // C++ [basic.std.dynamic]p2: + // [...] The following allocation and deallocation functions (18.4) are + // implicitly declared in global scope in each translation unit of a + // program + // + // C++03: + // void* operator new(std::size_t) throw(std::bad_alloc); + // void* operator new[](std::size_t) throw(std::bad_alloc); + // void operator delete(void*) throw(); + // void operator delete[](void*) throw(); + // C++0x: + // void* operator new(std::size_t); + // void* operator new[](std::size_t); + // void operator delete(void*); + // void operator delete[](void*); + // + // These implicit declarations introduce only the function names operator + // new, operator new[], operator delete, operator delete[]. + // + // Here, we need to refer to std::bad_alloc, so we will implicitly declare + // "std" or "bad_alloc" as necessary to form the exception specification. + // However, we do not make these implicit declarations visible to name + // lookup. + // Note that the C++0x versions of operator delete are deallocation functions, + // and thus are implicitly noexcept. + if (!StdBadAlloc && !getLangOptions().CPlusPlus0x) { + // The "std::bad_alloc" class has not yet been declared, so build it + // implicitly. + StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, + getOrCreateStdNamespace(), + SourceLocation(), SourceLocation(), + &PP.getIdentifierTable().get("bad_alloc"), + 0); + getStdBadAlloc()->setImplicit(true); + } + + GlobalNewDeleteDeclared = true; + + QualType VoidPtr = Context.getPointerType(Context.VoidTy); + QualType SizeT = Context.getSizeType(); + bool AssumeSaneOperatorNew = getLangOptions().AssumeSaneOperatorNew; + + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_New), + VoidPtr, SizeT, AssumeSaneOperatorNew); + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Array_New), + VoidPtr, SizeT, AssumeSaneOperatorNew); + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Delete), + Context.VoidTy, VoidPtr); + DeclareGlobalAllocationFunction( + Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete), + Context.VoidTy, VoidPtr); +} + +/// DeclareGlobalAllocationFunction - Declares a single implicit global +/// allocation function if it doesn't already exist. +void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, + QualType Return, QualType Argument, + bool AddMallocAttr) { + DeclContext *GlobalCtx = Context.getTranslationUnitDecl(); + + // Check if this function is already declared. + { + DeclContext::lookup_iterator Alloc, AllocEnd; + for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name); + Alloc != AllocEnd; ++Alloc) { + // Only look at non-template functions, as it is the predefined, + // non-templated allocation function we are trying to declare here. + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) { + QualType InitialParamType = + Context.getCanonicalType( + Func->getParamDecl(0)->getType().getUnqualifiedType()); + // FIXME: Do we need to check for default arguments here? + if (Func->getNumParams() == 1 && InitialParamType == Argument) { + if(AddMallocAttr && !Func->hasAttr<MallocAttr>()) + Func->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); + return; + } + } + } + } + + QualType BadAllocType; + bool HasBadAllocExceptionSpec + = (Name.getCXXOverloadedOperator() == OO_New || + Name.getCXXOverloadedOperator() == OO_Array_New); + if (HasBadAllocExceptionSpec && !getLangOptions().CPlusPlus0x) { + assert(StdBadAlloc && "Must have std::bad_alloc declared"); + BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); + } + + FunctionProtoType::ExtProtoInfo EPI; + if (HasBadAllocExceptionSpec) { + if (!getLangOptions().CPlusPlus0x) { + EPI.ExceptionSpecType = EST_Dynamic; + EPI.NumExceptions = 1; + EPI.Exceptions = &BadAllocType; + } + } else { + EPI.ExceptionSpecType = getLangOptions().CPlusPlus0x ? + EST_BasicNoexcept : EST_DynamicNone; + } + + QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI); + FunctionDecl *Alloc = + FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), + SourceLocation(), Name, + FnType, /*TInfo=*/0, SC_None, + SC_None, false, true); + Alloc->setImplicit(); + + if (AddMallocAttr) + Alloc->addAttr(::new (Context) MallocAttr(SourceLocation(), Context)); + + ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), + SourceLocation(), 0, + Argument, /*TInfo=*/0, + SC_None, SC_None, 0); + Alloc->setParams(&Param, 1); + + // FIXME: Also add this declaration to the IdentifierResolver, but + // make sure it is at the end of the chain to coincide with the + // global scope. + Context.getTranslationUnitDecl()->addDecl(Alloc); +} + +bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, + DeclarationName Name, + FunctionDecl* &Operator, bool Diagnose) { + LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName); + // Try to find operator delete/operator delete[] in class scope. + LookupQualifiedName(Found, RD); + + if (Found.isAmbiguous()) + return true; + + Found.suppressDiagnostics(); + + llvm::SmallVector<DeclAccessPair,4> Matches; + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) { + NamedDecl *ND = (*F)->getUnderlyingDecl(); + + // Ignore template operator delete members from the check for a usual + // deallocation function. + if (isa<FunctionTemplateDecl>(ND)) + continue; + + if (cast<CXXMethodDecl>(ND)->isUsualDeallocationFunction()) + Matches.push_back(F.getPair()); + } + + // There's exactly one suitable operator; pick it. + if (Matches.size() == 1) { + Operator = cast<CXXMethodDecl>(Matches[0]->getUnderlyingDecl()); + + if (Operator->isDeleted()) { + if (Diagnose) { + Diag(StartLoc, diag::err_deleted_function_use); + Diag(Operator->getLocation(), diag::note_unavailable_here) << true; + } + return true; + } + + CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), + Matches[0], Diagnose); + return false; + + // We found multiple suitable operators; complain about the ambiguity. + } else if (!Matches.empty()) { + if (Diagnose) { + Diag(StartLoc, diag::err_ambiguous_suitable_delete_member_function_found) + << Name << RD; + + for (llvm::SmallVectorImpl<DeclAccessPair>::iterator + F = Matches.begin(), FEnd = Matches.end(); F != FEnd; ++F) + Diag((*F)->getUnderlyingDecl()->getLocation(), + diag::note_member_declared_here) << Name; + } + return true; + } + + // We did find operator delete/operator delete[] declarations, but + // none of them were suitable. + if (!Found.empty()) { + if (Diagnose) { + Diag(StartLoc, diag::err_no_suitable_delete_member_function_found) + << Name << RD; + + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); + F != FEnd; ++F) + Diag((*F)->getUnderlyingDecl()->getLocation(), + diag::note_member_declared_here) << Name; + } + return true; + } + + // Look for a global declaration. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + + CXXNullPtrLiteralExpr Null(Context.VoidPtrTy, SourceLocation()); + Expr* DeallocArgs[1]; + DeallocArgs[0] = &Null; + if (FindAllocationOverload(StartLoc, SourceRange(), Name, + DeallocArgs, 1, TUDecl, !Diagnose, + Operator, Diagnose)) + return true; + + assert(Operator && "Did not find a deallocation function!"); + return false; +} + +/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: +/// @code ::delete ptr; @endcode +/// or +/// @code delete [] ptr; @endcode +ExprResult +Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, + bool ArrayForm, Expr *ExE) { + // C++ [expr.delete]p1: + // The operand shall have a pointer type, or a class type having a single + // conversion function to a pointer type. The result has type void. + // + // DR599 amends "pointer type" to "pointer to object type" in both cases. + + ExprResult Ex = Owned(ExE); + FunctionDecl *OperatorDelete = 0; + bool ArrayFormAsWritten = ArrayForm; + bool UsualArrayDeleteWantsSize = false; + + if (!Ex.get()->isTypeDependent()) { + QualType Type = Ex.get()->getType(); + + if (const RecordType *Record = Type->getAs<RecordType>()) { + if (RequireCompleteType(StartLoc, Type, + PDiag(diag::err_delete_incomplete_class_type))) + return ExprError(); + + llvm::SmallVector<CXXConversionDecl*, 4> ObjectPtrConversions; + + CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); + const UnresolvedSetImpl *Conversions = RD->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = I.getDecl(); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + // Skip over templated conversion functions; they aren't considered. + if (isa<FunctionTemplateDecl>(D)) + continue; + + CXXConversionDecl *Conv = cast<CXXConversionDecl>(D); + + QualType ConvType = Conv->getConversionType().getNonReferenceType(); + if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) + if (ConvPtrType->getPointeeType()->isIncompleteOrObjectType()) + ObjectPtrConversions.push_back(Conv); + } + if (ObjectPtrConversions.size() == 1) { + // We have a single conversion to a pointer-to-object type. Perform + // that conversion. + // TODO: don't redo the conversion calculation. + ExprResult Res = + PerformImplicitConversion(Ex.get(), + ObjectPtrConversions.front()->getConversionType(), + AA_Converting); + if (Res.isUsable()) { + Ex = move(Res); + Type = Ex.get()->getType(); + } + } + else if (ObjectPtrConversions.size() > 1) { + Diag(StartLoc, diag::err_ambiguous_delete_operand) + << Type << Ex.get()->getSourceRange(); + for (unsigned i= 0; i < ObjectPtrConversions.size(); i++) + NoteOverloadCandidate(ObjectPtrConversions[i]); + return ExprError(); + } + } + + if (!Type->isPointerType()) + return ExprError(Diag(StartLoc, diag::err_delete_operand) + << Type << Ex.get()->getSourceRange()); + + QualType Pointee = Type->getAs<PointerType>()->getPointeeType(); + if (Pointee->isVoidType() && !isSFINAEContext()) { + // The C++ standard bans deleting a pointer to a non-object type, which + // effectively bans deletion of "void*". However, most compilers support + // this, so we treat it as a warning unless we're in a SFINAE context. + Diag(StartLoc, diag::ext_delete_void_ptr_operand) + << Type << Ex.get()->getSourceRange(); + } else if (Pointee->isFunctionType() || Pointee->isVoidType()) + return ExprError(Diag(StartLoc, diag::err_delete_operand) + << Type << Ex.get()->getSourceRange()); + else if (!Pointee->isDependentType() && + RequireCompleteType(StartLoc, Pointee, + PDiag(diag::warn_delete_incomplete) + << Ex.get()->getSourceRange())) + return ExprError(); + else if (unsigned AddressSpace = Pointee.getAddressSpace()) + return Diag(Ex.get()->getLocStart(), + diag::err_address_space_qualified_delete) + << Pointee.getUnqualifiedType() << AddressSpace; + // C++ [expr.delete]p2: + // [Note: a pointer to a const type can be the operand of a + // delete-expression; it is not necessary to cast away the constness + // (5.2.11) of the pointer expression before it is used as the operand + // of the delete-expression. ] + Ex = ImpCastExprToType(Ex.take(), Context.getPointerType(Context.VoidTy), + CK_NoOp); + + if (Pointee->isArrayType() && !ArrayForm) { + Diag(StartLoc, diag::warn_delete_array_type) + << Type << Ex.get()->getSourceRange() + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(StartLoc), "[]"); + ArrayForm = true; + } + + DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( + ArrayForm ? OO_Array_Delete : OO_Delete); + + QualType PointeeElem = Context.getBaseElementType(Pointee); + if (const RecordType *RT = PointeeElem->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + if (!UseGlobal && + FindDeallocationFunction(StartLoc, RD, DeleteName, OperatorDelete)) + return ExprError(); + + // If we're allocating an array of records, check whether the + // usual operator delete[] has a size_t parameter. + if (ArrayForm) { + // If the user specifically asked to use the global allocator, + // we'll need to do the lookup into the class. + if (UseGlobal) + UsualArrayDeleteWantsSize = + doesUsualArrayDeleteWantSize(*this, StartLoc, PointeeElem); + + // Otherwise, the usual operator delete[] should be the + // function we just found. + else if (isa<CXXMethodDecl>(OperatorDelete)) + UsualArrayDeleteWantsSize = (OperatorDelete->getNumParams() == 2); + } + + if (!RD->hasTrivialDestructor()) + if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) { + MarkDeclarationReferenced(StartLoc, + const_cast<CXXDestructorDecl*>(Dtor)); + DiagnoseUseOfDecl(Dtor, StartLoc); + } + + // C++ [expr.delete]p3: + // In the first alternative (delete object), if the static type of the + // object to be deleted is different from its dynamic type, the static + // type shall be a base class of the dynamic type of the object to be + // deleted and the static type shall have a virtual destructor or the + // behavior is undefined. + // + // Note: a final class cannot be derived from, no issue there + if (!ArrayForm && RD->isPolymorphic() && !RD->hasAttr<FinalAttr>()) { + CXXDestructorDecl *dtor = RD->getDestructor(); + if (!dtor || !dtor->isVirtual()) + Diag(StartLoc, diag::warn_delete_non_virtual_dtor) << PointeeElem; + } + } + + if (!OperatorDelete) { + // Look for a global declaration. + DeclareGlobalNewDelete(); + DeclContext *TUDecl = Context.getTranslationUnitDecl(); + Expr *Arg = Ex.get(); + if (FindAllocationOverload(StartLoc, SourceRange(), DeleteName, + &Arg, 1, TUDecl, /*AllowMissing=*/false, + OperatorDelete)) + return ExprError(); + } + + MarkDeclarationReferenced(StartLoc, OperatorDelete); + + // Check access and ambiguity of operator delete and destructor. + if (const RecordType *RT = PointeeElem->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (CXXDestructorDecl *Dtor = LookupDestructor(RD)) { + CheckDestructorAccess(Ex.get()->getExprLoc(), Dtor, + PDiag(diag::err_access_dtor) << PointeeElem); + } + } + + } + + return Owned(new (Context) CXXDeleteExpr(Context.VoidTy, UseGlobal, ArrayForm, + ArrayFormAsWritten, + UsualArrayDeleteWantsSize, + OperatorDelete, Ex.take(), StartLoc)); +} + +/// \brief Check the use of the given variable as a C++ condition in an if, +/// while, do-while, or switch statement. +ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, + SourceLocation StmtLoc, + bool ConvertToBoolean) { + QualType T = ConditionVar->getType(); + + // C++ [stmt.select]p2: + // The declarator shall not specify a function or an array. + if (T->isFunctionType()) + return ExprError(Diag(ConditionVar->getLocation(), + diag::err_invalid_use_of_function_type) + << ConditionVar->getSourceRange()); + else if (T->isArrayType()) + return ExprError(Diag(ConditionVar->getLocation(), + diag::err_invalid_use_of_array_type) + << ConditionVar->getSourceRange()); + + ExprResult Condition = + Owned(DeclRefExpr::Create(Context, NestedNameSpecifierLoc(), + ConditionVar, + ConditionVar->getLocation(), + ConditionVar->getType().getNonReferenceType(), + VK_LValue)); + if (ConvertToBoolean) { + Condition = CheckBooleanCondition(Condition.take(), StmtLoc); + if (Condition.isInvalid()) + return ExprError(); + } + + return move(Condition); +} + +/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. +ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr) { + // C++ 6.4p4: + // The value of a condition that is an initialized declaration in a statement + // other than a switch statement is the value of the declared variable + // implicitly converted to type bool. If that conversion is ill-formed, the + // program is ill-formed. + // The value of a condition that is an expression is the value of the + // expression, implicitly converted to bool. + // + return PerformContextuallyConvertToBool(CondExpr); +} + +/// Helper function to determine whether this is the (deprecated) C++ +/// conversion from a string literal to a pointer to non-const char or +/// non-const wchar_t (for narrow and wide string literals, +/// respectively). +bool +Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { + // Look inside the implicit cast, if it exists. + if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(From)) + From = Cast->getSubExpr(); + + // A string literal (2.13.4) that is not a wide string literal can + // be converted to an rvalue of type "pointer to char"; a wide + // string literal can be converted to an rvalue of type "pointer + // to wchar_t" (C++ 4.2p2). + if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From->IgnoreParens())) + if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) + if (const BuiltinType *ToPointeeType + = ToPtrType->getPointeeType()->getAs<BuiltinType>()) { + // This conversion is considered only when there is an + // explicit appropriate pointer target type (C++ 4.2p2). + if (!ToPtrType->getPointeeType().hasQualifiers() && + ((StrLit->isWide() && ToPointeeType->isWideCharType()) || + (!StrLit->isWide() && + (ToPointeeType->getKind() == BuiltinType::Char_U || + ToPointeeType->getKind() == BuiltinType::Char_S)))) + return true; + } + + return false; +} + +static ExprResult BuildCXXCastArgument(Sema &S, + SourceLocation CastLoc, + QualType Ty, + CastKind Kind, + CXXMethodDecl *Method, + NamedDecl *FoundDecl, + Expr *From) { + switch (Kind) { + default: assert(0 && "Unhandled cast kind!"); + case CK_ConstructorConversion: { + ASTOwningVector<Expr*> ConstructorArgs(S); + + if (S.CompleteConstructorCall(cast<CXXConstructorDecl>(Method), + MultiExprArg(&From, 1), + CastLoc, ConstructorArgs)) + return ExprError(); + + ExprResult Result = + S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method), + move_arg(ConstructorArgs), + /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, + SourceRange()); + if (Result.isInvalid()) + return ExprError(); + + return S.MaybeBindToTemporary(Result.takeAs<Expr>()); + } + + case CK_UserDefinedConversion: { + assert(!From->getType()->isPointerType() && "Arg can't have pointer type!"); + + // Create an implicit call expr that calls it. + ExprResult Result = S.BuildCXXMemberCallExpr(From, FoundDecl, Method); + if (Result.isInvalid()) + return ExprError(); + + return S.MaybeBindToTemporary(Result.get()); + } + } +} + +/// PerformImplicitConversion - Perform an implicit conversion of the +/// expression From to the type ToType using the pre-computed implicit +/// conversion sequence ICS. Returns the converted +/// expression. Action is the kind of conversion we're performing, +/// used in the error message. +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + const ImplicitConversionSequence &ICS, + AssignmentAction Action, bool CStyle) { + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: { + ExprResult Res = PerformImplicitConversion(From, ToType, ICS.Standard, + Action, CStyle); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); + break; + } + + case ImplicitConversionSequence::UserDefinedConversion: { + + FunctionDecl *FD = ICS.UserDefined.ConversionFunction; + CastKind CastKind; + QualType BeforeToType; + if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) { + CastKind = CK_UserDefinedConversion; + + // If the user-defined conversion is specified by a conversion function, + // the initial standard conversion sequence converts the source type to + // the implicit object parameter of the conversion function. + BeforeToType = Context.getTagDeclType(Conv->getParent()); + } else { + const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(FD); + CastKind = CK_ConstructorConversion; + // Do no conversion if dealing with ... for the first conversion. + if (!ICS.UserDefined.EllipsisConversion) { + // If the user-defined conversion is specified by a constructor, the + // initial standard conversion sequence converts the source type to the + // type required by the argument of the constructor + BeforeToType = Ctor->getParamDecl(0)->getType().getNonReferenceType(); + } + } + // Watch out for elipsis conversion. + if (!ICS.UserDefined.EllipsisConversion) { + ExprResult Res = + PerformImplicitConversion(From, BeforeToType, + ICS.UserDefined.Before, AA_Converting, + CStyle); + if (Res.isInvalid()) + return ExprError(); + From = Res.take(); + } + + ExprResult CastArg + = BuildCXXCastArgument(*this, + From->getLocStart(), + ToType.getNonReferenceType(), + CastKind, cast<CXXMethodDecl>(FD), + ICS.UserDefined.FoundConversionFunction, + From); + + if (CastArg.isInvalid()) + return ExprError(); + + From = CastArg.take(); + + return PerformImplicitConversion(From, ToType, ICS.UserDefined.After, + AA_Converting, CStyle); + } + + case ImplicitConversionSequence::AmbiguousConversion: + ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(), + PDiag(diag::err_typecheck_ambiguous_condition) + << From->getSourceRange()); + return ExprError(); + + case ImplicitConversionSequence::EllipsisConversion: + assert(false && "Cannot perform an ellipsis conversion"); + return Owned(From); + + case ImplicitConversionSequence::BadConversion: + return ExprError(); + } + + // Everything went well. + return Owned(From); +} + +/// PerformImplicitConversion - Perform an implicit conversion of the +/// expression From to the type ToType by following the standard +/// conversion sequence SCS. Returns the converted +/// expression. Flavor is the context in which we're performing this +/// conversion, for use in error messages. +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + const StandardConversionSequence& SCS, + AssignmentAction Action, bool CStyle) { + // Overall FIXME: we are recomputing too many types here and doing far too + // much extra work. What this means is that we need to keep track of more + // information that is computed when we try the implicit conversion initially, + // so that we don't need to recompute anything here. + QualType FromType = From->getType(); + + if (SCS.CopyConstructor) { + // FIXME: When can ToType be a reference type? + assert(!ToType->isReferenceType()); + if (SCS.Second == ICK_Derived_To_Base) { + ASTOwningVector<Expr*> ConstructorArgs(*this); + if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor), + MultiExprArg(*this, &From, 1), + /*FIXME:ConstructLoc*/SourceLocation(), + ConstructorArgs)) + return ExprError(); + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + } + return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), + ToType, SCS.CopyConstructor, + MultiExprArg(*this, &From, 1), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + } + + // Resolve overloaded function references. + if (Context.hasSameType(FromType, Context.OverloadTy)) { + DeclAccessPair Found; + FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, + true, Found); + if (!Fn) + return ExprError(); + + if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) + return ExprError(); + + From = FixOverloadedFunctionReference(From, Found, Fn); + FromType = From->getType(); + } + + // Perform the first implicit conversion. + switch (SCS.First) { + case ICK_Identity: + // Nothing to do. + break; + + case ICK_Lvalue_To_Rvalue: + // Should this get its own ICK? + if (From->getObjectKind() == OK_ObjCProperty) { + ExprResult FromRes = ConvertPropertyForRValue(From); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); + if (!From->isGLValue()) break; + } + + // Check for trivial buffer overflows. + CheckArrayAccess(From); + + FromType = FromType.getUnqualifiedType(); + From = ImplicitCastExpr::Create(Context, FromType, CK_LValueToRValue, + From, 0, VK_RValue); + break; + + case ICK_Array_To_Pointer: + FromType = Context.getArrayDecayedType(FromType); + From = ImpCastExprToType(From, FromType, CK_ArrayToPointerDecay).take(); + break; + + case ICK_Function_To_Pointer: + FromType = Context.getPointerType(FromType); + From = ImpCastExprToType(From, FromType, CK_FunctionToPointerDecay).take(); + break; + + default: + assert(false && "Improper first standard conversion"); + break; + } + + // Perform the second implicit conversion + switch (SCS.Second) { + case ICK_Identity: + // If both sides are functions (or pointers/references to them), there could + // be incompatible exception declarations. + if (CheckExceptionSpecCompatibility(From, ToType)) + return ExprError(); + // Nothing else to do. + break; + + case ICK_NoReturn_Adjustment: + // If both sides are functions (or pointers/references to them), there could + // be incompatible exception declarations. + if (CheckExceptionSpecCompatibility(From, ToType)) + return ExprError(); + + From = ImpCastExprToType(From, ToType, CK_NoOp).take(); + break; + + case ICK_Integral_Promotion: + case ICK_Integral_Conversion: + From = ImpCastExprToType(From, ToType, CK_IntegralCast).take(); + break; + + case ICK_Floating_Promotion: + case ICK_Floating_Conversion: + From = ImpCastExprToType(From, ToType, CK_FloatingCast).take(); + break; + + case ICK_Complex_Promotion: + case ICK_Complex_Conversion: { + QualType FromEl = From->getType()->getAs<ComplexType>()->getElementType(); + QualType ToEl = ToType->getAs<ComplexType>()->getElementType(); + CastKind CK; + if (FromEl->isRealFloatingType()) { + if (ToEl->isRealFloatingType()) + CK = CK_FloatingComplexCast; + else + CK = CK_FloatingComplexToIntegralComplex; + } else if (ToEl->isRealFloatingType()) { + CK = CK_IntegralComplexToFloatingComplex; + } else { + CK = CK_IntegralComplexCast; + } + From = ImpCastExprToType(From, ToType, CK).take(); + break; + } + + case ICK_Floating_Integral: + if (ToType->isRealFloatingType()) + From = ImpCastExprToType(From, ToType, CK_IntegralToFloating).take(); + else + From = ImpCastExprToType(From, ToType, CK_FloatingToIntegral).take(); + break; + + case ICK_Compatible_Conversion: + From = ImpCastExprToType(From, ToType, CK_NoOp).take(); + break; + + case ICK_Pointer_Conversion: { + if (SCS.IncompatibleObjC && Action != AA_Casting) { + // Diagnose incompatible Objective-C conversions + if (Action == AA_Initializing || Action == AA_Assigning) + Diag(From->getSourceRange().getBegin(), + diag::ext_typecheck_convert_incompatible_pointer) + << ToType << From->getType() << Action + << From->getSourceRange(); + else + Diag(From->getSourceRange().getBegin(), + diag::ext_typecheck_convert_incompatible_pointer) + << From->getType() << ToType << Action + << From->getSourceRange(); + + if (From->getType()->isObjCObjectPointerType() && + ToType->isObjCObjectPointerType()) + EmitRelatedResultTypeNote(From); + } + + CastKind Kind = CK_Invalid; + CXXCastPath BasePath; + if (CheckPointerConversion(From, ToType, Kind, BasePath, CStyle)) + return ExprError(); + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take(); + break; + } + + case ICK_Pointer_Member: { + CastKind Kind = CK_Invalid; + CXXCastPath BasePath; + if (CheckMemberPointerConversion(From, ToType, Kind, BasePath, CStyle)) + return ExprError(); + if (CheckExceptionSpecCompatibility(From, ToType)) + return ExprError(); + From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath).take(); + break; + } + + case ICK_Boolean_Conversion: + From = ImpCastExprToType(From, Context.BoolTy, + ScalarTypeToBooleanCastKind(FromType)).take(); + break; + + case ICK_Derived_To_Base: { + CXXCastPath BasePath; + if (CheckDerivedToBaseConversion(From->getType(), + ToType.getNonReferenceType(), + From->getLocStart(), + From->getSourceRange(), + &BasePath, + CStyle)) + return ExprError(); + + From = ImpCastExprToType(From, ToType.getNonReferenceType(), + CK_DerivedToBase, CastCategory(From), + &BasePath).take(); + break; + } + + case ICK_Vector_Conversion: + From = ImpCastExprToType(From, ToType, CK_BitCast).take(); + break; + + case ICK_Vector_Splat: + From = ImpCastExprToType(From, ToType, CK_VectorSplat).take(); + break; + + case ICK_Complex_Real: + // Case 1. x -> _Complex y + if (const ComplexType *ToComplex = ToType->getAs<ComplexType>()) { + QualType ElType = ToComplex->getElementType(); + bool isFloatingComplex = ElType->isRealFloatingType(); + + // x -> y + if (Context.hasSameUnqualifiedType(ElType, From->getType())) { + // do nothing + } else if (From->getType()->isRealFloatingType()) { + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral).take(); + } else { + assert(From->getType()->isIntegerType()); + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast).take(); + } + // y -> _Complex y + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingRealToComplex + : CK_IntegralRealToComplex).take(); + + // Case 2. _Complex x -> y + } else { + const ComplexType *FromComplex = From->getType()->getAs<ComplexType>(); + assert(FromComplex); + + QualType ElType = FromComplex->getElementType(); + bool isFloatingComplex = ElType->isRealFloatingType(); + + // _Complex x -> x + From = ImpCastExprToType(From, ElType, + isFloatingComplex ? CK_FloatingComplexToReal + : CK_IntegralComplexToReal).take(); + + // x -> y + if (Context.hasSameUnqualifiedType(ElType, ToType)) { + // do nothing + } else if (ToType->isRealFloatingType()) { + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating).take(); + } else { + assert(ToType->isIntegerType()); + From = ImpCastExprToType(From, ToType, + isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast).take(); + } + } + break; + + case ICK_Block_Pointer_Conversion: { + From = ImpCastExprToType(From, ToType.getUnqualifiedType(), CK_BitCast, + VK_RValue).take(); + break; + } + + case ICK_TransparentUnionConversion: { + ExprResult FromRes = Owned(From); + Sema::AssignConvertType ConvTy = + CheckTransparentUnionArgumentConstraints(ToType, FromRes); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); + assert ((ConvTy == Sema::Compatible) && + "Improper transparent union conversion"); + (void)ConvTy; + break; + } + + case ICK_Lvalue_To_Rvalue: + case ICK_Array_To_Pointer: + case ICK_Function_To_Pointer: + case ICK_Qualification: + case ICK_Num_Conversion_Kinds: + assert(false && "Improper second standard conversion"); + break; + } + + switch (SCS.Third) { + case ICK_Identity: + // Nothing to do. + break; + + case ICK_Qualification: { + // The qualification keeps the category of the inner expression, unless the + // target type isn't a reference. + ExprValueKind VK = ToType->isReferenceType() ? + CastCategory(From) : VK_RValue; + From = ImpCastExprToType(From, ToType.getNonLValueExprType(Context), + CK_NoOp, VK).take(); + + if (SCS.DeprecatedStringLiteralToCharPtr && + !getLangOptions().WritableStrings) + Diag(From->getLocStart(), diag::warn_deprecated_string_literal_conversion) + << ToType.getNonReferenceType(); + + break; + } + + default: + assert(false && "Improper third standard conversion"); + break; + } + + return Owned(From); +} + +ExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait UTT, + SourceLocation KWLoc, + ParsedType Ty, + SourceLocation RParen) { + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Ty, &TSInfo); + + if (!TSInfo) + TSInfo = Context.getTrivialTypeSourceInfo(T); + return BuildUnaryTypeTrait(UTT, KWLoc, TSInfo, RParen); +} + +/// \brief Check the completeness of a type in a unary type trait. +/// +/// If the particular type trait requires a complete type, tries to complete +/// it. If completing the type fails, a diagnostic is emitted and false +/// returned. If completing the type succeeds or no completion was required, +/// returns true. +static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, + UnaryTypeTrait UTT, + SourceLocation Loc, + QualType ArgTy) { + // C++0x [meta.unary.prop]p3: + // For all of the class templates X declared in this Clause, instantiating + // that template with a template argument that is a class template + // specialization may result in the implicit instantiation of the template + // argument if and only if the semantics of X require that the argument + // must be a complete type. + // We apply this rule to all the type trait expressions used to implement + // these class templates. We also try to follow any GCC documented behavior + // in these expressions to ensure portability of standard libraries. + switch (UTT) { + // is_complete_type somewhat obviously cannot require a complete type. + case UTT_IsCompleteType: + // Fall-through + + // These traits are modeled on the type predicates in C++0x + // [meta.unary.cat] and [meta.unary.comp]. They are not specified as + // requiring a complete type, as whether or not they return true cannot be + // impacted by the completeness of the type. + case UTT_IsVoid: + case UTT_IsIntegral: + case UTT_IsFloatingPoint: + case UTT_IsArray: + case UTT_IsPointer: + case UTT_IsLvalueReference: + case UTT_IsRvalueReference: + case UTT_IsMemberFunctionPointer: + case UTT_IsMemberObjectPointer: + case UTT_IsEnum: + case UTT_IsUnion: + case UTT_IsClass: + case UTT_IsFunction: + case UTT_IsReference: + case UTT_IsArithmetic: + case UTT_IsFundamental: + case UTT_IsObject: + case UTT_IsScalar: + case UTT_IsCompound: + case UTT_IsMemberPointer: + // Fall-through + + // These traits are modeled on type predicates in C++0x [meta.unary.prop] + // which requires some of its traits to have the complete type. However, + // the completeness of the type cannot impact these traits' semantics, and + // so they don't require it. This matches the comments on these traits in + // Table 49. + case UTT_IsConst: + case UTT_IsVolatile: + case UTT_IsSigned: + case UTT_IsUnsigned: + return true; + + // C++0x [meta.unary.prop] Table 49 requires the following traits to be + // applied to a complete type. + case UTT_IsTrivial: + case UTT_IsTriviallyCopyable: + case UTT_IsStandardLayout: + case UTT_IsPOD: + case UTT_IsLiteral: + case UTT_IsEmpty: + case UTT_IsPolymorphic: + case UTT_IsAbstract: + // Fall-through + + // These trait expressions are designed to help implement predicates in + // [meta.unary.prop] despite not being named the same. They are specified + // by both GCC and the Embarcadero C++ compiler, and require the complete + // type due to the overarching C++0x type predicates being implemented + // requiring the complete type. + case UTT_HasNothrowAssign: + case UTT_HasNothrowConstructor: + case UTT_HasNothrowCopy: + case UTT_HasTrivialAssign: + case UTT_HasTrivialDefaultConstructor: + case UTT_HasTrivialCopy: + case UTT_HasTrivialDestructor: + case UTT_HasVirtualDestructor: + // Arrays of unknown bound are expressly allowed. + QualType ElTy = ArgTy; + if (ArgTy->isIncompleteArrayType()) + ElTy = S.Context.getAsArrayType(ArgTy)->getElementType(); + + // The void type is expressly allowed. + if (ElTy->isVoidType()) + return true; + + return !S.RequireCompleteType( + Loc, ElTy, diag::err_incomplete_type_used_in_type_trait_expr); + } + llvm_unreachable("Type trait not handled by switch"); +} + +static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, + SourceLocation KeyLoc, QualType T) { + assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); + + ASTContext &C = Self.Context; + switch(UTT) { + // Type trait expressions corresponding to the primary type category + // predicates in C++0x [meta.unary.cat]. + case UTT_IsVoid: + return T->isVoidType(); + case UTT_IsIntegral: + return T->isIntegralType(C); + case UTT_IsFloatingPoint: + return T->isFloatingType(); + case UTT_IsArray: + return T->isArrayType(); + case UTT_IsPointer: + return T->isPointerType(); + case UTT_IsLvalueReference: + return T->isLValueReferenceType(); + case UTT_IsRvalueReference: + return T->isRValueReferenceType(); + case UTT_IsMemberFunctionPointer: + return T->isMemberFunctionPointerType(); + case UTT_IsMemberObjectPointer: + return T->isMemberDataPointerType(); + case UTT_IsEnum: + return T->isEnumeralType(); + case UTT_IsUnion: + return T->isUnionType(); + case UTT_IsClass: + return T->isClassType() || T->isStructureType(); + case UTT_IsFunction: + return T->isFunctionType(); + + // Type trait expressions which correspond to the convenient composition + // predicates in C++0x [meta.unary.comp]. + case UTT_IsReference: + return T->isReferenceType(); + case UTT_IsArithmetic: + return T->isArithmeticType() && !T->isEnumeralType(); + case UTT_IsFundamental: + return T->isFundamentalType(); + case UTT_IsObject: + return T->isObjectType(); + case UTT_IsScalar: + return T->isScalarType(); + case UTT_IsCompound: + return T->isCompoundType(); + case UTT_IsMemberPointer: + return T->isMemberPointerType(); + + // Type trait expressions which correspond to the type property predicates + // in C++0x [meta.unary.prop]. + case UTT_IsConst: + return T.isConstQualified(); + case UTT_IsVolatile: + return T.isVolatileQualified(); + case UTT_IsTrivial: + return T->isTrivialType(); + case UTT_IsTriviallyCopyable: + return T->isTriviallyCopyableType(); + case UTT_IsStandardLayout: + return T->isStandardLayoutType(); + case UTT_IsPOD: + return T->isPODType(); + case UTT_IsLiteral: + return T->isLiteralType(); + case UTT_IsEmpty: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return !RD->isUnion() && RD->isEmpty(); + return false; + case UTT_IsPolymorphic: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isPolymorphic(); + return false; + case UTT_IsAbstract: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isAbstract(); + return false; + case UTT_IsSigned: + return T->isSignedIntegerType(); + case UTT_IsUnsigned: + return T->isUnsignedIntegerType(); + + // Type trait expressions which query classes regarding their construction, + // destruction, and copying. Rather than being based directly on the + // related type predicates in the standard, they are specified by both + // GCC[1] and the Embarcadero C++ compiler[2], and Clang implements those + // specifications. + // + // 1: http://gcc.gnu/.org/onlinedocs/gcc/Type-Traits.html + // 2: http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index + case UTT_HasTrivialDefaultConstructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true then the trait is true, else if type is + // a cv class or union type (or array thereof) with a trivial default + // constructor ([class.ctor]) then the trait is true, else it is false. + if (T->isPODType()) + return true; + if (const RecordType *RT = + C.getBaseElementType(T)->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor(); + return false; + case UTT_HasTrivialCopy: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true or type is a reference type then + // the trait is true, else if type is a cv class or union type + // with a trivial copy constructor ([class.copy]) then the trait + // is true, else it is false. + if (T->isPODType() || T->isReferenceType()) + return true; + if (const RecordType *RT = T->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor(); + return false; + case UTT_HasTrivialAssign: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If type is const qualified or is a reference type then the + // trait is false. Otherwise if __is_pod (type) is true then the + // trait is true, else if type is a cv class or union type with + // a trivial copy assignment ([class.copy]) then the trait is + // true, else it is false. + // Note: the const and reference restrictions are interesting, + // given that const and reference members don't prevent a class + // from having a trivial copy assignment operator (but do cause + // errors if the copy assignment operator is actually used, q.v. + // [class.copy]p12). + + if (C.getBaseElementType(T).isConstQualified()) + return false; + if (T->isPODType()) + return true; + if (const RecordType *RT = T->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment(); + return false; + case UTT_HasTrivialDestructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __is_pod (type) is true or type is a reference type + // then the trait is true, else if type is a cv class or union + // type (or array thereof) with a trivial destructor + // ([class.dtor]) then the trait is true, else it is + // false. + if (T->isPODType() || T->isReferenceType()) + return true; + if (const RecordType *RT = + C.getBaseElementType(T)->getAs<RecordType>()) + return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor(); + return false; + // TODO: Propagate nothrowness for implicitly declared special members. + case UTT_HasNothrowAssign: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If type is const qualified or is a reference type then the + // trait is false. Otherwise if __has_trivial_assign (type) + // is true then the trait is true, else if type is a cv class + // or union type with copy assignment operators that are known + // not to throw an exception then the trait is true, else it is + // false. + if (C.getBaseElementType(T).isConstQualified()) + return false; + if (T->isReferenceType()) + return false; + if (T->isPODType()) + return true; + if (const RecordType *RT = T->getAs<RecordType>()) { + CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->hasTrivialCopyAssignment()) + return true; + + bool FoundAssign = false; + DeclarationName Name = C.DeclarationNames.getCXXOperatorName(OO_Equal); + LookupResult Res(Self, DeclarationNameInfo(Name, KeyLoc), + Sema::LookupOrdinaryName); + if (Self.LookupQualifiedName(Res, RD)) { + for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end(); + Op != OpEnd; ++Op) { + CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op); + if (Operator->isCopyAssignmentOperator()) { + FoundAssign = true; + const FunctionProtoType *CPT + = Operator->getType()->getAs<FunctionProtoType>(); + if (CPT->getExceptionSpecType() == EST_Delayed) + return false; + if (!CPT->isNothrow(Self.Context)) + return false; + } + } + } + + return FoundAssign; + } + return false; + case UTT_HasNothrowCopy: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __has_trivial_copy (type) is true then the trait is true, else + // if type is a cv class or union type with copy constructors that are + // known not to throw an exception then the trait is true, else it is + // false. + if (T->isPODType() || T->isReferenceType()) + return true; + if (const RecordType *RT = T->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->hasTrivialCopyConstructor()) + return true; + + bool FoundConstructor = false; + unsigned FoundTQs; + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); + Con != ConEnd; ++Con) { + // A template constructor is never a copy constructor. + // FIXME: However, it may actually be selected at the actual overload + // resolution point. + if (isa<FunctionTemplateDecl>(*Con)) + continue; + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + if (Constructor->isCopyConstructor(FoundTQs)) { + FoundConstructor = true; + const FunctionProtoType *CPT + = Constructor->getType()->getAs<FunctionProtoType>(); + if (CPT->getExceptionSpecType() == EST_Delayed) + return false; + // FIXME: check whether evaluating default arguments can throw. + // For now, we'll be conservative and assume that they can throw. + if (!CPT->isNothrow(Self.Context) || CPT->getNumArgs() > 1) + return false; + } + } + + return FoundConstructor; + } + return false; + case UTT_HasNothrowConstructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If __has_trivial_constructor (type) is true then the trait is + // true, else if type is a cv class or union type (or array + // thereof) with a default constructor that is known not to + // throw an exception then the trait is true, else it is false. + if (T->isPODType()) + return true; + if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->hasTrivialDefaultConstructor()) + return true; + + DeclContext::lookup_const_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); + Con != ConEnd; ++Con) { + // FIXME: In C++0x, a constructor template can be a default constructor. + if (isa<FunctionTemplateDecl>(*Con)) + continue; + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); + if (Constructor->isDefaultConstructor()) { + const FunctionProtoType *CPT + = Constructor->getType()->getAs<FunctionProtoType>(); + if (CPT->getExceptionSpecType() == EST_Delayed) + return false; + // TODO: check whether evaluating default arguments can throw. + // For now, we'll be conservative and assume that they can throw. + return CPT->isNothrow(Self.Context) && CPT->getNumArgs() == 0; + } + } + } + return false; + case UTT_HasVirtualDestructor: + // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: + // If type is a class type with a virtual destructor ([class.dtor]) + // then the trait is true, else it is false. + if (const RecordType *Record = T->getAs<RecordType>()) { + CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); + if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD)) + return Destructor->isVirtual(); + } + return false; + + // These type trait expressions are modeled on the specifications for the + // Embarcadero C++0x type trait functions: + // http://docwiki.embarcadero.com/RADStudio/XE/en/Type_Trait_Functions_(C%2B%2B0x)_Index + case UTT_IsCompleteType: + // http://docwiki.embarcadero.com/RADStudio/XE/en/Is_complete_type_(typename_T_): + // Returns True if and only if T is a complete type at the point of the + // function call. + return !T->isIncompleteType(); + } + llvm_unreachable("Type trait not covered by switch"); +} + +ExprResult Sema::BuildUnaryTypeTrait(UnaryTypeTrait UTT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + SourceLocation RParen) { + QualType T = TSInfo->getType(); + if (!CheckUnaryTypeTraitTypeCompleteness(*this, UTT, KWLoc, T)) + return ExprError(); + + bool Value = false; + if (!T->isDependentType()) + Value = EvaluateUnaryTypeTrait(*this, UTT, KWLoc, T); + + return Owned(new (Context) UnaryTypeTraitExpr(KWLoc, UTT, TSInfo, Value, + RParen, Context.BoolTy)); +} + +ExprResult Sema::ActOnBinaryTypeTrait(BinaryTypeTrait BTT, + SourceLocation KWLoc, + ParsedType LhsTy, + ParsedType RhsTy, + SourceLocation RParen) { + TypeSourceInfo *LhsTSInfo; + QualType LhsT = GetTypeFromParser(LhsTy, &LhsTSInfo); + if (!LhsTSInfo) + LhsTSInfo = Context.getTrivialTypeSourceInfo(LhsT); + + TypeSourceInfo *RhsTSInfo; + QualType RhsT = GetTypeFromParser(RhsTy, &RhsTSInfo); + if (!RhsTSInfo) + RhsTSInfo = Context.getTrivialTypeSourceInfo(RhsT); + + return BuildBinaryTypeTrait(BTT, KWLoc, LhsTSInfo, RhsTSInfo, RParen); +} + +static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, + QualType LhsT, QualType RhsT, + SourceLocation KeyLoc) { + assert(!LhsT->isDependentType() && !RhsT->isDependentType() && + "Cannot evaluate traits of dependent types"); + + switch(BTT) { + case BTT_IsBaseOf: { + // C++0x [meta.rel]p2 + // Base is a base class of Derived without regard to cv-qualifiers or + // Base and Derived are not unions and name the same class type without + // regard to cv-qualifiers. + + const RecordType *lhsRecord = LhsT->getAs<RecordType>(); + if (!lhsRecord) return false; + + const RecordType *rhsRecord = RhsT->getAs<RecordType>(); + if (!rhsRecord) return false; + + assert(Self.Context.hasSameUnqualifiedType(LhsT, RhsT) + == (lhsRecord == rhsRecord)); + + if (lhsRecord == rhsRecord) + return !lhsRecord->getDecl()->isUnion(); + + // C++0x [meta.rel]p2: + // If Base and Derived are class types and are different types + // (ignoring possible cv-qualifiers) then Derived shall be a + // complete type. + if (Self.RequireCompleteType(KeyLoc, RhsT, + diag::err_incomplete_type_used_in_type_trait_expr)) + return false; + + return cast<CXXRecordDecl>(rhsRecord->getDecl()) + ->isDerivedFrom(cast<CXXRecordDecl>(lhsRecord->getDecl())); + } + case BTT_IsSame: + return Self.Context.hasSameType(LhsT, RhsT); + case BTT_TypeCompatible: + return Self.Context.typesAreCompatible(LhsT.getUnqualifiedType(), + RhsT.getUnqualifiedType()); + case BTT_IsConvertible: + case BTT_IsConvertibleTo: { + // C++0x [meta.rel]p4: + // Given the following function prototype: + // + // template <class T> + // typename add_rvalue_reference<T>::type create(); + // + // the predicate condition for a template specialization + // is_convertible<From, To> shall be satisfied if and only if + // the return expression in the following code would be + // well-formed, including any implicit conversions to the return + // type of the function: + // + // To test() { + // return create<From>(); + // } + // + // Access checking is performed as if in a context unrelated to To and + // From. Only the validity of the immediate context of the expression + // of the return-statement (including conversions to the return type) + // is considered. + // + // We model the initialization as a copy-initialization of a temporary + // of the appropriate type, which for this expression is identical to the + // return statement (since NRVO doesn't apply). + if (LhsT->isObjectType() || LhsT->isFunctionType()) + LhsT = Self.Context.getRValueReferenceType(LhsT); + + InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT)); + OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context), + Expr::getValueKindForType(LhsT)); + Expr *FromPtr = &From; + InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, + SourceLocation())); + + // Perform the initialization within a SFINAE trap at translation unit + // scope. + Sema::SFINAETrap SFINAE(Self, /*AccessCheckingSFINAE=*/true); + Sema::ContextRAII TUContext(Self, Self.Context.getTranslationUnitDecl()); + InitializationSequence Init(Self, To, Kind, &FromPtr, 1); + if (Init.Failed()) + return false; + + ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); + return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); + } + } + llvm_unreachable("Unknown type trait or not implemented"); +} + +ExprResult Sema::BuildBinaryTypeTrait(BinaryTypeTrait BTT, + SourceLocation KWLoc, + TypeSourceInfo *LhsTSInfo, + TypeSourceInfo *RhsTSInfo, + SourceLocation RParen) { + QualType LhsT = LhsTSInfo->getType(); + QualType RhsT = RhsTSInfo->getType(); + + if (BTT == BTT_TypeCompatible) { + if (getLangOptions().CPlusPlus) { + Diag(KWLoc, diag::err_types_compatible_p_in_cplusplus) + << SourceRange(KWLoc, RParen); + return ExprError(); + } + } + + bool Value = false; + if (!LhsT->isDependentType() && !RhsT->isDependentType()) + Value = EvaluateBinaryTypeTrait(*this, BTT, LhsT, RhsT, KWLoc); + + // Select trait result type. + QualType ResultType; + switch (BTT) { + case BTT_IsBaseOf: ResultType = Context.BoolTy; break; + case BTT_IsConvertible: ResultType = Context.BoolTy; break; + case BTT_IsSame: ResultType = Context.BoolTy; break; + case BTT_TypeCompatible: ResultType = Context.IntTy; break; + case BTT_IsConvertibleTo: ResultType = Context.BoolTy; break; + } + + return Owned(new (Context) BinaryTypeTraitExpr(KWLoc, BTT, LhsTSInfo, + RhsTSInfo, Value, RParen, + ResultType)); +} + +ExprResult Sema::ActOnArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + ParsedType Ty, + Expr* DimExpr, + SourceLocation RParen) { + TypeSourceInfo *TSInfo; + QualType T = GetTypeFromParser(Ty, &TSInfo); + if (!TSInfo) + TSInfo = Context.getTrivialTypeSourceInfo(T); + + return BuildArrayTypeTrait(ATT, KWLoc, TSInfo, DimExpr, RParen); +} + +static uint64_t EvaluateArrayTypeTrait(Sema &Self, ArrayTypeTrait ATT, + QualType T, Expr *DimExpr, + SourceLocation KeyLoc) { + assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); + + switch(ATT) { + case ATT_ArrayRank: + if (T->isArrayType()) { + unsigned Dim = 0; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + ++Dim; + T = AT->getElementType(); + } + return Dim; + } + return 0; + + case ATT_ArrayExtent: { + llvm::APSInt Value; + uint64_t Dim; + if (DimExpr->isIntegerConstantExpr(Value, Self.Context, 0, false)) { + if (Value < llvm::APSInt(Value.getBitWidth(), Value.isUnsigned())) { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << + DimExpr->getSourceRange(); + return false; + } + Dim = Value.getLimitedValue(); + } else { + Self.Diag(KeyLoc, diag::err_dimension_expr_not_constant_integer) << + DimExpr->getSourceRange(); + return false; + } + + if (T->isArrayType()) { + unsigned D = 0; + bool Matched = false; + while (const ArrayType *AT = Self.Context.getAsArrayType(T)) { + if (Dim == D) { + Matched = true; + break; + } + ++D; + T = AT->getElementType(); + } + + if (Matched && T->isArrayType()) { + if (const ConstantArrayType *CAT = Self.Context.getAsConstantArrayType(T)) + return CAT->getSize().getLimitedValue(); + } + } + return 0; + } + } + llvm_unreachable("Unknown type trait or not implemented"); +} + +ExprResult Sema::BuildArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + Expr* DimExpr, + SourceLocation RParen) { + QualType T = TSInfo->getType(); + + // FIXME: This should likely be tracked as an APInt to remove any host + // assumptions about the width of size_t on the target. + uint64_t Value = 0; + if (!T->isDependentType()) + Value = EvaluateArrayTypeTrait(*this, ATT, T, DimExpr, KWLoc); + + // While the specification for these traits from the Embarcadero C++ + // compiler's documentation says the return type is 'unsigned int', Clang + // returns 'size_t'. On Windows, the primary platform for the Embarcadero + // compiler, there is no difference. On several other platforms this is an + // important distinction. + return Owned(new (Context) ArrayTypeTraitExpr(KWLoc, ATT, TSInfo, Value, + DimExpr, RParen, + Context.getSizeType())); +} + +ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen) { + // If error parsing the expression, ignore. + if (!Queried) + return ExprError(); + + ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen); + + return move(Result); +} + +static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) { + switch (ET) { + case ET_IsLValueExpr: return E->isLValue(); + case ET_IsRValueExpr: return E->isRValue(); + } + llvm_unreachable("Expression trait not covered by switch"); +} + +ExprResult Sema::BuildExpressionTrait(ExpressionTrait ET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen) { + if (Queried->isTypeDependent()) { + // Delay type-checking for type-dependent expressions. + } else if (Queried->getType()->isPlaceholderType()) { + ExprResult PE = CheckPlaceholderExpr(Queried); + if (PE.isInvalid()) return ExprError(); + return BuildExpressionTrait(ET, KWLoc, PE.take(), RParen); + } + + bool Value = EvaluateExpressionTrait(ET, Queried); + + return Owned(new (Context) ExpressionTraitExpr(KWLoc, ET, Queried, Value, + RParen, Context.BoolTy)); +} + +QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex, + ExprValueKind &VK, + SourceLocation Loc, + bool isIndirect) { + const char *OpSpelling = isIndirect ? "->*" : ".*"; + // C++ 5.5p2 + // The binary operator .* [p3: ->*] binds its second operand, which shall + // be of type "pointer to member of T" (where T is a completely-defined + // class type) [...] + QualType RType = rex.get()->getType(); + const MemberPointerType *MemPtr = RType->getAs<MemberPointerType>(); + if (!MemPtr) { + Diag(Loc, diag::err_bad_memptr_rhs) + << OpSpelling << RType << rex.get()->getSourceRange(); + return QualType(); + } + + QualType Class(MemPtr->getClass(), 0); + + // Note: C++ [expr.mptr.oper]p2-3 says that the class type into which the + // member pointer points must be completely-defined. However, there is no + // reason for this semantic distinction, and the rule is not enforced by + // other compilers. Therefore, we do not check this property, as it is + // likely to be considered a defect. + + // C++ 5.5p2 + // [...] to its first operand, which shall be of class T or of a class of + // which T is an unambiguous and accessible base class. [p3: a pointer to + // such a class] + QualType LType = lex.get()->getType(); + if (isIndirect) { + if (const PointerType *Ptr = LType->getAs<PointerType>()) + LType = Ptr->getPointeeType(); + else { + Diag(Loc, diag::err_bad_memptr_lhs) + << OpSpelling << 1 << LType + << FixItHint::CreateReplacement(SourceRange(Loc), ".*"); + return QualType(); + } + } + + if (!Context.hasSameUnqualifiedType(Class, LType)) { + // If we want to check the hierarchy, we need a complete type. + if (RequireCompleteType(Loc, LType, PDiag(diag::err_bad_memptr_lhs) + << OpSpelling << (int)isIndirect)) { + return QualType(); + } + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/false); + // FIXME: Would it be useful to print full ambiguity paths, or is that + // overkill? + if (!IsDerivedFrom(LType, Class, Paths) || + Paths.isAmbiguous(Context.getCanonicalType(Class))) { + Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling + << (int)isIndirect << lex.get()->getType(); + return QualType(); + } + // Cast LHS to type of use. + QualType UseType = isIndirect ? Context.getPointerType(Class) : Class; + ExprValueKind VK = + isIndirect ? VK_RValue : CastCategory(lex.get()); + + CXXCastPath BasePath; + BuildBasePathArray(Paths, BasePath); + lex = ImpCastExprToType(lex.take(), UseType, CK_DerivedToBase, VK, &BasePath); + } + + if (isa<CXXScalarValueInitExpr>(rex.get()->IgnoreParens())) { + // Diagnose use of pointer-to-member type which when used as + // the functional cast in a pointer-to-member expression. + Diag(Loc, diag::err_pointer_to_member_type) << isIndirect; + return QualType(); + } + + // C++ 5.5p2 + // The result is an object or a function of the type specified by the + // second operand. + // The cv qualifiers are the union of those in the pointer and the left side, + // in accordance with 5.5p5 and 5.2.5. + QualType Result = MemPtr->getPointeeType(); + Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers()); + + // C++0x [expr.mptr.oper]p6: + // In a .* expression whose object expression is an rvalue, the program is + // ill-formed if the second operand is a pointer to member function with + // ref-qualifier &. In a ->* expression or in a .* expression whose object + // expression is an lvalue, the program is ill-formed if the second operand + // is a pointer to member function with ref-qualifier &&. + if (const FunctionProtoType *Proto = Result->getAs<FunctionProtoType>()) { + switch (Proto->getRefQualifier()) { + case RQ_None: + // Do nothing + break; + + case RQ_LValue: + if (!isIndirect && !lex.get()->Classify(Context).isLValue()) + Diag(Loc, diag::err_pointer_to_member_oper_value_classify) + << RType << 1 << lex.get()->getSourceRange(); + break; + + case RQ_RValue: + if (isIndirect || !lex.get()->Classify(Context).isRValue()) + Diag(Loc, diag::err_pointer_to_member_oper_value_classify) + << RType << 0 << lex.get()->getSourceRange(); + break; + } + } + + // C++ [expr.mptr.oper]p6: + // The result of a .* expression whose second operand is a pointer + // to a data member is of the same value category as its + // first operand. The result of a .* expression whose second + // operand is a pointer to a member function is a prvalue. The + // result of an ->* expression is an lvalue if its second operand + // is a pointer to data member and a prvalue otherwise. + if (Result->isFunctionType()) { + VK = VK_RValue; + return Context.BoundMemberTy; + } else if (isIndirect) { + VK = VK_LValue; + } else { + VK = lex.get()->getValueKind(); + } + + return Result; +} + +/// \brief Try to convert a type to another according to C++0x 5.16p3. +/// +/// This is part of the parameter validation for the ? operator. If either +/// value operand is a class type, the two operands are attempted to be +/// converted to each other. This function does the conversion in one direction. +/// It returns true if the program is ill-formed and has already been diagnosed +/// as such. +static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, + SourceLocation QuestionLoc, + bool &HaveConversion, + QualType &ToType) { + HaveConversion = false; + ToType = To->getType(); + + InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(), + SourceLocation()); + // C++0x 5.16p3 + // The process for determining whether an operand expression E1 of type T1 + // can be converted to match an operand expression E2 of type T2 is defined + // as follows: + // -- If E2 is an lvalue: + bool ToIsLvalue = To->isLValue(); + if (ToIsLvalue) { + // E1 can be converted to match E2 if E1 can be implicitly converted to + // type "lvalue reference to T2", subject to the constraint that in the + // conversion the reference must bind directly to E1. + QualType T = Self.Context.getLValueReferenceType(ToType); + InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); + + InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); + if (InitSeq.isDirectReferenceBinding()) { + ToType = T; + HaveConversion = true; + return false; + } + + if (InitSeq.isAmbiguous()) + return InitSeq.Diagnose(Self, Entity, Kind, &From, 1); + } + + // -- If E2 is an rvalue, or if the conversion above cannot be done: + // -- if E1 and E2 have class type, and the underlying class types are + // the same or one is a base class of the other: + QualType FTy = From->getType(); + QualType TTy = To->getType(); + const RecordType *FRec = FTy->getAs<RecordType>(); + const RecordType *TRec = TTy->getAs<RecordType>(); + bool FDerivedFromT = FRec && TRec && FRec != TRec && + Self.IsDerivedFrom(FTy, TTy); + if (FRec && TRec && + (FRec == TRec || FDerivedFromT || Self.IsDerivedFrom(TTy, FTy))) { + // E1 can be converted to match E2 if the class of T2 is the + // same type as, or a base class of, the class of T1, and + // [cv2 > cv1]. + if (FRec == TRec || FDerivedFromT) { + if (TTy.isAtLeastAsQualifiedAs(FTy)) { + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy); + InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); + if (InitSeq) { + HaveConversion = true; + return false; + } + + if (InitSeq.isAmbiguous()) + return InitSeq.Diagnose(Self, Entity, Kind, &From, 1); + } + } + + return false; + } + + // -- Otherwise: E1 can be converted to match E2 if E1 can be + // implicitly converted to the type that expression E2 would have + // if E2 were converted to an rvalue (or the type it has, if E2 is + // an rvalue). + // + // This actually refers very narrowly to the lvalue-to-rvalue conversion, not + // to the array-to-pointer or function-to-pointer conversions. + if (!TTy->getAs<TagType>()) + TTy = TTy.getUnqualifiedType(); + + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TTy); + InitializationSequence InitSeq(Self, Entity, Kind, &From, 1); + HaveConversion = !InitSeq.Failed(); + ToType = TTy; + if (InitSeq.isAmbiguous()) + return InitSeq.Diagnose(Self, Entity, Kind, &From, 1); + + return false; +} + +/// \brief Try to find a common type for two according to C++0x 5.16p5. +/// +/// This is part of the parameter validation for the ? operator. If either +/// value operand is a class type, overload resolution is used to find a +/// conversion to a common type. +static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS, + SourceLocation QuestionLoc) { + Expr *Args[2] = { LHS.get(), RHS.get() }; + OverloadCandidateSet CandidateSet(QuestionLoc); + Self.AddBuiltinOperatorCandidates(OO_Conditional, QuestionLoc, Args, 2, + CandidateSet); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(Self, QuestionLoc, Best)) { + case OR_Success: { + // We found a match. Perform the conversions on the arguments and move on. + ExprResult LHSRes = + Self.PerformImplicitConversion(LHS.get(), Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], Sema::AA_Converting); + if (LHSRes.isInvalid()) + break; + LHS = move(LHSRes); + + ExprResult RHSRes = + Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], Sema::AA_Converting); + if (RHSRes.isInvalid()) + break; + RHS = move(RHSRes); + if (Best->Function) + Self.MarkDeclarationReferenced(QuestionLoc, Best->Function); + return false; + } + + case OR_No_Viable_Function: + + // Emit a better diagnostic if one of the expressions is a null pointer + // constant and the other is a pointer type. In this case, the user most + // likely forgot to take the address of the other expression. + if (Self.DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) + return true; + + Self.Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return true; + + case OR_Ambiguous: + Self.Diag(QuestionLoc, diag::err_conditional_ambiguous_ovl) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + // FIXME: Print the possible common types by printing the return types of + // the viable candidates. + break; + + case OR_Deleted: + assert(false && "Conditional operator has only built-in overloads"); + break; + } + return true; +} + +/// \brief Perform an "extended" implicit conversion as returned by +/// TryClassUnification. +static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { + InitializedEntity Entity = InitializedEntity::InitializeTemporary(T); + InitializationKind Kind = InitializationKind::CreateCopy(E.get()->getLocStart(), + SourceLocation()); + Expr *Arg = E.take(); + InitializationSequence InitSeq(Self, Entity, Kind, &Arg, 1); + ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&Arg, 1)); + if (Result.isInvalid()) + return true; + + E = Result; + return false; +} + +/// \brief Check the operands of ?: under C++ semantics. +/// +/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y +/// extension. In this case, LHS == Cond. (But they're not aliases.) +QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, + ExprValueKind &VK, ExprObjectKind &OK, + SourceLocation QuestionLoc) { + // FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++ + // interface pointers. + + // C++0x 5.16p1 + // The first expression is contextually converted to bool. + if (!Cond.get()->isTypeDependent()) { + ExprResult CondRes = CheckCXXBooleanCondition(Cond.take()); + if (CondRes.isInvalid()) + return QualType(); + Cond = move(CondRes); + } + + // Assume r-value. + VK = VK_RValue; + OK = OK_Ordinary; + + // Either of the arguments dependent? + if (LHS.get()->isTypeDependent() || RHS.get()->isTypeDependent()) + return Context.DependentTy; + + // C++0x 5.16p2 + // If either the second or the third operand has type (cv) void, ... + QualType LTy = LHS.get()->getType(); + QualType RTy = RHS.get()->getType(); + bool LVoid = LTy->isVoidType(); + bool RVoid = RTy->isVoidType(); + if (LVoid || RVoid) { + // ... then the [l2r] conversions are performed on the second and third + // operands ... + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + RTy = RHS.get()->getType(); + + // ... and one of the following shall hold: + // -- The second or the third operand (but not both) is a throw- + // expression; the result is of the type of the other and is an rvalue. + bool LThrow = isa<CXXThrowExpr>(LHS.get()); + bool RThrow = isa<CXXThrowExpr>(RHS.get()); + if (LThrow && !RThrow) + return RTy; + if (RThrow && !LThrow) + return LTy; + + // -- Both the second and third operands have type void; the result is of + // type void and is an rvalue. + if (LVoid && RVoid) + return Context.VoidTy; + + // Neither holds, error. + Diag(QuestionLoc, diag::err_conditional_void_nonvoid) + << (LVoid ? RTy : LTy) << (LVoid ? 0 : 1) + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + + // Neither is void. + + // C++0x 5.16p3 + // Otherwise, if the second and third operand have different types, and + // either has (cv) class type, and attempt is made to convert each of those + // operands to the other. + if (!Context.hasSameType(LTy, RTy) && + (LTy->isRecordType() || RTy->isRecordType())) { + ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft; + // These return true if a single direction is already ambiguous. + QualType L2RType, R2LType; + bool HaveL2R, HaveR2L; + if (TryClassUnification(*this, LHS.get(), RHS.get(), QuestionLoc, HaveL2R, L2RType)) + return QualType(); + if (TryClassUnification(*this, RHS.get(), LHS.get(), QuestionLoc, HaveR2L, R2LType)) + return QualType(); + + // If both can be converted, [...] the program is ill-formed. + if (HaveL2R && HaveR2L) { + Diag(QuestionLoc, diag::err_conditional_ambiguous) + << LTy << RTy << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } + + // If exactly one conversion is possible, that conversion is applied to + // the chosen operand and the converted operands are used in place of the + // original operands for the remainder of this section. + if (HaveL2R) { + if (ConvertForConditional(*this, LHS, L2RType) || LHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + } else if (HaveR2L) { + if (ConvertForConditional(*this, RHS, R2LType) || RHS.isInvalid()) + return QualType(); + RTy = RHS.get()->getType(); + } + } + + // C++0x 5.16p4 + // If the second and third operands are glvalues of the same value + // category and have the same type, the result is of that type and + // value category and it is a bit-field if the second or the third + // operand is a bit-field, or if both are bit-fields. + // We only extend this to bitfields, not to the crazy other kinds of + // l-values. + bool Same = Context.hasSameType(LTy, RTy); + if (Same && + LHS.get()->isGLValue() && + LHS.get()->getValueKind() == RHS.get()->getValueKind() && + LHS.get()->isOrdinaryOrBitFieldObject() && + RHS.get()->isOrdinaryOrBitFieldObject()) { + VK = LHS.get()->getValueKind(); + if (LHS.get()->getObjectKind() == OK_BitField || + RHS.get()->getObjectKind() == OK_BitField) + OK = OK_BitField; + return LTy; + } + + // C++0x 5.16p5 + // Otherwise, the result is an rvalue. If the second and third operands + // do not have the same type, and either has (cv) class type, ... + if (!Same && (LTy->isRecordType() || RTy->isRecordType())) { + // ... overload resolution is used to determine the conversions (if any) + // to be applied to the operands. If the overload resolution fails, the + // program is ill-formed. + if (FindConditionalOverload(*this, LHS, RHS, QuestionLoc)) + return QualType(); + } + + // C++0x 5.16p6 + // LValue-to-rvalue, array-to-pointer, and function-to-pointer standard + // conversions are performed on the second and third operands. + LHS = DefaultFunctionArrayLvalueConversion(LHS.take()); + RHS = DefaultFunctionArrayLvalueConversion(RHS.take()); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + LTy = LHS.get()->getType(); + RTy = RHS.get()->getType(); + + // After those conversions, one of the following shall hold: + // -- The second and third operands have the same type; the result + // is of that type. If the operands have class type, the result + // is a prvalue temporary of the result type, which is + // copy-initialized from either the second operand or the third + // operand depending on the value of the first operand. + if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) { + if (LTy->isRecordType()) { + // The operands have class type. Make a temporary copy. + InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy); + ExprResult LHSCopy = PerformCopyInitialization(Entity, + SourceLocation(), + LHS); + if (LHSCopy.isInvalid()) + return QualType(); + + ExprResult RHSCopy = PerformCopyInitialization(Entity, + SourceLocation(), + RHS); + if (RHSCopy.isInvalid()) + return QualType(); + + LHS = LHSCopy; + RHS = RHSCopy; + } + + return LTy; + } + + // Extension: conditional operator involving vector types. + if (LTy->isVectorType() || RTy->isVectorType()) + return CheckVectorOperands(QuestionLoc, LHS, RHS); + + // -- The second and third operands have arithmetic or enumeration type; + // the usual arithmetic conversions are performed to bring them to a + // common type, and the result is of that type. + if (LTy->isArithmeticType() && RTy->isArithmeticType()) { + UsualArithmeticConversions(LHS, RHS); + if (LHS.isInvalid() || RHS.isInvalid()) + return QualType(); + return LHS.get()->getType(); + } + + // -- The second and third operands have pointer type, or one has pointer + // type and the other is a null pointer constant; pointer conversions + // and qualification conversions are performed to bring them to their + // composite pointer type. The result is of the composite pointer type. + // -- The second and third operands have pointer to member type, or one has + // pointer to member type and the other is a null pointer constant; + // pointer to member conversions and qualification conversions are + // performed to bring them to a common type, whose cv-qualification + // shall match the cv-qualification of either the second or the third + // operand. The result is of the common type. + bool NonStandardCompositeType = false; + QualType Composite = FindCompositePointerType(QuestionLoc, LHS, RHS, + isSFINAEContext()? 0 : &NonStandardCompositeType); + if (!Composite.isNull()) { + if (NonStandardCompositeType) + Diag(QuestionLoc, + diag::ext_typecheck_cond_incompatible_operands_nonstandard) + << LTy << RTy << Composite + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + + return Composite; + } + + // Similarly, attempt to find composite type of two objective-c pointers. + Composite = FindCompositeObjCPointerType(LHS, RHS, QuestionLoc); + if (!Composite.isNull()) + return Composite; + + // Check if we are using a null with a non-pointer type. + if (DiagnoseConditionalForNull(LHS.get(), RHS.get(), QuestionLoc)) + return QualType(); + + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHS.get()->getType() << RHS.get()->getType() + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); +} + +/// \brief Find a merged pointer type and convert the two expressions to it. +/// +/// This finds the composite pointer type (or member pointer type) for @p E1 +/// and @p E2 according to C++0x 5.9p2. It converts both expressions to this +/// type and returns it. +/// It does not emit diagnostics. +/// +/// \param Loc The location of the operator requiring these two expressions to +/// be converted to the composite pointer type. +/// +/// If \p NonStandardCompositeType is non-NULL, then we are permitted to find +/// a non-standard (but still sane) composite type to which both expressions +/// can be converted. When such a type is chosen, \c *NonStandardCompositeType +/// will be set true. +QualType Sema::FindCompositePointerType(SourceLocation Loc, + Expr *&E1, Expr *&E2, + bool *NonStandardCompositeType) { + if (NonStandardCompositeType) + *NonStandardCompositeType = false; + + assert(getLangOptions().CPlusPlus && "This function assumes C++"); + QualType T1 = E1->getType(), T2 = E2->getType(); + + if (!T1->isAnyPointerType() && !T1->isMemberPointerType() && + !T2->isAnyPointerType() && !T2->isMemberPointerType()) + return QualType(); + + // C++0x 5.9p2 + // Pointer conversions and qualification conversions are performed on + // pointer operands to bring them to their composite pointer type. If + // one operand is a null pointer constant, the composite pointer type is + // the type of the other operand. + if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + if (T2->isMemberPointerType()) + E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take(); + else + E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take(); + return T2; + } + if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { + if (T1->isMemberPointerType()) + E2 = ImpCastExprToType(E2, T1, CK_NullToMemberPointer).take(); + else + E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take(); + return T1; + } + + // Now both have to be pointers or member pointers. + if ((!T1->isPointerType() && !T1->isMemberPointerType()) || + (!T2->isPointerType() && !T2->isMemberPointerType())) + return QualType(); + + // Otherwise, of one of the operands has type "pointer to cv1 void," then + // the other has type "pointer to cv2 T" and the composite pointer type is + // "pointer to cv12 void," where cv12 is the union of cv1 and cv2. + // Otherwise, the composite pointer type is a pointer type similar to the + // type of one of the operands, with a cv-qualification signature that is + // the union of the cv-qualification signatures of the operand types. + // In practice, the first part here is redundant; it's subsumed by the second. + // What we do here is, we build the two possible composite types, and try the + // conversions in both directions. If only one works, or if the two composite + // types are the same, we have succeeded. + // FIXME: extended qualifiers? + typedef llvm::SmallVector<unsigned, 4> QualifierVector; + QualifierVector QualifierUnion; + typedef llvm::SmallVector<std::pair<const Type *, const Type *>, 4> + ContainingClassVector; + ContainingClassVector MemberOfClass; + QualType Composite1 = Context.getCanonicalType(T1), + Composite2 = Context.getCanonicalType(T2); + unsigned NeedConstBefore = 0; + do { + const PointerType *Ptr1, *Ptr2; + if ((Ptr1 = Composite1->getAs<PointerType>()) && + (Ptr2 = Composite2->getAs<PointerType>())) { + Composite1 = Ptr1->getPointeeType(); + Composite2 = Ptr2->getPointeeType(); + + // If we're allowed to create a non-standard composite type, keep track + // of where we need to fill in additional 'const' qualifiers. + if (NonStandardCompositeType && + Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers()) + NeedConstBefore = QualifierUnion.size(); + + QualifierUnion.push_back( + Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers()); + MemberOfClass.push_back(std::make_pair((const Type *)0, (const Type *)0)); + continue; + } + + const MemberPointerType *MemPtr1, *MemPtr2; + if ((MemPtr1 = Composite1->getAs<MemberPointerType>()) && + (MemPtr2 = Composite2->getAs<MemberPointerType>())) { + Composite1 = MemPtr1->getPointeeType(); + Composite2 = MemPtr2->getPointeeType(); + + // If we're allowed to create a non-standard composite type, keep track + // of where we need to fill in additional 'const' qualifiers. + if (NonStandardCompositeType && + Composite1.getCVRQualifiers() != Composite2.getCVRQualifiers()) + NeedConstBefore = QualifierUnion.size(); + + QualifierUnion.push_back( + Composite1.getCVRQualifiers() | Composite2.getCVRQualifiers()); + MemberOfClass.push_back(std::make_pair(MemPtr1->getClass(), + MemPtr2->getClass())); + continue; + } + + // FIXME: block pointer types? + + // Cannot unwrap any more types. + break; + } while (true); + + if (NeedConstBefore && NonStandardCompositeType) { + // Extension: Add 'const' to qualifiers that come before the first qualifier + // mismatch, so that our (non-standard!) composite type meets the + // requirements of C++ [conv.qual]p4 bullet 3. + for (unsigned I = 0; I != NeedConstBefore; ++I) { + if ((QualifierUnion[I] & Qualifiers::Const) == 0) { + QualifierUnion[I] = QualifierUnion[I] | Qualifiers::Const; + *NonStandardCompositeType = true; + } + } + } + + // Rewrap the composites as pointers or member pointers with the union CVRs. + ContainingClassVector::reverse_iterator MOC + = MemberOfClass.rbegin(); + for (QualifierVector::reverse_iterator + I = QualifierUnion.rbegin(), + E = QualifierUnion.rend(); + I != E; (void)++I, ++MOC) { + Qualifiers Quals = Qualifiers::fromCVRMask(*I); + if (MOC->first && MOC->second) { + // Rebuild member pointer type + Composite1 = Context.getMemberPointerType( + Context.getQualifiedType(Composite1, Quals), + MOC->first); + Composite2 = Context.getMemberPointerType( + Context.getQualifiedType(Composite2, Quals), + MOC->second); + } else { + // Rebuild pointer type + Composite1 + = Context.getPointerType(Context.getQualifiedType(Composite1, Quals)); + Composite2 + = Context.getPointerType(Context.getQualifiedType(Composite2, Quals)); + } + } + + // Try to convert to the first composite pointer type. + InitializedEntity Entity1 + = InitializedEntity::InitializeTemporary(Composite1); + InitializationKind Kind + = InitializationKind::CreateCopy(Loc, SourceLocation()); + InitializationSequence E1ToC1(*this, Entity1, Kind, &E1, 1); + InitializationSequence E2ToC1(*this, Entity1, Kind, &E2, 1); + + if (E1ToC1 && E2ToC1) { + // Conversion to Composite1 is viable. + if (!Context.hasSameType(Composite1, Composite2)) { + // Composite2 is a different type from Composite1. Check whether + // Composite2 is also viable. + InitializedEntity Entity2 + = InitializedEntity::InitializeTemporary(Composite2); + InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1); + InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1); + if (E1ToC2 && E2ToC2) { + // Both Composite1 and Composite2 are viable and are different; + // this is an ambiguity. + return QualType(); + } + } + + // Convert E1 to Composite1 + ExprResult E1Result + = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1)); + if (E1Result.isInvalid()) + return QualType(); + E1 = E1Result.takeAs<Expr>(); + + // Convert E2 to Composite1 + ExprResult E2Result + = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1)); + if (E2Result.isInvalid()) + return QualType(); + E2 = E2Result.takeAs<Expr>(); + + return Composite1; + } + + // Check whether Composite2 is viable. + InitializedEntity Entity2 + = InitializedEntity::InitializeTemporary(Composite2); + InitializationSequence E1ToC2(*this, Entity2, Kind, &E1, 1); + InitializationSequence E2ToC2(*this, Entity2, Kind, &E2, 1); + if (!E1ToC2 || !E2ToC2) + return QualType(); + + // Convert E1 to Composite2 + ExprResult E1Result + = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1)); + if (E1Result.isInvalid()) + return QualType(); + E1 = E1Result.takeAs<Expr>(); + + // Convert E2 to Composite2 + ExprResult E2Result + = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1)); + if (E2Result.isInvalid()) + return QualType(); + E2 = E2Result.takeAs<Expr>(); + + return Composite2; +} + +ExprResult Sema::MaybeBindToTemporary(Expr *E) { + if (!E) + return ExprError(); + + if (!Context.getLangOptions().CPlusPlus) + return Owned(E); + + assert(!isa<CXXBindTemporaryExpr>(E) && "Double-bound temporary?"); + + const RecordType *RT = E->getType()->getAs<RecordType>(); + if (!RT) + return Owned(E); + + // If the result is a glvalue, we shouldn't bind it. + if (E->Classify(Context).isGLValue()) + return Owned(E); + + // That should be enough to guarantee that this type is complete. + // If it has a trivial destructor, we can avoid the extra copy. + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->isInvalidDecl() || RD->hasTrivialDestructor()) + return Owned(E); + + CXXTemporary *Temp = CXXTemporary::Create(Context, LookupDestructor(RD)); + ExprTemporaries.push_back(Temp); + if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { + MarkDeclarationReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_temp) + << E->getType()); + } + // FIXME: Add the temporary to the temporaries vector. + return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E)); +} + +Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) { + assert(SubExpr && "sub expression can't be null!"); + + unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries; + assert(ExprTemporaries.size() >= FirstTemporary); + if (ExprTemporaries.size() == FirstTemporary) + return SubExpr; + + Expr *E = ExprWithCleanups::Create(Context, SubExpr, + &ExprTemporaries[FirstTemporary], + ExprTemporaries.size() - FirstTemporary); + ExprTemporaries.erase(ExprTemporaries.begin() + FirstTemporary, + ExprTemporaries.end()); + + return E; +} + +ExprResult +Sema::MaybeCreateExprWithCleanups(ExprResult SubExpr) { + if (SubExpr.isInvalid()) + return ExprError(); + + return Owned(MaybeCreateExprWithCleanups(SubExpr.take())); +} + +Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { + assert(SubStmt && "sub statement can't be null!"); + + unsigned FirstTemporary = ExprEvalContexts.back().NumTemporaries; + assert(ExprTemporaries.size() >= FirstTemporary); + if (ExprTemporaries.size() == FirstTemporary) + return SubStmt; + + // FIXME: In order to attach the temporaries, wrap the statement into + // a StmtExpr; currently this is only used for asm statements. + // This is hacky, either create a new CXXStmtWithTemporaries statement or + // a new AsmStmtWithTemporaries. + CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, &SubStmt, 1, + SourceLocation(), + SourceLocation()); + Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), + SourceLocation()); + return MaybeCreateExprWithCleanups(E); +} + +ExprResult +Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, + tok::TokenKind OpKind, ParsedType &ObjectType, + bool &MayBePseudoDestructor) { + // Since this might be a postfix expression, get rid of ParenListExprs. + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); + if (Result.isInvalid()) return ExprError(); + Base = Result.get(); + + QualType BaseType = Base->getType(); + MayBePseudoDestructor = false; + if (BaseType->isDependentType()) { + // If we have a pointer to a dependent type and are using the -> operator, + // the object type is the type that the pointer points to. We might still + // have enough information about that type to do something useful. + if (OpKind == tok::arrow) + if (const PointerType *Ptr = BaseType->getAs<PointerType>()) + BaseType = Ptr->getPointeeType(); + + ObjectType = ParsedType::make(BaseType); + MayBePseudoDestructor = true; + return Owned(Base); + } + + // C++ [over.match.oper]p8: + // [...] When operator->returns, the operator-> is applied to the value + // returned, with the original second operand. + if (OpKind == tok::arrow) { + // The set of types we've considered so far. + llvm::SmallPtrSet<CanQualType,8> CTypes; + llvm::SmallVector<SourceLocation, 8> Locations; + CTypes.insert(Context.getCanonicalType(BaseType)); + + while (BaseType->isRecordType()) { + Result = BuildOverloadedArrowExpr(S, Base, OpLoc); + if (Result.isInvalid()) + return ExprError(); + Base = Result.get(); + if (CXXOperatorCallExpr *OpCall = dyn_cast<CXXOperatorCallExpr>(Base)) + Locations.push_back(OpCall->getDirectCallee()->getLocation()); + BaseType = Base->getType(); + CanQualType CBaseType = Context.getCanonicalType(BaseType); + if (!CTypes.insert(CBaseType)) { + Diag(OpLoc, diag::err_operator_arrow_circular); + for (unsigned i = 0; i < Locations.size(); i++) + Diag(Locations[i], diag::note_declared_at); + return ExprError(); + } + } + + if (BaseType->isPointerType()) + BaseType = BaseType->getPointeeType(); + } + + // We could end up with various non-record types here, such as extended + // vector types or Objective-C interfaces. Just return early and let + // ActOnMemberReferenceExpr do the work. + if (!BaseType->isRecordType()) { + // C++ [basic.lookup.classref]p2: + // [...] If the type of the object expression is of pointer to scalar + // type, the unqualified-id is looked up in the context of the complete + // postfix-expression. + // + // This also indicates that we should be parsing a + // pseudo-destructor-name. + ObjectType = ParsedType(); + MayBePseudoDestructor = true; + return Owned(Base); + } + + // The object type must be complete (or dependent). + if (!BaseType->isDependentType() && + RequireCompleteType(OpLoc, BaseType, + PDiag(diag::err_incomplete_member_access))) + return ExprError(); + + // C++ [basic.lookup.classref]p2: + // If the id-expression in a class member access (5.2.5) is an + // unqualified-id, and the type of the object expression is of a class + // type C (or of pointer to a class type C), the unqualified-id is looked + // up in the scope of class C. [...] + ObjectType = ParsedType::make(BaseType); + return move(Base); +} + +ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, + Expr *MemExpr) { + SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc); + Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call) + << isa<CXXPseudoDestructorExpr>(MemExpr) + << FixItHint::CreateInsertion(ExpectedLParenLoc, "()"); + + return ActOnCallExpr(/*Scope*/ 0, + MemExpr, + /*LPLoc*/ ExpectedLParenLoc, + MultiExprArg(), + /*RPLoc*/ ExpectedLParenLoc); +} + +ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TypeSourceInfo *ScopeTypeInfo, + SourceLocation CCLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage Destructed, + bool HasTrailingLParen) { + TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); + + // C++ [expr.pseudo]p2: + // The left-hand side of the dot operator shall be of scalar type. The + // left-hand side of the arrow operator shall be of pointer to scalar type. + // This scalar type is the object type. + QualType ObjectType = Base->getType(); + if (OpKind == tok::arrow) { + if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { + ObjectType = Ptr->getPointeeType(); + } else if (!Base->isTypeDependent()) { + // The user wrote "p->" when she probably meant "p."; fix it. + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << ObjectType << true + << FixItHint::CreateReplacement(OpLoc, "."); + if (isSFINAEContext()) + return ExprError(); + + OpKind = tok::period; + } + } + + if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) { + Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar) + << ObjectType << Base->getSourceRange(); + return ExprError(); + } + + // C++ [expr.pseudo]p2: + // [...] The cv-unqualified versions of the object type and of the type + // designated by the pseudo-destructor-name shall be the same type. + if (DestructedTypeInfo) { + QualType DestructedType = DestructedTypeInfo->getType(); + SourceLocation DestructedTypeStart + = DestructedTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(); + if (!DestructedType->isDependentType() && !ObjectType->isDependentType() && + !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) { + Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch) + << ObjectType << DestructedType << Base->getSourceRange() + << DestructedTypeInfo->getTypeLoc().getLocalSourceRange(); + + // Recover by setting the destructed type to the object type. + DestructedType = ObjectType; + DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType, + DestructedTypeStart); + Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo); + } + } + + // C++ [expr.pseudo]p2: + // [...] Furthermore, the two type-names in a pseudo-destructor-name of the + // form + // + // ::[opt] nested-name-specifier[opt] type-name :: ~ type-name + // + // shall designate the same scalar type. + if (ScopeTypeInfo) { + QualType ScopeType = ScopeTypeInfo->getType(); + if (!ScopeType->isDependentType() && !ObjectType->isDependentType() && + !Context.hasSameUnqualifiedType(ScopeType, ObjectType)) { + + Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(), + diag::err_pseudo_dtor_type_mismatch) + << ObjectType << ScopeType << Base->getSourceRange() + << ScopeTypeInfo->getTypeLoc().getLocalSourceRange(); + + ScopeType = QualType(); + ScopeTypeInfo = 0; + } + } + + Expr *Result + = new (Context) CXXPseudoDestructorExpr(Context, Base, + OpKind == tok::arrow, OpLoc, + SS.getWithLocInContext(Context), + ScopeTypeInfo, + CCLoc, + TildeLoc, + Destructed); + + if (HasTrailingLParen) + return Owned(Result); + + return DiagnoseDtorReference(Destructed.getLocation(), Result); +} + +ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + CXXScopeSpec &SS, + UnqualifiedId &FirstTypeName, + SourceLocation CCLoc, + SourceLocation TildeLoc, + UnqualifiedId &SecondTypeName, + bool HasTrailingLParen) { + assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || + FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) && + "Invalid first type name in pseudo-destructor"); + assert((SecondTypeName.getKind() == UnqualifiedId::IK_TemplateId || + SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) && + "Invalid second type name in pseudo-destructor"); + + // C++ [expr.pseudo]p2: + // The left-hand side of the dot operator shall be of scalar type. The + // left-hand side of the arrow operator shall be of pointer to scalar type. + // This scalar type is the object type. + QualType ObjectType = Base->getType(); + if (OpKind == tok::arrow) { + if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) { + ObjectType = Ptr->getPointeeType(); + } else if (!ObjectType->isDependentType()) { + // The user wrote "p->" when she probably meant "p."; fix it. + Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << ObjectType << true + << FixItHint::CreateReplacement(OpLoc, "."); + if (isSFINAEContext()) + return ExprError(); + + OpKind = tok::period; + } + } + + // Compute the object type that we should use for name lookup purposes. Only + // record types and dependent types matter. + ParsedType ObjectTypePtrForLookup; + if (!SS.isSet()) { + if (ObjectType->isRecordType()) + ObjectTypePtrForLookup = ParsedType::make(ObjectType); + else if (ObjectType->isDependentType()) + ObjectTypePtrForLookup = ParsedType::make(Context.DependentTy); + } + + // Convert the name of the type being destructed (following the ~) into a + // type (with source-location information). + QualType DestructedType; + TypeSourceInfo *DestructedTypeInfo = 0; + PseudoDestructorTypeStorage Destructed; + if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) { + ParsedType T = getTypeName(*SecondTypeName.Identifier, + SecondTypeName.StartLocation, + S, &SS, true, false, ObjectTypePtrForLookup); + if (!T && + ((SS.isSet() && !computeDeclContext(SS, false)) || + (!SS.isSet() && ObjectType->isDependentType()))) { + // The name of the type being destroyed is a dependent name, and we + // couldn't find anything useful in scope. Just store the identifier and + // it's location, and we'll perform (qualified) name lookup again at + // template instantiation time. + Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier, + SecondTypeName.StartLocation); + } else if (!T) { + Diag(SecondTypeName.StartLocation, + diag::err_pseudo_dtor_destructor_non_type) + << SecondTypeName.Identifier << ObjectType; + if (isSFINAEContext()) + return ExprError(); + + // Recover by assuming we had the right type all along. + DestructedType = ObjectType; + } else + DestructedType = GetTypeFromParser(T, &DestructedTypeInfo); + } else { + // Resolve the template-id to a type. + TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId; + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + if (T.isInvalid() || !T.get()) { + // Recover by assuming we had the right type all along. + DestructedType = ObjectType; + } else + DestructedType = GetTypeFromParser(T.get(), &DestructedTypeInfo); + } + + // If we've performed some kind of recovery, (re-)build the type source + // information. + if (!DestructedType.isNull()) { + if (!DestructedTypeInfo) + DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType, + SecondTypeName.StartLocation); + Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo); + } + + // Convert the name of the scope type (the type prior to '::') into a type. + TypeSourceInfo *ScopeTypeInfo = 0; + QualType ScopeType; + if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || + FirstTypeName.Identifier) { + if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) { + ParsedType T = getTypeName(*FirstTypeName.Identifier, + FirstTypeName.StartLocation, + S, &SS, true, false, ObjectTypePtrForLookup); + if (!T) { + Diag(FirstTypeName.StartLocation, + diag::err_pseudo_dtor_destructor_non_type) + << FirstTypeName.Identifier << ObjectType; + + if (isSFINAEContext()) + return ExprError(); + + // Just drop this type. It's unnecessary anyway. + ScopeType = QualType(); + } else + ScopeType = GetTypeFromParser(T, &ScopeTypeInfo); + } else { + // Resolve the template-id to a type. + TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId; + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + TypeResult T = ActOnTemplateIdType(TemplateId->SS, + TemplateId->Template, + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->RAngleLoc); + if (T.isInvalid() || !T.get()) { + // Recover by dropping this type. + ScopeType = QualType(); + } else + ScopeType = GetTypeFromParser(T.get(), &ScopeTypeInfo); + } + } + + if (!ScopeType.isNull() && !ScopeTypeInfo) + ScopeTypeInfo = Context.getTrivialTypeSourceInfo(ScopeType, + FirstTypeName.StartLocation); + + + return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS, + ScopeTypeInfo, CCLoc, TildeLoc, + Destructed, HasTrailingLParen); +} + +ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, + CXXMethodDecl *Method) { + ExprResult Exp = PerformObjectArgumentInitialization(E, /*Qualifier=*/0, + FoundDecl, Method); + if (Exp.isInvalid()) + return true; + + MemberExpr *ME = + new (Context) MemberExpr(Exp.take(), /*IsArrow=*/false, Method, + SourceLocation(), Method->getType(), + VK_RValue, OK_Ordinary); + QualType ResultType = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultType); + ResultType = ResultType.getNonLValueExprType(Context); + + MarkDeclarationReferenced(Exp.get()->getLocStart(), Method); + CXXMemberCallExpr *CE = + new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK, + Exp.get()->getLocEnd()); + return CE; +} + +ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, + SourceLocation RParen) { + return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand, + Operand->CanThrow(Context), + KeyLoc, RParen)); +} + +ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation, + Expr *Operand, SourceLocation RParen) { + return BuildCXXNoexceptExpr(KeyLoc, Operand, RParen); +} + +/// Perform the conversions required for an expression used in a +/// context that ignores the result. +ExprResult Sema::IgnoredValueConversions(Expr *E) { + // C99 6.3.2.1: + // [Except in specific positions,] an lvalue that does not have + // array type is converted to the value stored in the + // designated object (and is no longer an lvalue). + if (E->isRValue()) return Owned(E); + + // We always want to do this on ObjC property references. + if (E->getObjectKind() == OK_ObjCProperty) { + ExprResult Res = ConvertPropertyForRValue(E); + if (Res.isInvalid()) return Owned(E); + E = Res.take(); + if (E->isRValue()) return Owned(E); + } + + // Otherwise, this rule does not apply in C++, at least not for the moment. + if (getLangOptions().CPlusPlus) return Owned(E); + + // GCC seems to also exclude expressions of incomplete enum type. + if (const EnumType *T = E->getType()->getAs<EnumType>()) { + if (!T->getDecl()->isComplete()) { + // FIXME: stupid workaround for a codegen bug! + E = ImpCastExprToType(E, Context.VoidTy, CK_ToVoid).take(); + return Owned(E); + } + } + + ExprResult Res = DefaultFunctionArrayLvalueConversion(E); + if (Res.isInvalid()) + return Owned(E); + E = Res.take(); + + if (!E->getType()->isVoidType()) + RequireCompleteType(E->getExprLoc(), E->getType(), + diag::err_incomplete_type); + return Owned(E); +} + +ExprResult Sema::ActOnFinishFullExpr(Expr *FE) { + ExprResult FullExpr = Owned(FE); + + if (!FullExpr.get()) + return ExprError(); + + if (DiagnoseUnexpandedParameterPack(FullExpr.get())) + return ExprError(); + + FullExpr = CheckPlaceholderExpr(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + FullExpr = IgnoredValueConversions(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + CheckImplicitConversions(FullExpr.get()); + return MaybeCreateExprWithCleanups(FullExpr); +} + +StmtResult Sema::ActOnFinishFullStmt(Stmt *FullStmt) { + if (!FullStmt) return StmtError(); + + return MaybeCreateStmtWithCleanups(FullStmt); +} + +bool Sema::CheckMicrosoftIfExistsSymbol(CXXScopeSpec &SS, + UnqualifiedId &Name) { + DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); + DeclarationName TargetName = TargetNameInfo.getName(); + if (!TargetName) + return false; + + // Do the redeclaration lookup in the current scope. + LookupResult R(*this, TargetNameInfo, Sema::LookupAnyName, + Sema::NotForRedeclaration); + R.suppressDiagnostics(); + LookupParsedName(R, getCurScope(), &SS); + return !R.empty(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp new file mode 100644 index 0000000..cb5c1e0 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -0,0 +1,1366 @@ +//===--- SemaExprObjC.cpp - Semantic Analysis for ObjC Expressions --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for Objective-C expressions. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallString.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; +using namespace sema; + +ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, + Expr **strings, + unsigned NumStrings) { + StringLiteral **Strings = reinterpret_cast<StringLiteral**>(strings); + + // Most ObjC strings are formed out of a single piece. However, we *can* + // have strings formed out of multiple @ strings with multiple pptokens in + // each one, e.g. @"foo" "bar" @"baz" "qux" which need to be turned into one + // StringLiteral for ObjCStringLiteral to hold onto. + StringLiteral *S = Strings[0]; + + // If we have a multi-part string, merge it all together. + if (NumStrings != 1) { + // Concatenate objc strings. + llvm::SmallString<128> StrBuf; + llvm::SmallVector<SourceLocation, 8> StrLocs; + + for (unsigned i = 0; i != NumStrings; ++i) { + S = Strings[i]; + + // ObjC strings can't be wide. + if (S->isWide()) { + Diag(S->getLocStart(), diag::err_cfstring_literal_not_string_constant) + << S->getSourceRange(); + return true; + } + + // Append the string. + StrBuf += S->getString(); + + // Get the locations of the string tokens. + StrLocs.append(S->tokloc_begin(), S->tokloc_end()); + } + + // Create the aggregate string with the appropriate content and location + // information. + S = StringLiteral::Create(Context, &StrBuf[0], StrBuf.size(), + /*Wide=*/false, /*Pascal=*/false, + Context.getPointerType(Context.CharTy), + &StrLocs[0], StrLocs.size()); + } + + // Verify that this composite string is acceptable for ObjC strings. + if (CheckObjCString(S)) + return true; + + // Initialize the constant string interface lazily. This assumes + // the NSString interface is seen in this translation unit. Note: We + // don't use NSConstantString, since the runtime team considers this + // interface private (even though it appears in the header files). + QualType Ty = Context.getObjCConstantStringInterface(); + if (!Ty.isNull()) { + Ty = Context.getObjCObjectPointerType(Ty); + } else if (getLangOptions().NoConstantCFStrings) { + IdentifierInfo *NSIdent=0; + std::string StringClass(getLangOptions().ObjCConstantStringClass); + + if (StringClass.empty()) + NSIdent = &Context.Idents.get("NSConstantString"); + else + NSIdent = &Context.Idents.get(StringClass); + + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0], + LookupOrdinaryName); + if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { + Context.setObjCConstantStringInterface(StrIF); + Ty = Context.getObjCConstantStringInterface(); + Ty = Context.getObjCObjectPointerType(Ty); + } else { + // If there is no NSConstantString interface defined then treat this + // as error and recover from it. + Diag(S->getLocStart(), diag::err_no_nsconstant_string_class) << NSIdent + << S->getSourceRange(); + Ty = Context.getObjCIdType(); + } + } else { + IdentifierInfo *NSIdent = &Context.Idents.get("NSString"); + NamedDecl *IF = LookupSingleName(TUScope, NSIdent, AtLocs[0], + LookupOrdinaryName); + if (ObjCInterfaceDecl *StrIF = dyn_cast_or_null<ObjCInterfaceDecl>(IF)) { + Context.setObjCConstantStringInterface(StrIF); + Ty = Context.getObjCConstantStringInterface(); + Ty = Context.getObjCObjectPointerType(Ty); + } else { + // If there is no NSString interface defined then treat constant + // strings as untyped objects and let the runtime figure it out later. + Ty = Context.getObjCIdType(); + } + } + + return new (Context) ObjCStringLiteral(S, Ty, AtLocs[0]); +} + +ExprResult Sema::BuildObjCEncodeExpression(SourceLocation AtLoc, + TypeSourceInfo *EncodedTypeInfo, + SourceLocation RParenLoc) { + QualType EncodedType = EncodedTypeInfo->getType(); + QualType StrTy; + if (EncodedType->isDependentType()) + StrTy = Context.DependentTy; + else { + if (!EncodedType->getAsArrayTypeUnsafe()) // Incomplete array is handled. + if (RequireCompleteType(AtLoc, EncodedType, + PDiag(diag::err_incomplete_type_objc_at_encode) + << EncodedTypeInfo->getTypeLoc().getSourceRange())) + return ExprError(); + + std::string Str; + Context.getObjCEncodingForType(EncodedType, Str); + + // The type of @encode is the same as the type of the corresponding string, + // which is an array type. + StrTy = Context.CharTy; + // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). + if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) + StrTy.addConst(); + StrTy = Context.getConstantArrayType(StrTy, llvm::APInt(32, Str.size()+1), + ArrayType::Normal, 0); + } + + return new (Context) ObjCEncodeExpr(StrTy, EncodedTypeInfo, AtLoc, RParenLoc); +} + +ExprResult Sema::ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncodeLoc, + SourceLocation LParenLoc, + ParsedType ty, + SourceLocation RParenLoc) { + // FIXME: Preserve type source info ? + TypeSourceInfo *TInfo; + QualType EncodedType = GetTypeFromParser(ty, &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(EncodedType, + PP.getLocForEndOfToken(LParenLoc)); + + return BuildObjCEncodeExpression(AtLoc, TInfo, RParenLoc); +} + +ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, + SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LParenLoc, RParenLoc), false, false); + if (!Method) + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LParenLoc, RParenLoc)); + if (!Method) + Diag(SelLoc, diag::warn_undeclared_selector) << Sel; + + llvm::DenseMap<Selector, SourceLocation>::iterator Pos + = ReferencedSelectors.find(Sel); + if (Pos == ReferencedSelectors.end()) + ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); + + QualType Ty = Context.getObjCSelType(); + return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); +} + +ExprResult Sema::ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + ObjCProtocolDecl* PDecl = LookupProtocol(ProtocolId, ProtoLoc); + if (!PDecl) { + Diag(ProtoLoc, diag::err_undeclared_protocol) << ProtocolId; + return true; + } + + QualType Ty = Context.getObjCProtoType(); + if (Ty.isNull()) + return true; + Ty = Context.getObjCObjectPointerType(Ty); + return new (Context) ObjCProtocolExpr(Ty, PDecl, AtLoc, RParenLoc); +} + +/// Try to capture an implicit reference to 'self'. +ObjCMethodDecl *Sema::tryCaptureObjCSelf() { + // Ignore block scopes: we can capture through them. + DeclContext *DC = CurContext; + while (true) { + if (isa<BlockDecl>(DC)) DC = cast<BlockDecl>(DC)->getDeclContext(); + else if (isa<EnumDecl>(DC)) DC = cast<EnumDecl>(DC)->getDeclContext(); + else break; + } + + // If we're not in an ObjC method, error out. Note that, unlike the + // C++ case, we don't require an instance method --- class methods + // still have a 'self', and we really do still need to capture it! + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(DC); + if (!method) + return 0; + + ImplicitParamDecl *self = method->getSelfDecl(); + assert(self && "capturing 'self' in non-definition?"); + + // Mark that we're closing on 'this' in all the block scopes, if applicable. + for (unsigned idx = FunctionScopes.size() - 1; + isa<BlockScopeInfo>(FunctionScopes[idx]); + --idx) { + BlockScopeInfo *blockScope = cast<BlockScopeInfo>(FunctionScopes[idx]); + unsigned &captureIndex = blockScope->CaptureMap[self]; + if (captureIndex) break; + + bool nested = isa<BlockScopeInfo>(FunctionScopes[idx-1]); + blockScope->Captures.push_back( + BlockDecl::Capture(self, /*byref*/ false, nested, /*copy*/ 0)); + captureIndex = blockScope->Captures.size(); // +1 + } + + return method; +} + +QualType Sema::getMessageSendResultType(QualType ReceiverType, + ObjCMethodDecl *Method, + bool isClassMessage, bool isSuperMessage) { + assert(Method && "Must have a method"); + if (!Method->hasRelatedResultType()) + return Method->getSendResultType(); + + // If a method has a related return type: + // - if the method found is an instance method, but the message send + // was a class message send, T is the declared return type of the method + // found + if (Method->isInstanceMethod() && isClassMessage) + return Method->getSendResultType(); + + // - if the receiver is super, T is a pointer to the class of the + // enclosing method definition + if (isSuperMessage) { + if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) + if (ObjCInterfaceDecl *Class = CurMethod->getClassInterface()) + return Context.getObjCObjectPointerType( + Context.getObjCInterfaceType(Class)); + } + + // - if the receiver is the name of a class U, T is a pointer to U + if (ReceiverType->getAs<ObjCInterfaceType>() || + ReceiverType->isObjCQualifiedInterfaceType()) + return Context.getObjCObjectPointerType(ReceiverType); + // - if the receiver is of type Class or qualified Class type, + // T is the declared return type of the method. + if (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()) + return Method->getSendResultType(); + + // - if the receiver is id, qualified id, Class, or qualified Class, T + // is the receiver type, otherwise + // - T is the type of the receiver expression. + return ReceiverType; +} + +void Sema::EmitRelatedResultTypeNote(const Expr *E) { + E = E->IgnoreParenImpCasts(); + const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E); + if (!MsgSend) + return; + + const ObjCMethodDecl *Method = MsgSend->getMethodDecl(); + if (!Method) + return; + + if (!Method->hasRelatedResultType()) + return; + + if (Context.hasSameUnqualifiedType(Method->getResultType() + .getNonReferenceType(), + MsgSend->getType())) + return; + + Diag(Method->getLocation(), diag::note_related_result_type_inferred) + << Method->isInstanceMethod() << Method->getSelector() + << MsgSend->getType(); +} + +bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, + Expr **Args, unsigned NumArgs, + Selector Sel, ObjCMethodDecl *Method, + bool isClassMessage, bool isSuperMessage, + SourceLocation lbrac, SourceLocation rbrac, + QualType &ReturnType, ExprValueKind &VK) { + if (!Method) { + // Apply default argument promotion as for (C99 6.5.2.2p6). + for (unsigned i = 0; i != NumArgs; i++) { + if (Args[i]->isTypeDependent()) + continue; + + ExprResult Result = DefaultArgumentPromotion(Args[i]); + if (Result.isInvalid()) + return true; + Args[i] = Result.take(); + } + + unsigned DiagID = isClassMessage ? diag::warn_class_method_not_found : + diag::warn_inst_method_not_found; + Diag(lbrac, DiagID) + << Sel << isClassMessage << SourceRange(lbrac, rbrac); + ReturnType = Context.getObjCIdType(); + VK = VK_RValue; + return false; + } + + ReturnType = getMessageSendResultType(ReceiverType, Method, isClassMessage, + isSuperMessage); + VK = Expr::getValueKindForType(Method->getResultType()); + + unsigned NumNamedArgs = Sel.getNumArgs(); + // Method might have more arguments than selector indicates. This is due + // to addition of c-style arguments in method. + if (Method->param_size() > Sel.getNumArgs()) + NumNamedArgs = Method->param_size(); + // FIXME. This need be cleaned up. + if (NumArgs < NumNamedArgs) { + Diag(lbrac, diag::err_typecheck_call_too_few_args) + << 2 << NumNamedArgs << NumArgs; + return false; + } + + bool IsError = false; + for (unsigned i = 0; i < NumNamedArgs; i++) { + // We can't do any type-checking on a type-dependent argument. + if (Args[i]->isTypeDependent()) + continue; + + Expr *argExpr = Args[i]; + + ParmVarDecl *Param = Method->param_begin()[i]; + assert(argExpr && "CheckMessageArgumentTypes(): missing expression"); + + if (RequireCompleteType(argExpr->getSourceRange().getBegin(), + Param->getType(), + PDiag(diag::err_call_incomplete_argument) + << argExpr->getSourceRange())) + return true; + + InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, + Param); + ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr)); + if (ArgE.isInvalid()) + IsError = true; + else + Args[i] = ArgE.takeAs<Expr>(); + } + + // Promote additional arguments to variadic methods. + if (Method->isVariadic()) { + for (unsigned i = NumNamedArgs; i < NumArgs; ++i) { + if (Args[i]->isTypeDependent()) + continue; + + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + Args[i] = Arg.take(); + } + } else { + // Check for extra arguments to non-variadic methods. + if (NumArgs != NumNamedArgs) { + Diag(Args[NumNamedArgs]->getLocStart(), + diag::err_typecheck_call_too_many_args) + << 2 /*method*/ << NumNamedArgs << NumArgs + << Method->getSourceRange() + << SourceRange(Args[NumNamedArgs]->getLocStart(), + Args[NumArgs-1]->getLocEnd()); + } + } + // diagnose nonnull arguments. + for (specific_attr_iterator<NonNullAttr> + i = Method->specific_attr_begin<NonNullAttr>(), + e = Method->specific_attr_end<NonNullAttr>(); i != e; ++i) { + CheckNonNullArguments(*i, Args, lbrac); + } + + DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs); + return IsError; +} + +bool Sema::isSelfExpr(Expr *RExpr) { + // 'self' is objc 'self' in an objc method only. + DeclContext *DC = CurContext; + while (isa<BlockDecl>(DC)) + DC = DC->getParent(); + if (DC && !isa<ObjCMethodDecl>(DC)) + return false; + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(RExpr)) + if (ICE->getCastKind() == CK_LValueToRValue) + RExpr = ICE->getSubExpr(); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(RExpr)) + if (DRE->getDecl()->getIdentifier() == &Context.Idents.get("self")) + return true; + return false; +} + +// Helper method for ActOnClassMethod/ActOnInstanceMethod. +// Will search "local" class/category implementations for a method decl. +// If failed, then we search in class's root for an instance method. +// Returns 0 if no method is found. +ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel, + ObjCInterfaceDecl *ClassDecl) { + ObjCMethodDecl *Method = 0; + // lookup in class and all superclasses + while (ClassDecl && !Method) { + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Method = ImpDecl->getClassMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Method) + Method = ClassDecl->getCategoryClassMethod(Sel); + + // Before we give up, check if the selector is an instance method. + // But only in the root. This matches gcc's behaviour and what the + // runtime expects. + if (!Method && !ClassDecl->getSuperClass()) { + Method = ClassDecl->lookupInstanceMethod(Sel); + // Look through local category implementations associated + // with the root class. + if (!Method) + Method = LookupPrivateInstanceMethod(Sel, ClassDecl); + } + + ClassDecl = ClassDecl->getSuperClass(); + } + return Method; +} + +ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, + ObjCInterfaceDecl *ClassDecl) { + ObjCMethodDecl *Method = 0; + while (ClassDecl && !Method) { + // If we have implementations in scope, check "private" methods. + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Method = ImpDecl->getInstanceMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Method) + Method = ClassDecl->getCategoryInstanceMethod(Sel); + ClassDecl = ClassDecl->getSuperClass(); + } + return Method; +} + +/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier +/// list of a qualified objective pointer type. +ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool Instance) +{ + ObjCMethodDecl *MD = 0; + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) { + ObjCProtocolDecl *PROTO = (*I); + if ((MD = PROTO->lookupMethod(Sel, Instance))) { + return MD; + } + } + return 0; +} + +/// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an +/// objective C interface. This is a property reference expression. +ExprResult Sema:: +HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, + Expr *BaseExpr, DeclarationName MemberName, + SourceLocation MemberLoc, + SourceLocation SuperLoc, QualType SuperType, + bool Super) { + const ObjCInterfaceType *IFaceT = OPT->getInterfaceType(); + ObjCInterfaceDecl *IFace = IFaceT->getDecl(); + + if (MemberName.getNameKind() != DeclarationName::Identifier) { + Diag(MemberLoc, diag::err_invalid_property_name) + << MemberName << QualType(OPT, 0); + return ExprError(); + } + + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + + if (IFace->isForwardDecl()) { + Diag(MemberLoc, diag::err_property_not_found_forward_class) + << MemberName << QualType(OPT, 0); + Diag(IFace->getLocation(), diag::note_forward_class); + return ExprError(); + } + // Search for a declared property first. + if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Member)) { + // Check whether we can reference this property. + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + QualType ResTy = PD->getType(); + ResTy = ResTy.getNonLValueExprType(Context); + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); + if (Getter && + (Getter->hasRelatedResultType() + || DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc))) + ResTy = getMessageSendResultType(QualType(OPT, 0), Getter, false, + Super); + + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, + VK_LValue, OK_ObjCProperty, + MemberLoc, BaseExpr)); + } + // Check protocols on qualified interfaces. + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Member)) { + // Check whether we can reference this property. + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); + + QualType T = PD->getType(); + if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + T = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super); + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(PD, T, + VK_LValue, + OK_ObjCProperty, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(PD, T, + VK_LValue, + OK_ObjCProperty, + MemberLoc, + BaseExpr)); + } + // If that failed, look for an "implicit" property by seeing if the nullary + // selector is implemented. + + // FIXME: The logic for looking up nullary and unary selectors should be + // shared with the code in ActOnInstanceMessage. + + Selector Sel = PP.getSelectorTable().getNullarySelector(Member); + ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); + + // May be founf in property's qualified list. + if (!Getter) + Getter = LookupMethodInQualifiedType(Sel, OPT, true); + + // If this reference is in an @implementation, check for 'private' methods. + if (!Getter) + Getter = IFace->lookupPrivateMethod(Sel); + + // Look through local category implementations associated with the class. + if (!Getter) + Getter = IFace->getCategoryInstanceMethod(Sel); + if (Getter) { + // Check if we can reference this property. + if (DiagnoseUseOfDecl(Getter, MemberLoc)) + return ExprError(); + } + // If we found a getter then this may be a valid dot-reference, we + // will look for the matching setter, in case it is needed. + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), Member); + ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); + + // May be founf in property's qualified list. + if (!Setter) + Setter = LookupMethodInQualifiedType(SetterSel, OPT, true); + + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + Setter = IFace->lookupPrivateMethod(SetterSel); + } + // Look through local category implementations associated with the class. + if (!Setter) + Setter = IFace->getCategoryInstanceMethod(SetterSel); + + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) + return ExprError(); + + if (Getter || Setter) { + QualType PType; + if (Getter) + PType = getMessageSendResultType(QualType(OPT, 0), Getter, false, Super); + else { + ParmVarDecl *ArgDecl = *Setter->param_begin(); + PType = ArgDecl->getType(); + } + + ExprValueKind VK = VK_LValue; + ExprObjectKind OK = OK_ObjCProperty; + if (!getLangOptions().CPlusPlus && !PType.hasQualifiers() && + PType->isVoidType()) + VK = VK_RValue, OK = OK_Ordinary; + + if (Super) + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + MemberLoc, + SuperLoc, SuperType)); + else + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + MemberLoc, BaseExpr)); + + } + + // Attempt to correct for typos in property names. + LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName); + if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) && + Res.getAsSingle<ObjCPropertyDecl>()) { + DeclarationName TypoResult = Res.getLookupName(); + Diag(MemberLoc, diag::err_property_not_found_suggest) + << MemberName << QualType(OPT, 0) << TypoResult + << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); + ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>(); + Diag(Property->getLocation(), diag::note_previous_decl) + << Property->getDeclName(); + return HandleExprPropertyRefExpr(OPT, BaseExpr, TypoResult, MemberLoc, + SuperLoc, SuperType, Super); + } + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *Ivar = + IFace->lookupInstanceVariable(Member, ClassDeclared)) { + QualType T = Ivar->getType(); + if (const ObjCObjectPointerType * OBJPT = + T->getAsObjCInterfacePointerType()) { + const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); + if (ObjCInterfaceDecl *IFace = IFaceT->getDecl()) + if (IFace->isForwardDecl()) { + Diag(MemberLoc, diag::err_property_not_as_forward_class) + << MemberName << IFace; + Diag(IFace->getLocation(), diag::note_forward_class); + return ExprError(); + } + } + } + + Diag(MemberLoc, diag::err_property_not_found) + << MemberName << QualType(OPT, 0); + if (Setter) + Diag(Setter->getLocation(), diag::note_getter_unavailable) + << MemberName << BaseExpr->getSourceRange(); + return ExprError(); +} + + + +ExprResult Sema:: +ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation receiverNameLoc, + SourceLocation propertyNameLoc) { + + IdentifierInfo *receiverNamePtr = &receiverName; + ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(receiverNamePtr, + receiverNameLoc); + + bool IsSuper = false; + if (IFace == 0) { + // If the "receiver" is 'super' in a method, handle it as an expression-like + // property reference. + if (receiverNamePtr->isStr("super")) { + IsSuper = true; + + if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf()) { + if (CurMethod->isInstanceMethod()) { + QualType T = + Context.getObjCInterfaceType(CurMethod->getClassInterface()); + T = Context.getObjCObjectPointerType(T); + + return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), + /*BaseExpr*/0, &propertyName, + propertyNameLoc, + receiverNameLoc, T, true); + } + + // Otherwise, if this is a class method, try dispatching to our + // superclass. + IFace = CurMethod->getClassInterface()->getSuperClass(); + } + } + + if (IFace == 0) { + Diag(receiverNameLoc, diag::err_expected_ident_or_lparen); + return ExprError(); + } + } + + // Search for a declared property first. + Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName); + ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel); + + // If this reference is in an @implementation, check for 'private' methods. + if (!Getter) + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Getter = ImpDecl->getClassMethod(Sel); + + if (Getter) { + // FIXME: refactor/share with ActOnMemberReference(). + // Check if we can reference this property. + if (DiagnoseUseOfDecl(Getter, propertyNameLoc)) + return ExprError(); + } + + // Look for the matching setter, in case it is needed. + Selector SetterSel = + SelectorTable::constructSetterName(PP.getIdentifierTable(), + PP.getSelectorTable(), &propertyName); + + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); + if (!Setter) { + // If this reference is in an @implementation, also check for 'private' + // methods. + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) + if (ObjCImplementationDecl *ImpDecl = ClassDecl->getImplementation()) + Setter = ImpDecl->getClassMethod(SetterSel); + } + // Look through local category implementations associated with the class. + if (!Setter) + Setter = IFace->getCategoryClassMethod(SetterSel); + + if (Setter && DiagnoseUseOfDecl(Setter, propertyNameLoc)) + return ExprError(); + + if (Getter || Setter) { + QualType PType; + + ExprValueKind VK = VK_LValue; + if (Getter) { + PType = getMessageSendResultType(Context.getObjCInterfaceType(IFace), + Getter, true, + receiverNamePtr->isStr("super")); + if (!getLangOptions().CPlusPlus && + !PType.hasQualifiers() && PType->isVoidType()) + VK = VK_RValue; + } else { + for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(), + E = Setter->param_end(); PI != E; ++PI) + PType = (*PI)->getType(); + VK = VK_LValue; + } + + ExprObjectKind OK = (VK == VK_RValue ? OK_Ordinary : OK_ObjCProperty); + + if (IsSuper) + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + propertyNameLoc, + receiverNameLoc, + Context.getObjCInterfaceType(IFace))); + + return Owned(new (Context) ObjCPropertyRefExpr(Getter, Setter, + PType, VK, OK, + propertyNameLoc, + receiverNameLoc, IFace)); + } + return ExprError(Diag(propertyNameLoc, diag::err_property_not_found) + << &propertyName << Context.getObjCInterfaceType(IFace)); +} + +Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, + IdentifierInfo *Name, + SourceLocation NameLoc, + bool IsSuper, + bool HasTrailingDot, + ParsedType &ReceiverType) { + ReceiverType = ParsedType(); + + // If the identifier is "super" and there is no trailing dot, we're + // messaging super. If the identifier is "super" and there is a + // trailing dot, it's an instance message. + if (IsSuper && S->isInObjcMethodScope()) + return HasTrailingDot? ObjCInstanceMessage : ObjCSuperMessage; + + LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); + LookupName(Result, S); + + switch (Result.getResultKind()) { + case LookupResult::NotFound: + // Normal name lookup didn't find anything. If we're in an + // Objective-C method, look for ivars. If we find one, we're done! + // FIXME: This is a hack. Ivar lookup should be part of normal + // lookup. + if (ObjCMethodDecl *Method = getCurMethodDecl()) { + ObjCInterfaceDecl *ClassDeclared; + if (Method->getClassInterface()->lookupInstanceVariable(Name, + ClassDeclared)) + return ObjCInstanceMessage; + } + + // Break out; we'll perform typo correction below. + break; + + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + case LookupResult::Ambiguous: + Result.suppressDiagnostics(); + return ObjCInstanceMessage; + + case LookupResult::Found: { + // If the identifier is a class or not, and there is a trailing dot, + // it's an instance message. + if (HasTrailingDot) + return ObjCInstanceMessage; + // We found something. If it's a type, then we have a class + // message. Otherwise, it's an instance message. + NamedDecl *ND = Result.getFoundDecl(); + QualType T; + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) + T = Context.getObjCInterfaceType(Class); + else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + T = Context.getTypeDeclType(Type); + else + return ObjCInstanceMessage; + + // We have a class message, and T is the type we're + // messaging. Build source-location information for it. + TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); + ReceiverType = CreateParsedType(T, TSInfo); + return ObjCClassMessage; + } + } + + // Determine our typo-correction context. + CorrectTypoContext CTC = CTC_Expression; + if (ObjCMethodDecl *Method = getCurMethodDecl()) + if (Method->getClassInterface() && + Method->getClassInterface()->getSuperClass()) + CTC = CTC_ObjCMessageReceiver; + + if (DeclarationName Corrected = CorrectTypo(Result, S, 0, 0, false, CTC)) { + if (Result.isSingleResult()) { + // If we found a declaration, correct when it refers to an Objective-C + // class. + NamedDecl *ND = Result.getFoundDecl(); + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) { + Diag(NameLoc, diag::err_unknown_receiver_suggest) + << Name << Result.getLookupName() + << FixItHint::CreateReplacement(SourceRange(NameLoc), + ND->getNameAsString()); + Diag(ND->getLocation(), diag::note_previous_decl) + << Corrected; + + QualType T = Context.getObjCInterfaceType(Class); + TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); + ReceiverType = CreateParsedType(T, TSInfo); + return ObjCClassMessage; + } + } else if (Result.empty() && Corrected.getAsIdentifierInfo() && + Corrected.getAsIdentifierInfo()->isStr("super")) { + // If we've found the keyword "super", this is a send to super. + Diag(NameLoc, diag::err_unknown_receiver_suggest) + << Name << Corrected + << FixItHint::CreateReplacement(SourceRange(NameLoc), "super"); + return ObjCSuperMessage; + } + } + + // Fall back: let the parser try to parse it as an instance message. + return ObjCInstanceMessage; +} + +ExprResult Sema::ActOnSuperMessage(Scope *S, + SourceLocation SuperLoc, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + // Determine whether we are inside a method or not. + ObjCMethodDecl *Method = tryCaptureObjCSelf(); + if (!Method) { + Diag(SuperLoc, diag::err_invalid_receiver_to_message_super); + return ExprError(); + } + + ObjCInterfaceDecl *Class = Method->getClassInterface(); + if (!Class) { + Diag(SuperLoc, diag::error_no_super_class_message) + << Method->getDeclName(); + return ExprError(); + } + + ObjCInterfaceDecl *Super = Class->getSuperClass(); + if (!Super) { + // The current class does not have a superclass. + Diag(SuperLoc, diag::error_root_class_cannot_use_super) + << Class->getIdentifier(); + return ExprError(); + } + + // We are in a method whose class has a superclass, so 'super' + // is acting as a keyword. + if (Method->isInstanceMethod()) { + // Since we are in an instance method, this is an instance + // message to the superclass instance. + QualType SuperTy = Context.getObjCInterfaceType(Super); + SuperTy = Context.getObjCObjectPointerType(SuperTy); + return BuildInstanceMessage(0, SuperTy, SuperLoc, + Sel, /*Method=*/0, + LBracLoc, SelectorLoc, RBracLoc, move(Args)); + } + + // Since we are in a class method, this is a class message to + // the superclass. + return BuildClassMessage(/*ReceiverTypeInfo=*/0, + Context.getObjCInterfaceType(Super), + SuperLoc, Sel, /*Method=*/0, + LBracLoc, SelectorLoc, RBracLoc, move(Args)); +} + +/// \brief Build an Objective-C class message expression. +/// +/// This routine takes care of both normal class messages and +/// class messages to the superclass. +/// +/// \param ReceiverTypeInfo Type source information that describes the +/// receiver of this message. This may be NULL, in which case we are +/// sending to the superclass and \p SuperLoc must be a valid source +/// location. + +/// \param ReceiverType The type of the object receiving the +/// message. When \p ReceiverTypeInfo is non-NULL, this is the same +/// type as that refers to. For a superclass send, this is the type of +/// the superclass. +/// +/// \param SuperLoc The location of the "super" keyword in a +/// superclass message. +/// +/// \param Sel The selector to which the message is being sent. +/// +/// \param Method The method that this class message is invoking, if +/// already known. +/// +/// \param LBracLoc The location of the opening square bracket ']'. +/// +/// \param RBrac The location of the closing square bracket ']'. +/// +/// \param Args The message arguments. +ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg ArgsIn) { + SourceLocation Loc = SuperLoc.isValid()? SuperLoc + : ReceiverTypeInfo->getTypeLoc().getSourceRange().getBegin(); + if (LBracLoc.isInvalid()) { + Diag(Loc, diag::err_missing_open_square_message_send) + << FixItHint::CreateInsertion(Loc, "["); + LBracLoc = Loc; + } + + if (ReceiverType->isDependentType()) { + // If the receiver type is dependent, we can't type-check anything + // at this point. Build a dependent expression. + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + assert(SuperLoc.isInvalid() && "Message to super with dependent type"); + return Owned(ObjCMessageExpr::Create(Context, ReceiverType, + VK_RValue, LBracLoc, ReceiverTypeInfo, + Sel, SelectorLoc, /*Method=*/0, + Args, NumArgs, RBracLoc)); + } + + // Find the class to which we are sending this message. + ObjCInterfaceDecl *Class = 0; + const ObjCObjectType *ClassType = ReceiverType->getAs<ObjCObjectType>(); + if (!ClassType || !(Class = ClassType->getInterface())) { + Diag(Loc, diag::err_invalid_receiver_class_message) + << ReceiverType; + return ExprError(); + } + assert(Class && "We don't know which class we're messaging?"); + (void)DiagnoseUseOfDecl(Class, Loc); + // Find the method we are messaging. + if (!Method) { + if (Class->isForwardDecl()) { + // A forward class used in messaging is treated as a 'Class' + Diag(Loc, diag::warn_receiver_forward_class) << Class->getDeclName(); + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc)); + if (Method) + Diag(Method->getLocation(), diag::note_method_sent_forward_class) + << Method->getDeclName(); + } + if (!Method) + Method = Class->lookupClassMethod(Sel); + + // If we have an implementation in scope, check "private" methods. + if (!Method) + Method = LookupPrivateClassMethod(Sel, Class); + + if (Method && DiagnoseUseOfDecl(Method, Loc)) + return ExprError(); + } + + // Check the argument types and determine the result type. + QualType ReturnType; + ExprValueKind VK = VK_RValue; + + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, true, + SuperLoc.isValid(), LBracLoc, RBracLoc, + ReturnType, VK)) + return ExprError(); + + if (Method && !Method->getResultType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getResultType(), + diag::err_illegal_message_expr_incomplete_type)) + return ExprError(); + + // Construct the appropriate ObjCMessageExpr. + Expr *Result; + if (SuperLoc.isValid()) + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + SuperLoc, /*IsInstanceSuper=*/false, + ReceiverType, Sel, SelectorLoc, + Method, Args, NumArgs, RBracLoc); + else + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + ReceiverTypeInfo, Sel, SelectorLoc, + Method, Args, NumArgs, RBracLoc); + return MaybeBindToTemporary(Result); +} + +// ActOnClassMessage - used for both unary and keyword messages. +// ArgExprs is optional - if it is present, the number of expressions +// is obtained from Sel.getNumArgs(). +ExprResult Sema::ActOnClassMessage(Scope *S, + ParsedType Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + TypeSourceInfo *ReceiverTypeInfo; + QualType ReceiverType = GetTypeFromParser(Receiver, &ReceiverTypeInfo); + if (ReceiverType.isNull()) + return ExprError(); + + + if (!ReceiverTypeInfo) + ReceiverTypeInfo = Context.getTrivialTypeSourceInfo(ReceiverType, LBracLoc); + + return BuildClassMessage(ReceiverTypeInfo, ReceiverType, + /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, + LBracLoc, SelectorLoc, RBracLoc, move(Args)); +} + +/// \brief Build an Objective-C instance message expression. +/// +/// This routine takes care of both normal instance messages and +/// instance messages to the superclass instance. +/// +/// \param Receiver The expression that computes the object that will +/// receive this message. This may be empty, in which case we are +/// sending to the superclass instance and \p SuperLoc must be a valid +/// source location. +/// +/// \param ReceiverType The (static) type of the object receiving the +/// message. When a \p Receiver expression is provided, this is the +/// same type as that expression. For a superclass instance send, this +/// is a pointer to the type of the superclass. +/// +/// \param SuperLoc The location of the "super" keyword in a +/// superclass instance message. +/// +/// \param Sel The selector to which the message is being sent. +/// +/// \param Method The method that this instance message is invoking, if +/// already known. +/// +/// \param LBracLoc The location of the opening square bracket ']'. +/// +/// \param RBrac The location of the closing square bracket ']'. +/// +/// \param Args The message arguments. +ExprResult Sema::BuildInstanceMessage(Expr *Receiver, + QualType ReceiverType, + SourceLocation SuperLoc, + Selector Sel, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg ArgsIn) { + // The location of the receiver. + SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart(); + + if (LBracLoc.isInvalid()) { + Diag(Loc, diag::err_missing_open_square_message_send) + << FixItHint::CreateInsertion(Loc, "["); + LBracLoc = Loc; + } + + // If we have a receiver expression, perform appropriate promotions + // and determine receiver type. + if (Receiver) { + if (Receiver->isTypeDependent()) { + // If the receiver is type-dependent, we can't type-check anything + // at this point. Build a dependent expression. + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + assert(SuperLoc.isInvalid() && "Message to super with dependent type"); + return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy, + VK_RValue, LBracLoc, Receiver, Sel, + SelectorLoc, /*Method=*/0, + Args, NumArgs, RBracLoc)); + } + + // If necessary, apply function/array conversion to the receiver. + // C99 6.7.5.3p[7,8]. + ExprResult Result = DefaultFunctionArrayLvalueConversion(Receiver); + if (Result.isInvalid()) + return ExprError(); + Receiver = Result.take(); + ReceiverType = Receiver->getType(); + } + + if (!Method) { + // Handle messages to id. + bool receiverIsId = ReceiverType->isObjCIdType(); + if (receiverIsId || ReceiverType->isBlockPointerType() || + (Receiver && Context.isObjCNSObjectType(Receiver->getType()))) { + Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc), + receiverIsId); + if (!Method) + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc), + receiverIsId); + } else if (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()) { + // Handle messages to Class. + // We allow sending a message to a qualified Class ("Class<foo>"), which + // is ok as long as one of the protocols implements the selector (if not, warn). + if (const ObjCObjectPointerType *QClassTy + = ReceiverType->getAsObjCQualifiedClassType()) { + // Search protocols for class methods. + Method = LookupMethodInQualifiedType(Sel, QClassTy, false); + if (!Method) { + Method = LookupMethodInQualifiedType(Sel, QClassTy, true); + // warn if instance method found for a Class message. + if (Method) { + Diag(Loc, diag::warn_instance_method_on_class_found) + << Method->getSelector() << Sel; + Diag(Method->getLocation(), diag::note_method_declared_at); + } + } + } else { + if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { + if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { + // First check the public methods in the class interface. + Method = ClassDecl->lookupClassMethod(Sel); + + if (!Method) + Method = LookupPrivateClassMethod(Sel, ClassDecl); + } + if (Method && DiagnoseUseOfDecl(Method, Loc)) + return ExprError(); + } + if (!Method) { + // If not messaging 'self', look for any factory method named 'Sel'. + if (!Receiver || !isSelfExpr(Receiver)) { + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc), + true); + if (!Method) { + // If no class (factory) method was found, check if an _instance_ + // method of the same name exists in the root class only. + Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc), + true); + if (Method) + if (const ObjCInterfaceDecl *ID = + dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) { + if (ID->getSuperClass()) + Diag(Loc, diag::warn_root_inst_method_not_found) + << Sel << SourceRange(LBracLoc, RBracLoc); + } + } + } + } + } + } else { + ObjCInterfaceDecl* ClassDecl = 0; + + // We allow sending a message to a qualified ID ("id<foo>"), which is ok as + // long as one of the protocols implements the selector (if not, warn). + if (const ObjCObjectPointerType *QIdTy + = ReceiverType->getAsObjCQualifiedIdType()) { + // Search protocols for instance methods. + Method = LookupMethodInQualifiedType(Sel, QIdTy, true); + if (!Method) + Method = LookupMethodInQualifiedType(Sel, QIdTy, false); + } else if (const ObjCObjectPointerType *OCIType + = ReceiverType->getAsObjCInterfacePointerType()) { + // We allow sending a message to a pointer to an interface (an object). + ClassDecl = OCIType->getInterfaceDecl(); + // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be + // faster than the following method (which can do *many* linear searches). + // The idea is to add class info to MethodPool. + Method = ClassDecl->lookupInstanceMethod(Sel); + + if (!Method) + // Search protocol qualifiers. + Method = LookupMethodInQualifiedType(Sel, OCIType, true); + + const ObjCInterfaceDecl *forwardClass = 0; + if (!Method) { + // If we have implementations in scope, check "private" methods. + Method = LookupPrivateInstanceMethod(Sel, ClassDecl); + + if (!Method && (!Receiver || !isSelfExpr(Receiver))) { + // If we still haven't found a method, look in the global pool. This + // behavior isn't very desirable, however we need it for GCC + // compatibility. FIXME: should we deviate?? + if (OCIType->qual_empty()) { + Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LBracLoc, RBracLoc)); + if (OCIType->getInterfaceDecl()->isForwardDecl()) + forwardClass = OCIType->getInterfaceDecl(); + if (Method && !forwardClass) + Diag(Loc, diag::warn_maynot_respond) + << OCIType->getInterfaceDecl()->getIdentifier() << Sel; + } + } + } + if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass)) + return ExprError(); + } else if (!Context.getObjCIdType().isNull() && + (ReceiverType->isPointerType() || + ReceiverType->isIntegerType())) { + // Implicitly convert integers and pointers to 'id' but emit a warning. + Diag(Loc, diag::warn_bad_receiver_type) + << ReceiverType + << Receiver->getSourceRange(); + if (ReceiverType->isPointerType()) + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + CK_BitCast).take(); + else { + // TODO: specialized warning on null receivers? + bool IsNull = Receiver->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + IsNull ? CK_NullToPointer : CK_IntegralToPointer).take(); + } + ReceiverType = Receiver->getType(); + } + else { + ExprResult ReceiverRes; + if (getLangOptions().CPlusPlus) + ReceiverRes = PerformContextuallyConvertToObjCId(Receiver); + if (ReceiverRes.isUsable()) { + Receiver = ReceiverRes.take(); + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Receiver)) { + Receiver = ICE->getSubExpr(); + ReceiverType = Receiver->getType(); + } + return BuildInstanceMessage(Receiver, + ReceiverType, + SuperLoc, + Sel, + Method, + LBracLoc, + SelectorLoc, + RBracLoc, + move(ArgsIn)); + } else { + // Reject other random receiver types (e.g. structs). + Diag(Loc, diag::err_bad_receiver_type) + << ReceiverType << Receiver->getSourceRange(); + return ExprError(); + } + } + } + } + + // Check the message arguments. + unsigned NumArgs = ArgsIn.size(); + Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + QualType ReturnType; + ExprValueKind VK = VK_RValue; + bool ClassMessage = (ReceiverType->isObjCClassType() || + ReceiverType->isObjCQualifiedClassType()); + if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, + ClassMessage, SuperLoc.isValid(), + LBracLoc, RBracLoc, ReturnType, VK)) + return ExprError(); + + if (Method && !Method->getResultType()->isVoidType() && + RequireCompleteType(LBracLoc, Method->getResultType(), + diag::err_illegal_message_expr_incomplete_type)) + return ExprError(); + + // Construct the appropriate ObjCMessageExpr instance. + Expr *Result; + if (SuperLoc.isValid()) + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + SuperLoc, /*IsInstanceSuper=*/true, + ReceiverType, Sel, SelectorLoc, Method, + Args, NumArgs, RBracLoc); + else + Result = ObjCMessageExpr::Create(Context, ReturnType, VK, LBracLoc, + Receiver, Sel, SelectorLoc, Method, + Args, NumArgs, RBracLoc); + return MaybeBindToTemporary(Result); +} + +// ActOnInstanceMessage - used for both unary and keyword messages. +// ArgExprs is optional - if it is present, the number of expressions +// is obtained from Sel.getNumArgs(). +ExprResult Sema::ActOnInstanceMessage(Scope *S, + Expr *Receiver, + Selector Sel, + SourceLocation LBracLoc, + SourceLocation SelectorLoc, + SourceLocation RBracLoc, + MultiExprArg Args) { + if (!Receiver) + return ExprError(); + + return BuildInstanceMessage(Receiver, Receiver->getType(), + /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, + LBracLoc, SelectorLoc, RBracLoc, move(Args)); +} + diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp new file mode 100644 index 0000000..a33f5d0 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -0,0 +1,4721 @@ +//===--- SemaInit.cpp - Semantic Analysis for Initializers ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for initializers. The main entry +// point is Sema::CheckInitList(), but all of the work is performed +// within the InitListChecker class. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/Designator.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeLoc.h" +#include "llvm/Support/ErrorHandling.h" +#include <map> +using namespace clang; + +//===----------------------------------------------------------------------===// +// Sema Initialization Checking +//===----------------------------------------------------------------------===// + +static Expr *IsStringInit(Expr *Init, const ArrayType *AT, + ASTContext &Context) { + if (!isa<ConstantArrayType>(AT) && !isa<IncompleteArrayType>(AT)) + return 0; + + // See if this is a string literal or @encode. + Init = Init->IgnoreParens(); + + // Handle @encode, which is a narrow string. + if (isa<ObjCEncodeExpr>(Init) && AT->getElementType()->isCharType()) + return Init; + + // Otherwise we can only handle string literals. + StringLiteral *SL = dyn_cast<StringLiteral>(Init); + if (SL == 0) return 0; + + QualType ElemTy = Context.getCanonicalType(AT->getElementType()); + // char array can be initialized with a narrow string. + // Only allow char x[] = "foo"; not char x[] = L"foo"; + if (!SL->isWide()) + return ElemTy->isCharType() ? Init : 0; + + // wchar_t array can be initialized with a wide string: C99 6.7.8p15 (with + // correction from DR343): "An array with element type compatible with a + // qualified or unqualified version of wchar_t may be initialized by a wide + // string literal, optionally enclosed in braces." + if (Context.typesAreCompatible(Context.getWCharType(), + ElemTy.getUnqualifiedType())) + return Init; + + return 0; +} + +static Expr *IsStringInit(Expr *init, QualType declType, ASTContext &Context) { + const ArrayType *arrayType = Context.getAsArrayType(declType); + if (!arrayType) return 0; + + return IsStringInit(init, arrayType, Context); +} + +static void CheckStringInit(Expr *Str, QualType &DeclT, const ArrayType *AT, + Sema &S) { + // Get the length of the string as parsed. + uint64_t StrLength = + cast<ConstantArrayType>(Str->getType())->getSize().getZExtValue(); + + + if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) { + // C99 6.7.8p14. We have an array of character type with unknown size + // being initialized to a string literal. + llvm::APSInt ConstVal(32); + ConstVal = StrLength; + // Return a new array type (C99 6.7.8p22). + DeclT = S.Context.getConstantArrayType(IAT->getElementType(), + ConstVal, + ArrayType::Normal, 0); + return; + } + + const ConstantArrayType *CAT = cast<ConstantArrayType>(AT); + + // We have an array of character type with known size. However, + // the size may be smaller or larger than the string we are initializing. + // FIXME: Avoid truncation for 64-bit length strings. + if (S.getLangOptions().CPlusPlus) { + if (StringLiteral *SL = dyn_cast<StringLiteral>(Str)) { + // For Pascal strings it's OK to strip off the terminating null character, + // so the example below is valid: + // + // unsigned char a[2] = "\pa"; + if (SL->isPascal()) + StrLength--; + } + + // [dcl.init.string]p2 + if (StrLength > CAT->getSize().getZExtValue()) + S.Diag(Str->getSourceRange().getBegin(), + diag::err_initializer_string_for_char_array_too_long) + << Str->getSourceRange(); + } else { + // C99 6.7.8p14. + if (StrLength-1 > CAT->getSize().getZExtValue()) + S.Diag(Str->getSourceRange().getBegin(), + diag::warn_initializer_string_for_char_array_too_long) + << Str->getSourceRange(); + } + + // Set the type to the actual size that we are initializing. If we have + // something like: + // char x[1] = "foo"; + // then this will set the string literal's type to char[1]. + Str->setType(DeclT); +} + +//===----------------------------------------------------------------------===// +// Semantic checking for initializer lists. +//===----------------------------------------------------------------------===// + +/// @brief Semantic checking for initializer lists. +/// +/// The InitListChecker class contains a set of routines that each +/// handle the initialization of a certain kind of entity, e.g., +/// arrays, vectors, struct/union types, scalars, etc. The +/// InitListChecker itself performs a recursive walk of the subobject +/// structure of the type to be initialized, while stepping through +/// the initializer list one element at a time. The IList and Index +/// parameters to each of the Check* routines contain the active +/// (syntactic) initializer list and the index into that initializer +/// list that represents the current initializer. Each routine is +/// responsible for moving that Index forward as it consumes elements. +/// +/// Each Check* routine also has a StructuredList/StructuredIndex +/// arguments, which contains the current "structured" (semantic) +/// initializer list and the index into that initializer list where we +/// are copying initializers as we map them over to the semantic +/// list. Once we have completed our recursive walk of the subobject +/// structure, we will have constructed a full semantic initializer +/// list. +/// +/// C99 designators cause changes in the initializer list traversal, +/// because they make the initialization "jump" into a specific +/// subobject and then continue the initialization from that +/// point. CheckDesignatedInitializer() recursively steps into the +/// designated subobject and manages backing out the recursion to +/// initialize the subobjects after the one designated. +namespace { +class InitListChecker { + Sema &SemaRef; + bool hadError; + std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic; + InitListExpr *FullyStructuredList; + + void CheckImplicitInitList(const InitializedEntity &Entity, + InitListExpr *ParentIList, QualType T, + unsigned &Index, InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject = false); + void CheckExplicitInitList(const InitializedEntity &Entity, + InitListExpr *IList, QualType &T, + unsigned &Index, InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject = false); + void CheckListElementTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject = false); + void CheckSubElementType(const InitializedEntity &Entity, + InitListExpr *IList, QualType ElemType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckScalarType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckReferenceType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckVectorType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + void CheckStructUnionTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + RecordDecl::field_iterator Field, + bool SubobjectIsDesignatorContext, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject = false); + void CheckArrayType(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, + llvm::APSInt elementIndex, + bool SubobjectIsDesignatorContext, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex); + bool CheckDesignatedInitializer(const InitializedEntity &Entity, + InitListExpr *IList, DesignatedInitExpr *DIE, + unsigned DesigIdx, + QualType &CurrentObjectType, + RecordDecl::field_iterator *NextField, + llvm::APSInt *NextElementIndex, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool FinishSubobjectInit, + bool TopLevelObject); + InitListExpr *getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, + QualType CurrentObjectType, + InitListExpr *StructuredList, + unsigned StructuredIndex, + SourceRange InitRange); + void UpdateStructuredListElement(InitListExpr *StructuredList, + unsigned &StructuredIndex, + Expr *expr); + int numArrayElements(QualType DeclType); + int numStructUnionElements(QualType DeclType); + + void FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, bool &RequiresSecondPass); + void FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, bool &RequiresSecondPass); +public: + InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T); + bool HadError() { return hadError; } + + // @brief Retrieves the fully-structured initializer list used for + // semantic analysis and code generation. + InitListExpr *getFullyStructuredList() const { return FullyStructuredList; } +}; +} // end anonymous namespace + +void InitListChecker::FillInValueInitForField(unsigned Init, FieldDecl *Field, + const InitializedEntity &ParentEntity, + InitListExpr *ILE, + bool &RequiresSecondPass) { + SourceLocation Loc = ILE->getSourceRange().getBegin(); + unsigned NumInits = ILE->getNumInits(); + InitializedEntity MemberEntity + = InitializedEntity::InitializeMember(Field, &ParentEntity); + if (Init >= NumInits || !ILE->getInit(Init)) { + // FIXME: We probably don't need to handle references + // specially here, since value-initialization of references is + // handled in InitializationSequence. + if (Field->getType()->isReferenceType()) { + // C++ [dcl.init.aggr]p9: + // If an incomplete or empty initializer-list leaves a + // member of reference type uninitialized, the program is + // ill-formed. + SemaRef.Diag(Loc, diag::err_init_reference_member_uninitialized) + << Field->getType() + << ILE->getSyntacticForm()->getSourceRange(); + SemaRef.Diag(Field->getLocation(), + diag::note_uninit_reference_member); + hadError = true; + return; + } + + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, MemberEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, MemberEntity, Kind, 0, 0); + hadError = true; + return; + } + + ExprResult MemberInit + = InitSeq.Perform(SemaRef, MemberEntity, Kind, MultiExprArg()); + if (MemberInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + ILE->setInit(Init, MemberInit.takeAs<Expr>()); + } else if (InitSeq.isConstructorInitialization()) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(SemaRef.Context, Init, MemberInit.takeAs<Expr>()); + RequiresSecondPass = true; + } + } else if (InitListExpr *InnerILE + = dyn_cast<InitListExpr>(ILE->getInit(Init))) + FillInValueInitializations(MemberEntity, InnerILE, + RequiresSecondPass); +} + +/// Recursively replaces NULL values within the given initializer list +/// with expressions that perform value-initialization of the +/// appropriate type. +void +InitListChecker::FillInValueInitializations(const InitializedEntity &Entity, + InitListExpr *ILE, + bool &RequiresSecondPass) { + assert((ILE->getType() != SemaRef.Context.VoidTy) && + "Should not have void type"); + SourceLocation Loc = ILE->getSourceRange().getBegin(); + if (ILE->getSyntacticForm()) + Loc = ILE->getSyntacticForm()->getSourceRange().getBegin(); + + if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { + if (RType->getDecl()->isUnion() && + ILE->getInitializedFieldInUnion()) + FillInValueInitForField(0, ILE->getInitializedFieldInUnion(), + Entity, ILE, RequiresSecondPass); + else { + unsigned Init = 0; + for (RecordDecl::field_iterator + Field = RType->getDecl()->field_begin(), + FieldEnd = RType->getDecl()->field_end(); + Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (hadError) + return; + + FillInValueInitForField(Init, *Field, Entity, ILE, RequiresSecondPass); + if (hadError) + return; + + ++Init; + + // Only look at the first initialization of a union. + if (RType->getDecl()->isUnion()) + break; + } + } + + return; + } + + QualType ElementType; + + InitializedEntity ElementEntity = Entity; + unsigned NumInits = ILE->getNumInits(); + unsigned NumElements = NumInits; + if (const ArrayType *AType = SemaRef.Context.getAsArrayType(ILE->getType())) { + ElementType = AType->getElementType(); + if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) + NumElements = CAType->getSize().getZExtValue(); + ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, + 0, Entity); + } else if (const VectorType *VType = ILE->getType()->getAs<VectorType>()) { + ElementType = VType->getElementType(); + NumElements = VType->getNumElements(); + ElementEntity = InitializedEntity::InitializeElement(SemaRef.Context, + 0, Entity); + } else + ElementType = ILE->getType(); + + + for (unsigned Init = 0; Init != NumElements; ++Init) { + if (hadError) + return; + + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement || + ElementEntity.getKind() == InitializedEntity::EK_VectorElement) + ElementEntity.setElementIndex(Init); + + if (Init >= NumInits || !ILE->getInit(Init)) { + InitializationKind Kind = InitializationKind::CreateValue(Loc, Loc, Loc, + true); + InitializationSequence InitSeq(SemaRef, ElementEntity, Kind, 0, 0); + if (!InitSeq) { + InitSeq.Diagnose(SemaRef, ElementEntity, Kind, 0, 0); + hadError = true; + return; + } + + ExprResult ElementInit + = InitSeq.Perform(SemaRef, ElementEntity, Kind, MultiExprArg()); + if (ElementInit.isInvalid()) { + hadError = true; + return; + } + + if (hadError) { + // Do nothing + } else if (Init < NumInits) { + // For arrays, just set the expression used for value-initialization + // of the "holes" in the array. + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) + ILE->setArrayFiller(ElementInit.takeAs<Expr>()); + else + ILE->setInit(Init, ElementInit.takeAs<Expr>()); + } else { + // For arrays, just set the expression used for value-initialization + // of the rest of elements and exit. + if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement) { + ILE->setArrayFiller(ElementInit.takeAs<Expr>()); + return; + } + + if (InitSeq.isConstructorInitialization()) { + // Value-initialization requires a constructor call, so + // extend the initializer list to include the constructor + // call and make a note that we'll need to take another pass + // through the initializer list. + ILE->updateInit(SemaRef.Context, Init, ElementInit.takeAs<Expr>()); + RequiresSecondPass = true; + } + } + } else if (InitListExpr *InnerILE + = dyn_cast<InitListExpr>(ILE->getInit(Init))) + FillInValueInitializations(ElementEntity, InnerILE, RequiresSecondPass); + } +} + + +InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, + InitListExpr *IL, QualType &T) + : SemaRef(S) { + hadError = false; + + unsigned newIndex = 0; + unsigned newStructuredIndex = 0; + FullyStructuredList + = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange()); + CheckExplicitInitList(Entity, IL, T, newIndex, + FullyStructuredList, newStructuredIndex, + /*TopLevelObject=*/true); + + if (!hadError) { + bool RequiresSecondPass = false; + FillInValueInitializations(Entity, FullyStructuredList, RequiresSecondPass); + if (RequiresSecondPass && !hadError) + FillInValueInitializations(Entity, FullyStructuredList, + RequiresSecondPass); + } +} + +int InitListChecker::numArrayElements(QualType DeclType) { + // FIXME: use a proper constant + int maxElements = 0x7FFFFFFF; + if (const ConstantArrayType *CAT = + SemaRef.Context.getAsConstantArrayType(DeclType)) { + maxElements = static_cast<int>(CAT->getSize().getZExtValue()); + } + return maxElements; +} + +int InitListChecker::numStructUnionElements(QualType DeclType) { + RecordDecl *structDecl = DeclType->getAs<RecordType>()->getDecl(); + int InitializableMembers = 0; + for (RecordDecl::field_iterator + Field = structDecl->field_begin(), + FieldEnd = structDecl->field_end(); + Field != FieldEnd; ++Field) { + if ((*Field)->getIdentifier() || !(*Field)->isBitField()) + ++InitializableMembers; + } + if (structDecl->isUnion()) + return std::min(InitializableMembers, 1); + return InitializableMembers - structDecl->hasFlexibleArrayMember(); +} + +void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, + InitListExpr *ParentIList, + QualType T, unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject) { + int maxElements = 0; + + if (T->isArrayType()) + maxElements = numArrayElements(T); + else if (T->isRecordType()) + maxElements = numStructUnionElements(T); + else if (T->isVectorType()) + maxElements = T->getAs<VectorType>()->getNumElements(); + else + assert(0 && "CheckImplicitInitList(): Illegal type"); + + if (maxElements == 0) { + SemaRef.Diag(ParentIList->getInit(Index)->getLocStart(), + diag::err_implicit_empty_initializer); + ++Index; + hadError = true; + return; + } + + // Build a structured initializer list corresponding to this subobject. + InitListExpr *StructuredSubobjectInitList + = getStructuredSubobjectInit(ParentIList, Index, T, StructuredList, + StructuredIndex, + SourceRange(ParentIList->getInit(Index)->getSourceRange().getBegin(), + ParentIList->getSourceRange().getEnd())); + unsigned StructuredSubobjectInitIndex = 0; + + // Check the element types and build the structural subobject. + unsigned StartIndex = Index; + CheckListElementTypes(Entity, ParentIList, T, + /*SubobjectIsDesignatorContext=*/false, Index, + StructuredSubobjectInitList, + StructuredSubobjectInitIndex, + TopLevelObject); + unsigned EndIndex = (Index == StartIndex? StartIndex : Index - 1); + StructuredSubobjectInitList->setType(T); + + // Update the structured sub-object initializer so that it's ending + // range corresponds with the end of the last initializer it used. + if (EndIndex < ParentIList->getNumInits()) { + SourceLocation EndLoc + = ParentIList->getInit(EndIndex)->getSourceRange().getEnd(); + StructuredSubobjectInitList->setRBraceLoc(EndLoc); + } + + // Warn about missing braces. + if (T->isArrayType() || T->isRecordType()) { + SemaRef.Diag(StructuredSubobjectInitList->getLocStart(), + diag::warn_missing_braces) + << StructuredSubobjectInitList->getSourceRange() + << FixItHint::CreateInsertion(StructuredSubobjectInitList->getLocStart(), + "{") + << FixItHint::CreateInsertion(SemaRef.PP.getLocForEndOfToken( + StructuredSubobjectInitList->getLocEnd()), + "}"); + } +} + +void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, + InitListExpr *IList, QualType &T, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject) { + assert(IList->isExplicit() && "Illegal Implicit InitListExpr"); + SyntacticToSemantic[IList] = StructuredList; + StructuredList->setSyntacticForm(IList); + CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, + Index, StructuredList, StructuredIndex, TopLevelObject); + QualType ExprTy = T.getNonLValueExprType(SemaRef.Context); + IList->setType(ExprTy); + StructuredList->setType(ExprTy); + if (hadError) + return; + + if (Index < IList->getNumInits()) { + // We have leftover initializers + if (StructuredIndex == 1 && + IsStringInit(StructuredList->getInit(0), T, SemaRef.Context)) { + unsigned DK = diag::warn_excess_initializers_in_char_array_initializer; + if (SemaRef.getLangOptions().CPlusPlus) { + DK = diag::err_excess_initializers_in_char_array_initializer; + hadError = true; + } + // Special-case + SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) + << IList->getInit(Index)->getSourceRange(); + } else if (!T->isIncompleteType()) { + // Don't complain for incomplete types, since we'll get an error + // elsewhere + QualType CurrentObjectType = StructuredList->getType(); + int initKind = + CurrentObjectType->isArrayType()? 0 : + CurrentObjectType->isVectorType()? 1 : + CurrentObjectType->isScalarType()? 2 : + CurrentObjectType->isUnionType()? 3 : + 4; + + unsigned DK = diag::warn_excess_initializers; + if (SemaRef.getLangOptions().CPlusPlus) { + DK = diag::err_excess_initializers; + hadError = true; + } + if (SemaRef.getLangOptions().OpenCL && initKind == 1) { + DK = diag::err_excess_initializers; + hadError = true; + } + + SemaRef.Diag(IList->getInit(Index)->getLocStart(), DK) + << initKind << IList->getInit(Index)->getSourceRange(); + } + } + + if (T->isScalarType() && !TopLevelObject) + SemaRef.Diag(IList->getLocStart(), diag::warn_braces_around_scalar_init) + << IList->getSourceRange() + << FixItHint::CreateRemoval(IList->getLocStart()) + << FixItHint::CreateRemoval(IList->getLocEnd()); +} + +void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, + InitListExpr *IList, + QualType &DeclType, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject) { + if (DeclType->isScalarType()) { + CheckScalarType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isVectorType()) { + CheckVectorType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isAggregateType()) { + if (DeclType->isRecordType()) { + RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); + CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(), + SubobjectIsDesignatorContext, Index, + StructuredList, StructuredIndex, + TopLevelObject); + } else if (DeclType->isArrayType()) { + llvm::APSInt Zero( + SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()), + false); + CheckArrayType(Entity, IList, DeclType, Zero, + SubobjectIsDesignatorContext, Index, + StructuredList, StructuredIndex); + } else + assert(0 && "Aggregate that isn't a structure or array?!"); + } else if (DeclType->isVoidType() || DeclType->isFunctionType()) { + // This type is invalid, issue a diagnostic. + ++Index; + SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) + << DeclType; + hadError = true; + } else if (DeclType->isRecordType()) { + // C++ [dcl.init]p14: + // [...] If the class is an aggregate (8.5.1), and the initializer + // is a brace-enclosed list, see 8.5.1. + // + // Note: 8.5.1 is handled below; here, we diagnose the case where + // we have an initializer list and a destination type that is not + // an aggregate. + // FIXME: In C++0x, this is yet another form of initialization. + SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) + << DeclType << IList->getSourceRange(); + hadError = true; + } else if (DeclType->isReferenceType()) { + CheckReferenceType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); + } else if (DeclType->isObjCObjectType()) { + SemaRef.Diag(IList->getLocStart(), diag::err_init_objc_class) + << DeclType; + hadError = true; + } else { + SemaRef.Diag(IList->getLocStart(), diag::err_illegal_initializer_type) + << DeclType; + hadError = true; + } +} + +void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, + InitListExpr *IList, + QualType ElemType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + Expr *expr = IList->getInit(Index); + if (InitListExpr *SubInitList = dyn_cast<InitListExpr>(expr)) { + unsigned newIndex = 0; + unsigned newStructuredIndex = 0; + InitListExpr *newStructuredList + = getStructuredSubobjectInit(IList, Index, ElemType, + StructuredList, StructuredIndex, + SubInitList->getSourceRange()); + CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex, + newStructuredList, newStructuredIndex); + ++StructuredIndex; + ++Index; + return; + } else if (ElemType->isScalarType()) { + return CheckScalarType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); + } else if (ElemType->isReferenceType()) { + return CheckReferenceType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); + } + + if (const ArrayType *arrayType = SemaRef.Context.getAsArrayType(ElemType)) { + // arrayType can be incomplete if we're initializing a flexible + // array member. There's nothing we can do with the completed + // type here, though. + + if (Expr *Str = IsStringInit(expr, arrayType, SemaRef.Context)) { + CheckStringInit(Str, ElemType, arrayType, SemaRef); + UpdateStructuredListElement(StructuredList, StructuredIndex, Str); + ++Index; + return; + } + + // Fall through for subaggregate initialization. + + } else if (SemaRef.getLangOptions().CPlusPlus) { + // C++ [dcl.init.aggr]p12: + // All implicit type conversions (clause 4) are considered when + // initializing the aggregate member with an ini- tializer from + // an initializer-list. If the initializer can initialize a + // member, the member is initialized. [...] + + // FIXME: Better EqualLoc? + InitializationKind Kind = + InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); + InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1); + + if (Seq) { + ExprResult Result = + Seq.Perform(SemaRef, Entity, Kind, MultiExprArg(&expr, 1)); + if (Result.isInvalid()) + hadError = true; + + UpdateStructuredListElement(StructuredList, StructuredIndex, + Result.takeAs<Expr>()); + ++Index; + return; + } + + // Fall through for subaggregate initialization + } else { + // C99 6.7.8p13: + // + // The initializer for a structure or union object that has + // automatic storage duration shall be either an initializer + // list as described below, or a single expression that has + // compatible structure or union type. In the latter case, the + // initial value of the object, including unnamed members, is + // that of the expression. + ExprResult ExprRes = SemaRef.Owned(expr); + if ((ElemType->isRecordType() || ElemType->isVectorType()) && + SemaRef.CheckSingleAssignmentConstraints(ElemType, ExprRes) + == Sema::Compatible) { + if (ExprRes.isInvalid()) + hadError = true; + else { + ExprRes = SemaRef.DefaultFunctionArrayLvalueConversion(ExprRes.take()); + if (ExprRes.isInvalid()) + hadError = true; + } + UpdateStructuredListElement(StructuredList, StructuredIndex, + ExprRes.takeAs<Expr>()); + ++Index; + return; + } + ExprRes.release(); + // Fall through for subaggregate initialization + } + + // C++ [dcl.init.aggr]p12: + // + // [...] Otherwise, if the member is itself a non-empty + // subaggregate, brace elision is assumed and the initializer is + // considered for the initialization of the first member of + // the subaggregate. + if (ElemType->isAggregateType() || ElemType->isVectorType()) { + CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, + StructuredIndex); + ++StructuredIndex; + } else { + // We cannot initialize this element, so let + // PerformCopyInitialization produce the appropriate diagnostic. + SemaRef.PerformCopyInitialization(Entity, SourceLocation(), + SemaRef.Owned(expr)); + hadError = true; + ++Index; + ++StructuredIndex; + } +} + +void InitListChecker::CheckScalarType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + if (Index >= IList->getNumInits()) { + SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer) + << IList->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + Expr *expr = IList->getInit(Index); + if (InitListExpr *SubIList = dyn_cast<InitListExpr>(expr)) { + SemaRef.Diag(SubIList->getLocStart(), + diag::warn_many_braces_around_scalar_init) + << SubIList->getSourceRange(); + + CheckScalarType(Entity, SubIList, DeclType, Index, StructuredList, + StructuredIndex); + return; + } else if (isa<DesignatedInitExpr>(expr)) { + SemaRef.Diag(expr->getSourceRange().getBegin(), + diag::err_designator_for_scalar_init) + << DeclType << expr->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + ExprResult Result = + SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), + SemaRef.Owned(expr)); + + Expr *ResultExpr = 0; + + if (Result.isInvalid()) + hadError = true; // types weren't compatible. + else { + ResultExpr = Result.takeAs<Expr>(); + + if (ResultExpr != expr) { + // The type was promoted, update initializer list. + IList->setInit(Index, ResultExpr); + } + } + if (hadError) + ++StructuredIndex; + else + UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); + ++Index; +} + +void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + if (Index < IList->getNumInits()) { + Expr *expr = IList->getInit(Index); + if (isa<InitListExpr>(expr)) { + SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) + << DeclType << IList->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + ExprResult Result = + SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), + SemaRef.Owned(expr)); + + if (Result.isInvalid()) + hadError = true; + + expr = Result.takeAs<Expr>(); + IList->setInit(Index, expr); + + if (hadError) + ++StructuredIndex; + else + UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + ++Index; + } else { + // FIXME: It would be wonderful if we could point at the actual member. In + // general, it would be useful to pass location information down the stack, + // so that we know the location (or decl) of the "current object" being + // initialized. + SemaRef.Diag(IList->getLocStart(), + diag::err_init_reference_member_uninitialized) + << DeclType + << IList->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } +} + +void InitListChecker::CheckVectorType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + if (Index >= IList->getNumInits()) + return; + + const VectorType *VT = DeclType->getAs<VectorType>(); + unsigned maxElements = VT->getNumElements(); + unsigned numEltsInit = 0; + QualType elementType = VT->getElementType(); + + if (!SemaRef.getLangOptions().OpenCL) { + // If the initializing element is a vector, try to copy-initialize + // instead of breaking it apart (which is doomed to failure anyway). + Expr *Init = IList->getInit(Index); + if (!isa<InitListExpr>(Init) && Init->getType()->isVectorType()) { + ExprResult Result = + SemaRef.PerformCopyInitialization(Entity, Init->getLocStart(), + SemaRef.Owned(Init)); + + Expr *ResultExpr = 0; + if (Result.isInvalid()) + hadError = true; // types weren't compatible. + else { + ResultExpr = Result.takeAs<Expr>(); + + if (ResultExpr != Init) { + // The type was promoted, update initializer list. + IList->setInit(Index, ResultExpr); + } + } + if (hadError) + ++StructuredIndex; + else + UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); + ++Index; + return; + } + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) { + // Don't attempt to go past the end of the init list + if (Index >= IList->getNumInits()) + break; + + ElementEntity.setElementIndex(Index); + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + } + return; + } + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + // OpenCL initializers allows vectors to be constructed from vectors. + for (unsigned i = 0; i < maxElements; ++i) { + // Don't attempt to go past the end of the init list + if (Index >= IList->getNumInits()) + break; + + ElementEntity.setElementIndex(Index); + + QualType IType = IList->getInit(Index)->getType(); + if (!IType->isVectorType()) { + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + ++numEltsInit; + } else { + QualType VecType; + const VectorType *IVT = IType->getAs<VectorType>(); + unsigned numIElts = IVT->getNumElements(); + + if (IType->isExtVectorType()) + VecType = SemaRef.Context.getExtVectorType(elementType, numIElts); + else + VecType = SemaRef.Context.getVectorType(elementType, numIElts, + IVT->getVectorKind()); + CheckSubElementType(ElementEntity, IList, VecType, Index, + StructuredList, StructuredIndex); + numEltsInit += numIElts; + } + } + + // OpenCL requires all elements to be initialized. + if (numEltsInit != maxElements) + if (SemaRef.getLangOptions().OpenCL) + SemaRef.Diag(IList->getSourceRange().getBegin(), + diag::err_vector_incorrect_num_initializers) + << (numEltsInit < maxElements) << maxElements << numEltsInit; +} + +void InitListChecker::CheckArrayType(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, + llvm::APSInt elementIndex, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex) { + const ArrayType *arrayType = SemaRef.Context.getAsArrayType(DeclType); + + // Check for the special-case of initializing an array with a string. + if (Index < IList->getNumInits()) { + if (Expr *Str = IsStringInit(IList->getInit(Index), arrayType, + SemaRef.Context)) { + CheckStringInit(Str, DeclType, arrayType, SemaRef); + // We place the string literal directly into the resulting + // initializer list. This is the only place where the structure + // of the structured initializer list doesn't match exactly, + // because doing so would involve allocating one character + // constant for each string. + UpdateStructuredListElement(StructuredList, StructuredIndex, Str); + StructuredList->resizeInits(SemaRef.Context, StructuredIndex); + ++Index; + return; + } + } + if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(arrayType)) { + // Check for VLAs; in standard C it would be possible to check this + // earlier, but I don't know where clang accepts VLAs (gcc accepts + // them in all sorts of strange places). + SemaRef.Diag(VAT->getSizeExpr()->getLocStart(), + diag::err_variable_object_no_init) + << VAT->getSizeExpr()->getSourceRange(); + hadError = true; + ++Index; + ++StructuredIndex; + return; + } + + // We might know the maximum number of elements in advance. + llvm::APSInt maxElements(elementIndex.getBitWidth(), + elementIndex.isUnsigned()); + bool maxElementsKnown = false; + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(arrayType)) { + maxElements = CAT->getSize(); + elementIndex = elementIndex.extOrTrunc(maxElements.getBitWidth()); + elementIndex.setIsUnsigned(maxElements.isUnsigned()); + maxElementsKnown = true; + } + + QualType elementType = arrayType->getElementType(); + while (Index < IList->getNumInits()) { + Expr *Init = IList->getInit(Index); + if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) { + // If we're not the subobject that matches up with the '{' for + // the designator, we shouldn't be handling the + // designator. Return immediately. + if (!SubobjectIsDesignatorContext) + return; + + // Handle this designated initializer. elementIndex will be + // updated to be the next array element we'll initialize. + if (CheckDesignatedInitializer(Entity, IList, DIE, 0, + DeclType, 0, &elementIndex, Index, + StructuredList, StructuredIndex, true, + false)) { + hadError = true; + continue; + } + + if (elementIndex.getBitWidth() > maxElements.getBitWidth()) + maxElements = maxElements.extend(elementIndex.getBitWidth()); + else if (elementIndex.getBitWidth() < maxElements.getBitWidth()) + elementIndex = elementIndex.extend(maxElements.getBitWidth()); + elementIndex.setIsUnsigned(maxElements.isUnsigned()); + + // If the array is of incomplete type, keep track of the number of + // elements in the initializer. + if (!maxElementsKnown && elementIndex > maxElements) + maxElements = elementIndex; + + continue; + } + + // If we know the maximum number of elements, and we've already + // hit it, stop consuming elements in the initializer list. + if (maxElementsKnown && elementIndex == maxElements) + break; + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex, + Entity); + // Check this element. + CheckSubElementType(ElementEntity, IList, elementType, Index, + StructuredList, StructuredIndex); + ++elementIndex; + + // If the array is of incomplete type, keep track of the number of + // elements in the initializer. + if (!maxElementsKnown && elementIndex > maxElements) + maxElements = elementIndex; + } + if (!hadError && DeclType->isIncompleteArrayType()) { + // If this is an incomplete array type, the actual type needs to + // be calculated here. + llvm::APSInt Zero(maxElements.getBitWidth(), maxElements.isUnsigned()); + if (maxElements == Zero) { + // Sizing an array implicitly to zero is not allowed by ISO C, + // but is supported by GNU. + SemaRef.Diag(IList->getLocStart(), + diag::ext_typecheck_zero_array_size); + } + + DeclType = SemaRef.Context.getConstantArrayType(elementType, maxElements, + ArrayType::Normal, 0); + } +} + +void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, + InitListExpr *IList, + QualType DeclType, + RecordDecl::field_iterator Field, + bool SubobjectIsDesignatorContext, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool TopLevelObject) { + RecordDecl* structDecl = DeclType->getAs<RecordType>()->getDecl(); + + // If the record is invalid, some of it's members are invalid. To avoid + // confusion, we forgo checking the intializer for the entire record. + if (structDecl->isInvalidDecl()) { + hadError = true; + return; + } + + if (DeclType->isUnionType() && IList->getNumInits() == 0) { + // Value-initialize the first named member of the union. + RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); + for (RecordDecl::field_iterator FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Field->getDeclName()) { + StructuredList->setInitializedFieldInUnion(*Field); + break; + } + } + return; + } + + // If structDecl is a forward declaration, this loop won't do + // anything except look at designated initializers; That's okay, + // because an error should get printed out elsewhere. It might be + // worthwhile to skip over the rest of the initializer, though. + RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); + RecordDecl::field_iterator FieldEnd = RD->field_end(); + bool InitializedSomething = false; + bool CheckForMissingFields = true; + while (Index < IList->getNumInits()) { + Expr *Init = IList->getInit(Index); + + if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Init)) { + // If we're not the subobject that matches up with the '{' for + // the designator, we shouldn't be handling the + // designator. Return immediately. + if (!SubobjectIsDesignatorContext) + return; + + // Handle this designated initializer. Field will be updated to + // the next field that we'll be initializing. + if (CheckDesignatedInitializer(Entity, IList, DIE, 0, + DeclType, &Field, 0, Index, + StructuredList, StructuredIndex, + true, TopLevelObject)) + hadError = true; + + InitializedSomething = true; + + // Disable check for missing fields when designators are used. + // This matches gcc behaviour. + CheckForMissingFields = false; + continue; + } + + if (Field == FieldEnd) { + // We've run out of fields. We're done. + break; + } + + // We've already initialized a member of a union. We're done. + if (InitializedSomething && DeclType->isUnionType()) + break; + + // If we've hit the flexible array member at the end, we're done. + if (Field->getType()->isIncompleteArrayType()) + break; + + if (Field->isUnnamedBitfield()) { + // Don't initialize unnamed bitfields, e.g. "int : 20;" + ++Field; + continue; + } + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); + InitializedSomething = true; + + if (DeclType->isUnionType()) { + // Initialize the first field within the union. + StructuredList->setInitializedFieldInUnion(*Field); + } + + ++Field; + } + + // Emit warnings for missing struct field initializers. + if (InitializedSomething && CheckForMissingFields && Field != FieldEnd && + !Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) { + // It is possible we have one or more unnamed bitfields remaining. + // Find first (if any) named field and emit warning. + for (RecordDecl::field_iterator it = Field, end = RD->field_end(); + it != end; ++it) { + if (!it->isUnnamedBitfield()) { + SemaRef.Diag(IList->getSourceRange().getEnd(), + diag::warn_missing_field_initializers) << it->getName(); + break; + } + } + } + + if (Field == FieldEnd || !Field->getType()->isIncompleteArrayType() || + Index >= IList->getNumInits()) + return; + + // Handle GNU flexible array initializers. + if (!TopLevelObject && + (!isa<InitListExpr>(IList->getInit(Index)) || + cast<InitListExpr>(IList->getInit(Index))->getNumInits() > 0)) { + SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(), + diag::err_flexible_array_init_nonempty) + << IList->getInit(Index)->getSourceRange().getBegin(); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << *Field; + hadError = true; + ++Index; + return; + } else { + SemaRef.Diag(IList->getInit(Index)->getSourceRange().getBegin(), + diag::ext_flexible_array_init) + << IList->getInit(Index)->getSourceRange().getBegin(); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << *Field; + } + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + + if (isa<InitListExpr>(IList->getInit(Index))) + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); + else + CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); +} + +/// \brief Expand a field designator that refers to a member of an +/// anonymous struct or union into a series of field designators that +/// refers to the field within the appropriate subobject. +/// +static void ExpandAnonymousFieldDesignator(Sema &SemaRef, + DesignatedInitExpr *DIE, + unsigned DesigIdx, + IndirectFieldDecl *IndirectField) { + typedef DesignatedInitExpr::Designator Designator; + + // Build the replacement designators. + llvm::SmallVector<Designator, 4> Replacements; + for (IndirectFieldDecl::chain_iterator PI = IndirectField->chain_begin(), + PE = IndirectField->chain_end(); PI != PE; ++PI) { + if (PI + 1 == PE) + Replacements.push_back(Designator((IdentifierInfo *)0, + DIE->getDesignator(DesigIdx)->getDotLoc(), + DIE->getDesignator(DesigIdx)->getFieldLoc())); + else + Replacements.push_back(Designator((IdentifierInfo *)0, SourceLocation(), + SourceLocation())); + assert(isa<FieldDecl>(*PI)); + Replacements.back().setField(cast<FieldDecl>(*PI)); + } + + // Expand the current designator into the set of replacement + // designators, so we have a full subobject path down to where the + // member of the anonymous struct/union is actually stored. + DIE->ExpandDesignator(SemaRef.Context, DesigIdx, &Replacements[0], + &Replacements[0] + Replacements.size()); +} + +/// \brief Given an implicit anonymous field, search the IndirectField that +/// corresponds to FieldName. +static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField, + IdentifierInfo *FieldName) { + assert(AnonField->isAnonymousStructOrUnion()); + Decl *NextDecl = AnonField->getNextDeclInContext(); + while (IndirectFieldDecl *IF = dyn_cast<IndirectFieldDecl>(NextDecl)) { + if (FieldName && FieldName == IF->getAnonField()->getIdentifier()) + return IF; + NextDecl = NextDecl->getNextDeclInContext(); + } + return 0; +} + +/// @brief Check the well-formedness of a C99 designated initializer. +/// +/// Determines whether the designated initializer @p DIE, which +/// resides at the given @p Index within the initializer list @p +/// IList, is well-formed for a current object of type @p DeclType +/// (C99 6.7.8). The actual subobject that this designator refers to +/// within the current subobject is returned in either +/// @p NextField or @p NextElementIndex (whichever is appropriate). +/// +/// @param IList The initializer list in which this designated +/// initializer occurs. +/// +/// @param DIE The designated initializer expression. +/// +/// @param DesigIdx The index of the current designator. +/// +/// @param DeclType The type of the "current object" (C99 6.7.8p17), +/// into which the designation in @p DIE should refer. +/// +/// @param NextField If non-NULL and the first designator in @p DIE is +/// a field, this will be set to the field declaration corresponding +/// to the field named by the designator. +/// +/// @param NextElementIndex If non-NULL and the first designator in @p +/// DIE is an array designator or GNU array-range designator, this +/// will be set to the last index initialized by this designator. +/// +/// @param Index Index into @p IList where the designated initializer +/// @p DIE occurs. +/// +/// @param StructuredList The initializer list expression that +/// describes all of the subobject initializers in the order they'll +/// actually be initialized. +/// +/// @returns true if there was an error, false otherwise. +bool +InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, + InitListExpr *IList, + DesignatedInitExpr *DIE, + unsigned DesigIdx, + QualType &CurrentObjectType, + RecordDecl::field_iterator *NextField, + llvm::APSInt *NextElementIndex, + unsigned &Index, + InitListExpr *StructuredList, + unsigned &StructuredIndex, + bool FinishSubobjectInit, + bool TopLevelObject) { + if (DesigIdx == DIE->size()) { + // Check the actual initialization for the designated object type. + bool prevHadError = hadError; + + // Temporarily remove the designator expression from the + // initializer list that the child calls see, so that we don't try + // to re-process the designator. + unsigned OldIndex = Index; + IList->setInit(OldIndex, DIE->getInit()); + + CheckSubElementType(Entity, IList, CurrentObjectType, Index, + StructuredList, StructuredIndex); + + // Restore the designated initializer expression in the syntactic + // form of the initializer list. + if (IList->getInit(OldIndex) != DIE->getInit()) + DIE->setInit(IList->getInit(OldIndex)); + IList->setInit(OldIndex, DIE); + + return hadError && !prevHadError; + } + + bool IsFirstDesignator = (DesigIdx == 0); + assert((IsFirstDesignator || StructuredList) && + "Need a non-designated initializer list to start from"); + + DesignatedInitExpr::Designator *D = DIE->getDesignator(DesigIdx); + // Determine the structural initializer list that corresponds to the + // current subobject. + StructuredList = IsFirstDesignator? SyntacticToSemantic[IList] + : getStructuredSubobjectInit(IList, Index, CurrentObjectType, + StructuredList, StructuredIndex, + SourceRange(D->getStartLocation(), + DIE->getSourceRange().getEnd())); + assert(StructuredList && "Expected a structured initializer list"); + + if (D->isFieldDesignator()) { + // C99 6.7.8p7: + // + // If a designator has the form + // + // . identifier + // + // then the current object (defined below) shall have + // structure or union type and the identifier shall be the + // name of a member of that type. + const RecordType *RT = CurrentObjectType->getAs<RecordType>(); + if (!RT) { + SourceLocation Loc = D->getDotLoc(); + if (Loc.isInvalid()) + Loc = D->getFieldLoc(); + SemaRef.Diag(Loc, diag::err_field_designator_non_aggr) + << SemaRef.getLangOptions().CPlusPlus << CurrentObjectType; + ++Index; + return true; + } + + // Note: we perform a linear search of the fields here, despite + // the fact that we have a faster lookup method, because we always + // need to compute the field's index. + FieldDecl *KnownField = D->getField(); + IdentifierInfo *FieldName = D->getFieldName(); + unsigned FieldIndex = 0; + RecordDecl::field_iterator + Field = RT->getDecl()->field_begin(), + FieldEnd = RT->getDecl()->field_end(); + for (; Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + // If we find a field representing an anonymous field, look in the + // IndirectFieldDecl that follow for the designated initializer. + if (!KnownField && Field->isAnonymousStructOrUnion()) { + if (IndirectFieldDecl *IF = + FindIndirectFieldDesignator(*Field, FieldName)) { + ExpandAnonymousFieldDesignator(SemaRef, DIE, DesigIdx, IF); + D = DIE->getDesignator(DesigIdx); + break; + } + } + if (KnownField && KnownField == *Field) + break; + if (FieldName && FieldName == Field->getIdentifier()) + break; + + ++FieldIndex; + } + + if (Field == FieldEnd) { + // There was no normal field in the struct with the designated + // name. Perform another lookup for this name, which may find + // something that we can't designate (e.g., a member function), + // may find nothing, or may find a member of an anonymous + // struct/union. + DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); + FieldDecl *ReplacementField = 0; + if (Lookup.first == Lookup.second) { + // Name lookup didn't find anything. Determine whether this + // was a typo for another field name. + LookupResult R(SemaRef, FieldName, D->getFieldLoc(), + Sema::LookupMemberName); + if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false, + Sema::CTC_NoKeywords) && + (ReplacementField = R.getAsSingle<FieldDecl>()) && + ReplacementField->getDeclContext()->getRedeclContext() + ->Equals(RT->getDecl())) { + SemaRef.Diag(D->getFieldLoc(), + diag::err_field_designator_unknown_suggest) + << FieldName << CurrentObjectType << R.getLookupName() + << FixItHint::CreateReplacement(D->getFieldLoc(), + R.getLookupName().getAsString()); + SemaRef.Diag(ReplacementField->getLocation(), + diag::note_previous_decl) + << ReplacementField->getDeclName(); + } else { + SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) + << FieldName << CurrentObjectType; + ++Index; + return true; + } + } + + if (!ReplacementField) { + // Name lookup found something, but it wasn't a field. + SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_nonfield) + << FieldName; + SemaRef.Diag((*Lookup.first)->getLocation(), + diag::note_field_designator_found); + ++Index; + return true; + } + + if (!KnownField) { + // The replacement field comes from typo correction; find it + // in the list of fields. + FieldIndex = 0; + Field = RT->getDecl()->field_begin(); + for (; Field != FieldEnd; ++Field) { + if (Field->isUnnamedBitfield()) + continue; + + if (ReplacementField == *Field || + Field->getIdentifier() == ReplacementField->getIdentifier()) + break; + + ++FieldIndex; + } + } + } + + // All of the fields of a union are located at the same place in + // the initializer list. + if (RT->getDecl()->isUnion()) { + FieldIndex = 0; + StructuredList->setInitializedFieldInUnion(*Field); + } + + // Update the designator with the field declaration. + D->setField(*Field); + + // Make sure that our non-designated initializer list has space + // for a subobject corresponding to this field. + if (FieldIndex >= StructuredList->getNumInits()) + StructuredList->resizeInits(SemaRef.Context, FieldIndex + 1); + + // This designator names a flexible array member. + if (Field->getType()->isIncompleteArrayType()) { + bool Invalid = false; + if ((DesigIdx + 1) != DIE->size()) { + // We can't designate an object within the flexible array + // member (because GCC doesn't allow it). + DesignatedInitExpr::Designator *NextD + = DIE->getDesignator(DesigIdx + 1); + SemaRef.Diag(NextD->getStartLocation(), + diag::err_designator_into_flexible_array_member) + << SourceRange(NextD->getStartLocation(), + DIE->getSourceRange().getEnd()); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << *Field; + Invalid = true; + } + + if (!hadError && !isa<InitListExpr>(DIE->getInit()) && + !isa<StringLiteral>(DIE->getInit())) { + // The initializer is not an initializer list. + SemaRef.Diag(DIE->getInit()->getSourceRange().getBegin(), + diag::err_flexible_array_init_needs_braces) + << DIE->getInit()->getSourceRange(); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << *Field; + Invalid = true; + } + + // Handle GNU flexible array initializers. + if (!Invalid && !TopLevelObject && + cast<InitListExpr>(DIE->getInit())->getNumInits() > 0) { + SemaRef.Diag(DIE->getSourceRange().getBegin(), + diag::err_flexible_array_init_nonempty) + << DIE->getSourceRange().getBegin(); + SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) + << *Field; + Invalid = true; + } + + if (Invalid) { + ++Index; + return true; + } + + // Initialize the array. + bool prevHadError = hadError; + unsigned newStructuredIndex = FieldIndex; + unsigned OldIndex = Index; + IList->setInit(Index, DIE->getInit()); + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, + StructuredList, newStructuredIndex); + + IList->setInit(OldIndex, DIE); + if (hadError && !prevHadError) { + ++Field; + ++FieldIndex; + if (NextField) + *NextField = Field; + StructuredIndex = FieldIndex; + return true; + } + } else { + // Recurse to check later designated subobjects. + QualType FieldType = (*Field)->getType(); + unsigned newStructuredIndex = FieldIndex; + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1, + FieldType, 0, 0, Index, + StructuredList, newStructuredIndex, + true, false)) + return true; + } + + // Find the position of the next field to be initialized in this + // subobject. + ++Field; + ++FieldIndex; + + // If this the first designator, our caller will continue checking + // the rest of this struct/class/union subobject. + if (IsFirstDesignator) { + if (NextField) + *NextField = Field; + StructuredIndex = FieldIndex; + return false; + } + + if (!FinishSubobjectInit) + return false; + + // We've already initialized something in the union; we're done. + if (RT->getDecl()->isUnion()) + return hadError; + + // Check the remaining fields within this class/struct/union subobject. + bool prevHadError = hadError; + + CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index, + StructuredList, FieldIndex); + return hadError && !prevHadError; + } + + // C99 6.7.8p6: + // + // If a designator has the form + // + // [ constant-expression ] + // + // then the current object (defined below) shall have array + // type and the expression shall be an integer constant + // expression. If the array is of unknown size, any + // nonnegative value is valid. + // + // Additionally, cope with the GNU extension that permits + // designators of the form + // + // [ constant-expression ... constant-expression ] + const ArrayType *AT = SemaRef.Context.getAsArrayType(CurrentObjectType); + if (!AT) { + SemaRef.Diag(D->getLBracketLoc(), diag::err_array_designator_non_array) + << CurrentObjectType; + ++Index; + return true; + } + + Expr *IndexExpr = 0; + llvm::APSInt DesignatedStartIndex, DesignatedEndIndex; + if (D->isArrayDesignator()) { + IndexExpr = DIE->getArrayIndex(*D); + DesignatedStartIndex = IndexExpr->EvaluateAsInt(SemaRef.Context); + DesignatedEndIndex = DesignatedStartIndex; + } else { + assert(D->isArrayRangeDesignator() && "Need array-range designator"); + + DesignatedStartIndex = + DIE->getArrayRangeStart(*D)->EvaluateAsInt(SemaRef.Context); + DesignatedEndIndex = + DIE->getArrayRangeEnd(*D)->EvaluateAsInt(SemaRef.Context); + IndexExpr = DIE->getArrayRangeEnd(*D); + + // Codegen can't handle evaluating array range designators that have side + // effects, because we replicate the AST value for each initialized element. + // As such, set the sawArrayRangeDesignator() bit if we initialize multiple + // elements with something that has a side effect, so codegen can emit an + // "error unsupported" error instead of miscompiling the app. + if (DesignatedStartIndex.getZExtValue()!=DesignatedEndIndex.getZExtValue()&& + DIE->getInit()->HasSideEffects(SemaRef.Context)) + FullyStructuredList->sawArrayRangeDesignator(); + } + + if (isa<ConstantArrayType>(AT)) { + llvm::APSInt MaxElements(cast<ConstantArrayType>(AT)->getSize(), false); + DesignatedStartIndex + = DesignatedStartIndex.extOrTrunc(MaxElements.getBitWidth()); + DesignatedStartIndex.setIsUnsigned(MaxElements.isUnsigned()); + DesignatedEndIndex + = DesignatedEndIndex.extOrTrunc(MaxElements.getBitWidth()); + DesignatedEndIndex.setIsUnsigned(MaxElements.isUnsigned()); + if (DesignatedEndIndex >= MaxElements) { + SemaRef.Diag(IndexExpr->getSourceRange().getBegin(), + diag::err_array_designator_too_large) + << DesignatedEndIndex.toString(10) << MaxElements.toString(10) + << IndexExpr->getSourceRange(); + ++Index; + return true; + } + } else { + // Make sure the bit-widths and signedness match. + if (DesignatedStartIndex.getBitWidth() > DesignatedEndIndex.getBitWidth()) + DesignatedEndIndex + = DesignatedEndIndex.extend(DesignatedStartIndex.getBitWidth()); + else if (DesignatedStartIndex.getBitWidth() < + DesignatedEndIndex.getBitWidth()) + DesignatedStartIndex + = DesignatedStartIndex.extend(DesignatedEndIndex.getBitWidth()); + DesignatedStartIndex.setIsUnsigned(true); + DesignatedEndIndex.setIsUnsigned(true); + } + + // Make sure that our non-designated initializer list has space + // for a subobject corresponding to this array element. + if (DesignatedEndIndex.getZExtValue() >= StructuredList->getNumInits()) + StructuredList->resizeInits(SemaRef.Context, + DesignatedEndIndex.getZExtValue() + 1); + + // Repeatedly perform subobject initializations in the range + // [DesignatedStartIndex, DesignatedEndIndex]. + + // Move to the next designator + unsigned ElementIndex = DesignatedStartIndex.getZExtValue(); + unsigned OldIndex = Index; + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + + while (DesignatedStartIndex <= DesignatedEndIndex) { + // Recurse to check later designated subobjects. + QualType ElementType = AT->getElementType(); + Index = OldIndex; + + ElementEntity.setElementIndex(ElementIndex); + if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1, + ElementType, 0, 0, Index, + StructuredList, ElementIndex, + (DesignatedStartIndex == DesignatedEndIndex), + false)) + return true; + + // Move to the next index in the array that we'll be initializing. + ++DesignatedStartIndex; + ElementIndex = DesignatedStartIndex.getZExtValue(); + } + + // If this the first designator, our caller will continue checking + // the rest of this array subobject. + if (IsFirstDesignator) { + if (NextElementIndex) + *NextElementIndex = DesignatedStartIndex; + StructuredIndex = ElementIndex; + return false; + } + + if (!FinishSubobjectInit) + return false; + + // Check the remaining elements within this array subobject. + bool prevHadError = hadError; + CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex, + /*SubobjectIsDesignatorContext=*/false, Index, + StructuredList, ElementIndex); + return hadError && !prevHadError; +} + +// Get the structured initializer list for a subobject of type +// @p CurrentObjectType. +InitListExpr * +InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, + QualType CurrentObjectType, + InitListExpr *StructuredList, + unsigned StructuredIndex, + SourceRange InitRange) { + Expr *ExistingInit = 0; + if (!StructuredList) + ExistingInit = SyntacticToSemantic[IList]; + else if (StructuredIndex < StructuredList->getNumInits()) + ExistingInit = StructuredList->getInit(StructuredIndex); + + if (InitListExpr *Result = dyn_cast_or_null<InitListExpr>(ExistingInit)) + return Result; + + if (ExistingInit) { + // We are creating an initializer list that initializes the + // subobjects of the current object, but there was already an + // initialization that completely initialized the current + // subobject, e.g., by a compound literal: + // + // struct X { int a, b; }; + // struct X xs[] = { [0] = (struct X) { 1, 2 }, [0].b = 3 }; + // + // Here, xs[0].a == 0 and xs[0].b == 3, since the second, + // designated initializer re-initializes the whole + // subobject [0], overwriting previous initializers. + SemaRef.Diag(InitRange.getBegin(), + diag::warn_subobject_initializer_overrides) + << InitRange; + SemaRef.Diag(ExistingInit->getSourceRange().getBegin(), + diag::note_previous_initializer) + << /*FIXME:has side effects=*/0 + << ExistingInit->getSourceRange(); + } + + InitListExpr *Result + = new (SemaRef.Context) InitListExpr(SemaRef.Context, + InitRange.getBegin(), 0, 0, + InitRange.getEnd()); + + Result->setType(CurrentObjectType.getNonLValueExprType(SemaRef.Context)); + + // Pre-allocate storage for the structured initializer list. + unsigned NumElements = 0; + unsigned NumInits = 0; + bool GotNumInits = false; + if (!StructuredList) { + NumInits = IList->getNumInits(); + GotNumInits = true; + } else if (Index < IList->getNumInits()) { + if (InitListExpr *SubList = dyn_cast<InitListExpr>(IList->getInit(Index))) { + NumInits = SubList->getNumInits(); + GotNumInits = true; + } + } + + if (const ArrayType *AType + = SemaRef.Context.getAsArrayType(CurrentObjectType)) { + if (const ConstantArrayType *CAType = dyn_cast<ConstantArrayType>(AType)) { + NumElements = CAType->getSize().getZExtValue(); + // Simple heuristic so that we don't allocate a very large + // initializer with many empty entries at the end. + if (GotNumInits && NumElements > NumInits) + NumElements = 0; + } + } else if (const VectorType *VType = CurrentObjectType->getAs<VectorType>()) + NumElements = VType->getNumElements(); + else if (const RecordType *RType = CurrentObjectType->getAs<RecordType>()) { + RecordDecl *RDecl = RType->getDecl(); + if (RDecl->isUnion()) + NumElements = 1; + else + NumElements = std::distance(RDecl->field_begin(), + RDecl->field_end()); + } + + if (NumElements < NumInits) + NumElements = IList->getNumInits(); + + Result->reserveInits(SemaRef.Context, NumElements); + + // Link this new initializer list into the structured initializer + // lists. + if (StructuredList) + StructuredList->updateInit(SemaRef.Context, StructuredIndex, Result); + else { + Result->setSyntacticForm(IList); + SyntacticToSemantic[IList] = Result; + } + + return Result; +} + +/// Update the initializer at index @p StructuredIndex within the +/// structured initializer list to the value @p expr. +void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, + unsigned &StructuredIndex, + Expr *expr) { + // No structured initializer list to update + if (!StructuredList) + return; + + if (Expr *PrevInit = StructuredList->updateInit(SemaRef.Context, + StructuredIndex, expr)) { + // This initializer overwrites a previous initializer. Warn. + SemaRef.Diag(expr->getSourceRange().getBegin(), + diag::warn_initializer_overrides) + << expr->getSourceRange(); + SemaRef.Diag(PrevInit->getSourceRange().getBegin(), + diag::note_previous_initializer) + << /*FIXME:has side effects=*/0 + << PrevInit->getSourceRange(); + } + + ++StructuredIndex; +} + +/// Check that the given Index expression is a valid array designator +/// value. This is essentailly just a wrapper around +/// VerifyIntegerConstantExpression that also checks for negative values +/// and produces a reasonable diagnostic if there is a +/// failure. Returns true if there was an error, false otherwise. If +/// everything went okay, Value will receive the value of the constant +/// expression. +static bool +CheckArrayDesignatorExpr(Sema &S, Expr *Index, llvm::APSInt &Value) { + SourceLocation Loc = Index->getSourceRange().getBegin(); + + // Make sure this is an integer constant expression. + if (S.VerifyIntegerConstantExpression(Index, &Value)) + return true; + + if (Value.isSigned() && Value.isNegative()) + return S.Diag(Loc, diag::err_array_designator_negative) + << Value.toString(10) << Index->getSourceRange(); + + Value.setIsUnsigned(true); + return false; +} + +ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, + SourceLocation Loc, + bool GNUSyntax, + ExprResult Init) { + typedef DesignatedInitExpr::Designator ASTDesignator; + + bool Invalid = false; + llvm::SmallVector<ASTDesignator, 32> Designators; + llvm::SmallVector<Expr *, 32> InitExpressions; + + // Build designators and check array designator expressions. + for (unsigned Idx = 0; Idx < Desig.getNumDesignators(); ++Idx) { + const Designator &D = Desig.getDesignator(Idx); + switch (D.getKind()) { + case Designator::FieldDesignator: + Designators.push_back(ASTDesignator(D.getField(), D.getDotLoc(), + D.getFieldLoc())); + break; + + case Designator::ArrayDesignator: { + Expr *Index = static_cast<Expr *>(D.getArrayIndex()); + llvm::APSInt IndexValue; + if (!Index->isTypeDependent() && + !Index->isValueDependent() && + CheckArrayDesignatorExpr(*this, Index, IndexValue)) + Invalid = true; + else { + Designators.push_back(ASTDesignator(InitExpressions.size(), + D.getLBracketLoc(), + D.getRBracketLoc())); + InitExpressions.push_back(Index); + } + break; + } + + case Designator::ArrayRangeDesignator: { + Expr *StartIndex = static_cast<Expr *>(D.getArrayRangeStart()); + Expr *EndIndex = static_cast<Expr *>(D.getArrayRangeEnd()); + llvm::APSInt StartValue; + llvm::APSInt EndValue; + bool StartDependent = StartIndex->isTypeDependent() || + StartIndex->isValueDependent(); + bool EndDependent = EndIndex->isTypeDependent() || + EndIndex->isValueDependent(); + if ((!StartDependent && + CheckArrayDesignatorExpr(*this, StartIndex, StartValue)) || + (!EndDependent && + CheckArrayDesignatorExpr(*this, EndIndex, EndValue))) + Invalid = true; + else { + // Make sure we're comparing values with the same bit width. + if (StartDependent || EndDependent) { + // Nothing to compute. + } else if (StartValue.getBitWidth() > EndValue.getBitWidth()) + EndValue = EndValue.extend(StartValue.getBitWidth()); + else if (StartValue.getBitWidth() < EndValue.getBitWidth()) + StartValue = StartValue.extend(EndValue.getBitWidth()); + + if (!StartDependent && !EndDependent && EndValue < StartValue) { + Diag(D.getEllipsisLoc(), diag::err_array_designator_empty_range) + << StartValue.toString(10) << EndValue.toString(10) + << StartIndex->getSourceRange() << EndIndex->getSourceRange(); + Invalid = true; + } else { + Designators.push_back(ASTDesignator(InitExpressions.size(), + D.getLBracketLoc(), + D.getEllipsisLoc(), + D.getRBracketLoc())); + InitExpressions.push_back(StartIndex); + InitExpressions.push_back(EndIndex); + } + } + break; + } + } + } + + if (Invalid || Init.isInvalid()) + return ExprError(); + + // Clear out the expressions within the designation. + Desig.ClearExprs(*this); + + DesignatedInitExpr *DIE + = DesignatedInitExpr::Create(Context, + Designators.data(), Designators.size(), + InitExpressions.data(), InitExpressions.size(), + Loc, GNUSyntax, Init.takeAs<Expr>()); + + if (getLangOptions().CPlusPlus) + Diag(DIE->getLocStart(), diag::ext_designated_init_cxx) + << DIE->getSourceRange(); + else if (!getLangOptions().C99) + Diag(DIE->getLocStart(), diag::ext_designated_init) + << DIE->getSourceRange(); + + return Owned(DIE); +} + +bool Sema::CheckInitList(const InitializedEntity &Entity, + InitListExpr *&InitList, QualType &DeclType) { + InitListChecker CheckInitList(*this, Entity, InitList, DeclType); + if (!CheckInitList.HadError()) + InitList = CheckInitList.getFullyStructuredList(); + + return CheckInitList.HadError(); +} + +//===----------------------------------------------------------------------===// +// Initialization entity +//===----------------------------------------------------------------------===// + +InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, + const InitializedEntity &Parent) + : Parent(&Parent), Index(Index) +{ + if (const ArrayType *AT = Context.getAsArrayType(Parent.getType())) { + Kind = EK_ArrayElement; + Type = AT->getElementType(); + } else { + Kind = EK_VectorElement; + Type = Parent.getType()->getAs<VectorType>()->getElementType(); + } +} + +InitializedEntity InitializedEntity::InitializeBase(ASTContext &Context, + CXXBaseSpecifier *Base, + bool IsInheritedVirtualBase) +{ + InitializedEntity Result; + Result.Kind = EK_Base; + Result.Base = reinterpret_cast<uintptr_t>(Base); + if (IsInheritedVirtualBase) + Result.Base |= 0x01; + + Result.Type = Base->getType(); + return Result; +} + +DeclarationName InitializedEntity::getName() const { + switch (getKind()) { + case EK_Parameter: + if (!VariableOrMember) + return DeclarationName(); + // Fall through + + case EK_Variable: + case EK_Member: + return VariableOrMember->getDeclName(); + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_Delegating: + case EK_ArrayElement: + case EK_VectorElement: + case EK_BlockElement: + return DeclarationName(); + } + + // Silence GCC warning + return DeclarationName(); +} + +DeclaratorDecl *InitializedEntity::getDecl() const { + switch (getKind()) { + case EK_Variable: + case EK_Parameter: + case EK_Member: + return VariableOrMember; + + case EK_Result: + case EK_Exception: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_Delegating: + case EK_ArrayElement: + case EK_VectorElement: + case EK_BlockElement: + return 0; + } + + // Silence GCC warning + return 0; +} + +bool InitializedEntity::allowsNRVO() const { + switch (getKind()) { + case EK_Result: + case EK_Exception: + return LocAndNRVO.NRVO; + + case EK_Variable: + case EK_Parameter: + case EK_Member: + case EK_New: + case EK_Temporary: + case EK_Base: + case EK_Delegating: + case EK_ArrayElement: + case EK_VectorElement: + case EK_BlockElement: + break; + } + + return false; +} + +//===----------------------------------------------------------------------===// +// Initialization sequence +//===----------------------------------------------------------------------===// + +void InitializationSequence::Step::Destroy() { + switch (Kind) { + case SK_ResolveAddressOfOverloadedFunction: + case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseXValue: + case SK_CastDerivedToBaseLValue: + case SK_BindReference: + case SK_BindReferenceToTemporary: + case SK_ExtraneousCopyToTemporary: + case SK_UserConversion: + case SK_QualificationConversionRValue: + case SK_QualificationConversionXValue: + case SK_QualificationConversionLValue: + case SK_ListInitialization: + case SK_ConstructorInitialization: + case SK_ZeroInitialization: + case SK_CAssignment: + case SK_StringInit: + case SK_ObjCObjectConversion: + case SK_ArrayInit: + break; + + case SK_ConversionSequence: + delete ICS; + } +} + +bool InitializationSequence::isDirectReferenceBinding() const { + return getKind() == ReferenceBinding && Steps.back().Kind == SK_BindReference; +} + +bool InitializationSequence::isAmbiguous() const { + if (!Failed()) + return false; + + switch (getFailureKind()) { + case FK_TooManyInitsForReference: + case FK_ArrayNeedsInitList: + case FK_ArrayNeedsInitListOrStringLiteral: + case FK_AddressOfOverloadFailed: // FIXME: Could do better + case FK_NonConstLValueReferenceBindingToTemporary: + case FK_NonConstLValueReferenceBindingToUnrelated: + case FK_RValueReferenceBindingToLValue: + case FK_ReferenceInitDropsQualifiers: + case FK_ReferenceInitFailed: + case FK_ConversionFailed: + case FK_ConversionFromPropertyFailed: + case FK_TooManyInitsForScalar: + case FK_ReferenceBindingToInitList: + case FK_InitListBadDestinationType: + case FK_DefaultInitOfConst: + case FK_Incomplete: + case FK_ArrayTypeMismatch: + case FK_NonConstantArrayInit: + return false; + + case FK_ReferenceInitOverloadFailed: + case FK_UserConversionOverloadFailed: + case FK_ConstructorOverloadFailed: + return FailedOverloadResult == OR_Ambiguous; + } + + return false; +} + +bool InitializationSequence::isConstructorInitialization() const { + return !Steps.empty() && Steps.back().Kind == SK_ConstructorInitialization; +} + +void InitializationSequence::AddAddressOverloadResolutionStep( + FunctionDecl *Function, + DeclAccessPair Found) { + Step S; + S.Kind = SK_ResolveAddressOfOverloadedFunction; + S.Type = Function->getType(); + S.Function.Function = Function; + S.Function.FoundDecl = Found; + Steps.push_back(S); +} + +void InitializationSequence::AddDerivedToBaseCastStep(QualType BaseType, + ExprValueKind VK) { + Step S; + switch (VK) { + case VK_RValue: S.Kind = SK_CastDerivedToBaseRValue; break; + case VK_XValue: S.Kind = SK_CastDerivedToBaseXValue; break; + case VK_LValue: S.Kind = SK_CastDerivedToBaseLValue; break; + default: llvm_unreachable("No such category"); + } + S.Type = BaseType; + Steps.push_back(S); +} + +void InitializationSequence::AddReferenceBindingStep(QualType T, + bool BindingTemporary) { + Step S; + S.Kind = BindingTemporary? SK_BindReferenceToTemporary : SK_BindReference; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddExtraneousCopyToTemporary(QualType T) { + Step S; + S.Kind = SK_ExtraneousCopyToTemporary; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddUserConversionStep(FunctionDecl *Function, + DeclAccessPair FoundDecl, + QualType T) { + Step S; + S.Kind = SK_UserConversion; + S.Type = T; + S.Function.Function = Function; + S.Function.FoundDecl = FoundDecl; + Steps.push_back(S); +} + +void InitializationSequence::AddQualificationConversionStep(QualType Ty, + ExprValueKind VK) { + Step S; + S.Kind = SK_QualificationConversionRValue; // work around a gcc warning + switch (VK) { + case VK_RValue: + S.Kind = SK_QualificationConversionRValue; + break; + case VK_XValue: + S.Kind = SK_QualificationConversionXValue; + break; + case VK_LValue: + S.Kind = SK_QualificationConversionLValue; + break; + } + S.Type = Ty; + Steps.push_back(S); +} + +void InitializationSequence::AddConversionSequenceStep( + const ImplicitConversionSequence &ICS, + QualType T) { + Step S; + S.Kind = SK_ConversionSequence; + S.Type = T; + S.ICS = new ImplicitConversionSequence(ICS); + Steps.push_back(S); +} + +void InitializationSequence::AddListInitializationStep(QualType T) { + Step S; + S.Kind = SK_ListInitialization; + S.Type = T; + Steps.push_back(S); +} + +void +InitializationSequence::AddConstructorInitializationStep( + CXXConstructorDecl *Constructor, + AccessSpecifier Access, + QualType T) { + Step S; + S.Kind = SK_ConstructorInitialization; + S.Type = T; + S.Function.Function = Constructor; + S.Function.FoundDecl = DeclAccessPair::make(Constructor, Access); + Steps.push_back(S); +} + +void InitializationSequence::AddZeroInitializationStep(QualType T) { + Step S; + S.Kind = SK_ZeroInitialization; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddCAssignmentStep(QualType T) { + Step S; + S.Kind = SK_CAssignment; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddStringInitStep(QualType T) { + Step S; + S.Kind = SK_StringInit; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddObjCObjectConversionStep(QualType T) { + Step S; + S.Kind = SK_ObjCObjectConversion; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddArrayInitStep(QualType T) { + Step S; + S.Kind = SK_ArrayInit; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::SetOverloadFailure(FailureKind Failure, + OverloadingResult Result) { + setSequenceKind(FailedSequence); + this->Failure = Failure; + this->FailedOverloadResult = Result; +} + +//===----------------------------------------------------------------------===// +// Attempt initialization +//===----------------------------------------------------------------------===// + +/// \brief Attempt list initialization (C++0x [dcl.init.list]) +static void TryListInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitListExpr *InitList, + InitializationSequence &Sequence) { + // FIXME: We only perform rudimentary checking of list + // initializations at this point, then assume that any list + // initialization of an array, aggregate, or scalar will be + // well-formed. When we actually "perform" list initialization, we'll + // do all of the necessary checking. C++0x initializer lists will + // force us to perform more checking here. + + QualType DestType = Entity.getType(); + + // C++ [dcl.init]p13: + // If T is a scalar type, then a declaration of the form + // + // T x = { a }; + // + // is equivalent to + // + // T x = a; + if (DestType->isScalarType()) { + if (InitList->getNumInits() > 1 && S.getLangOptions().CPlusPlus) { + Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForScalar); + return; + } + + // Assume scalar initialization from a single value works. + } else if (DestType->isAggregateType()) { + // Assume aggregate initialization works. + } else if (DestType->isVectorType()) { + // Assume vector initialization works. + } else if (DestType->isReferenceType()) { + // FIXME: C++0x defines behavior for this. + Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); + return; + } else if (DestType->isRecordType()) { + // FIXME: C++0x defines behavior for this + Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType); + } + + // Add a general "list initialization" step. + Sequence.AddListInitializationStep(DestType); +} + +/// \brief Try a reference initialization that involves calling a conversion +/// function. +static OverloadingResult TryRefInitWithConversionFunction(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + bool AllowRValues, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); + QualType T1 = cv1T1.getUnqualifiedType(); + QualType cv2T2 = Initializer->getType(); + QualType T2 = cv2T2.getUnqualifiedType(); + + bool DerivedToBase; + bool ObjCConversion; + assert(!S.CompareReferenceRelationship(Initializer->getLocStart(), + T1, T2, DerivedToBase, + ObjCConversion) && + "Must have incompatible references when binding via conversion"); + (void)DerivedToBase; + (void)ObjCConversion; + + // Build the candidate set directly in the initialization sequence + // structure, so that it will persist if we fail. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + CandidateSet.clear(); + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct; + + const RecordType *T1RecordType = 0; + if (AllowRValues && (T1RecordType = T1->getAs<RecordType>()) && + !S.RequireCompleteType(Kind.getLocation(), T1, 0)) { + // The type we're converting to is a class type. Enumerate its constructors + // to see if there is a suitable conversion. + CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl()); + + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); + if (ConstructorTmpl) + Constructor = cast<CXXConstructorDecl>( + ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast<CXXConstructorDecl>(D); + + if (!Constructor->isInvalidDecl() && + Constructor->isConvertingConstructor(AllowExplicit)) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + &Initializer, 1, CandidateSet, + /*SuppressUserConversions=*/true); + else + S.AddOverloadCandidate(Constructor, FoundDecl, + &Initializer, 1, CandidateSet, + /*SuppressUserConversions=*/true); + } + } + } + if (T1RecordType && T1RecordType->getDecl()->isInvalidDecl()) + return OR_No_Viable_Function; + + const RecordType *T2RecordType = 0; + if ((T2RecordType = T2->getAs<RecordType>()) && + !S.RequireCompleteType(Kind.getLocation(), T2, 0)) { + // The type we're converting from is a class type, enumerate its conversion + // functions. + CXXRecordDecl *T2RecordDecl = cast<CXXRecordDecl>(T2RecordType->getDecl()); + + const UnresolvedSetImpl *Conversions + = T2RecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::const_iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + Conv = cast<CXXConversionDecl>(D); + + // If the conversion function doesn't return a reference type, + // it can't be considered for this conversion unless we're allowed to + // consider rvalues. + // FIXME: Do we need to make sure that we only consider conversion + // candidates with reference-compatible results? That might be needed to + // break recursion. + if ((AllowExplicit || !Conv->isExplicit()) && + (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), + ActingDC, Initializer, + DestType, CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, + Initializer, DestType, CandidateSet); + } + } + } + if (T2RecordType && T2RecordType->getDecl()->isInvalidDecl()) + return OR_No_Viable_Function; + + SourceLocation DeclLoc = Initializer->getLocStart(); + + // Perform overload resolution. If it fails, return the failed result. + OverloadCandidateSet::iterator Best; + if (OverloadingResult Result + = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) + return Result; + + FunctionDecl *Function = Best->Function; + + // This is the overload that will actually be used for the initialization, so + // mark it as used. + S.MarkDeclarationReferenced(DeclLoc, Function); + + // Compute the returned type of the conversion. + if (isa<CXXConversionDecl>(Function)) + T2 = Function->getResultType(); + else + T2 = cv1T1; + + // Add the user-defined conversion step. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, + T2.getNonLValueExprType(S.Context)); + + // Determine whether we need to perform derived-to-base or + // cv-qualification adjustments. + ExprValueKind VK = VK_RValue; + if (T2->isLValueReferenceType()) + VK = VK_LValue; + else if (const RValueReferenceType *RRef = T2->getAs<RValueReferenceType>()) + VK = RRef->getPointeeType()->isFunctionType() ? VK_LValue : VK_XValue; + + bool NewDerivedToBase = false; + bool NewObjCConversion = false; + Sema::ReferenceCompareResult NewRefRelationship + = S.CompareReferenceRelationship(DeclLoc, T1, + T2.getNonLValueExprType(S.Context), + NewDerivedToBase, NewObjCConversion); + if (NewRefRelationship == Sema::Ref_Incompatible) { + // If the type we've converted to is not reference-related to the + // type we're looking for, then there is another conversion step + // we need to perform to produce a temporary of the right type + // that we'll be binding to. + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard = Best->FinalConversion; + T2 = ICS.Standard.getToType(2); + Sequence.AddConversionSequenceStep(ICS, T2); + } else if (NewDerivedToBase) + Sequence.AddDerivedToBaseCastStep( + S.Context.getQualifiedType(T1, + T2.getNonReferenceType().getQualifiers()), + VK); + else if (NewObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, + T2.getNonReferenceType().getQualifiers())); + + if (cv1T1.getQualifiers() != T2.getNonReferenceType().getQualifiers()) + Sequence.AddQualificationConversionStep(cv1T1, VK); + + Sequence.AddReferenceBindingStep(cv1T1, !T2->isReferenceType()); + return OR_Success; +} + +/// \brief Attempt reference initialization (C++0x [dcl.init.ref]) +static void TryReferenceInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + InitializationSequence &Sequence) { + Sequence.setSequenceKind(InitializationSequence::ReferenceBinding); + + QualType DestType = Entity.getType(); + QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); + Qualifiers T1Quals; + QualType T1 = S.Context.getUnqualifiedArrayType(cv1T1, T1Quals); + QualType cv2T2 = Initializer->getType(); + Qualifiers T2Quals; + QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); + SourceLocation DeclLoc = Initializer->getLocStart(); + + // If the initializer is the address of an overloaded function, try + // to resolve the overloaded function. If all goes well, T2 is the + // type of the resulting function. + if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { + DeclAccessPair Found; + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Initializer, + T1, + false, + Found)) { + Sequence.AddAddressOverloadResolutionStep(Fn, Found); + cv2T2 = Fn->getType(); + T2 = cv2T2.getUnqualifiedType(); + } else if (!T1->isRecordType()) { + Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + return; + } + } + + // Compute some basic properties of the types and the initializer. + bool isLValueRef = DestType->isLValueReferenceType(); + bool isRValueRef = !isLValueRef; + bool DerivedToBase = false; + bool ObjCConversion = false; + Expr::Classification InitCategory = Initializer->Classify(S.Context); + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase, + ObjCConversion); + + // C++0x [dcl.init.ref]p5: + // A reference to type "cv1 T1" is initialized by an expression of type + // "cv2 T2" as follows: + // + // - If the reference is an lvalue reference and the initializer + // expression + // Note the analogous bullet points for rvlaue refs to functions. Because + // there are no function rvalues in C++, rvalue refs to functions are treated + // like lvalue refs. + OverloadingResult ConvOvlResult = OR_Success; + bool T1Function = T1->isFunctionType(); + if (isLValueRef || T1Function) { + if (InitCategory.isLValue() && + (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification || + (Kind.isCStyleOrFunctionalCast() && + RefRelationship == Sema::Ref_Related))) { + // - is an lvalue (but is not a bit-field), and "cv1 T1" is + // reference-compatible with "cv2 T2," or + // + // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a + // bit-field when we're determining whether the reference initialization + // can occur. However, we do pay attention to whether it is a bit-field + // to decide whether we're actually binding to a temporary created from + // the bit-field. + if (DerivedToBase) + Sequence.AddDerivedToBaseCastStep( + S.Context.getQualifiedType(T1, T2Quals), + VK_LValue); + else if (ObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, T2Quals)); + + if (T1Quals != T2Quals) + Sequence.AddQualificationConversionStep(cv1T1, VK_LValue); + bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() && + (Initializer->getBitField() || Initializer->refersToVectorElement()); + Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary); + return; + } + + // - has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to an + // lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible + // with "cv3 T3" (this conversion is selected by enumerating the + // applicable conversion functions (13.3.1.6) and choosing the best + // one through overload resolution (13.3)), + // If we have an rvalue ref to function type here, the rhs must be + // an rvalue. + if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() && + (isLValueRef || InitCategory.isRValue())) { + ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind, + Initializer, + /*AllowRValues=*/isRValueRef, + Sequence); + if (ConvOvlResult == OR_Success) + return; + if (ConvOvlResult != OR_No_Viable_Function) { + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + } + } + } + + // - Otherwise, the reference shall be an lvalue reference to a + // non-volatile const type (i.e., cv1 shall be const), or the reference + // shall be an rvalue reference. + if (isLValueRef && !(T1Quals.hasConst() && !T1Quals.hasVolatile())) { + if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) + Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + else + Sequence.SetFailed(InitCategory.isLValue() + ? (RefRelationship == Sema::Ref_Related + ? InitializationSequence::FK_ReferenceInitDropsQualifiers + : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated) + : InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); + + return; + } + + // - If the initializer expression + // - is an xvalue, class prvalue, array prvalue, or function lvalue and + // "cv1 T1" is reference-compatible with "cv2 T2" + // Note: functions are handled below. + if (!T1Function && + (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification || + (Kind.isCStyleOrFunctionalCast() && + RefRelationship == Sema::Ref_Related)) && + (InitCategory.isXValue() || + (InitCategory.isPRValue() && T2->isRecordType()) || + (InitCategory.isPRValue() && T2->isArrayType()))) { + ExprValueKind ValueKind = InitCategory.isXValue()? VK_XValue : VK_RValue; + if (InitCategory.isPRValue() && T2->isRecordType()) { + // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the + // compiler the freedom to perform a copy here or bind to the + // object, while C++0x requires that we bind directly to the + // object. Hence, we always bind to the object without making an + // extra copy. However, in C++03 requires that we check for the + // presence of a suitable copy constructor: + // + // The constructor that would be used to make the copy shall + // be callable whether or not the copy is actually done. + if (!S.getLangOptions().CPlusPlus0x && !S.getLangOptions().Microsoft) + Sequence.AddExtraneousCopyToTemporary(cv2T2); + } + + if (DerivedToBase) + Sequence.AddDerivedToBaseCastStep(S.Context.getQualifiedType(T1, T2Quals), + ValueKind); + else if (ObjCConversion) + Sequence.AddObjCObjectConversionStep( + S.Context.getQualifiedType(T1, T2Quals)); + + if (T1Quals != T2Quals) + Sequence.AddQualificationConversionStep(cv1T1, ValueKind); + Sequence.AddReferenceBindingStep(cv1T1, + /*bindingTemporary=*/(InitCategory.isPRValue() && !T2->isArrayType())); + return; + } + + // - has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to an + // xvalue, class prvalue, or function lvalue of type "cv3 T3", + // where "cv1 T1" is reference-compatible with "cv3 T3", + if (T2->isRecordType()) { + if (RefRelationship == Sema::Ref_Incompatible) { + ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, + Kind, Initializer, + /*AllowRValues=*/true, + Sequence); + if (ConvOvlResult) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + + return; + } + + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); + return; + } + + // - Otherwise, a temporary of type "cv1 T1" is created and initialized + // from the initializer expression using the rules for a non-reference + // copy initialization (8.5). The reference is then bound to the + // temporary. [...] + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct); + + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); + + if (S.TryImplicitConversion(Sequence, TempEntity, Initializer, + /*SuppressUserConversions*/ false, + AllowExplicit, + /*FIXME:InOverloadResolution=*/false, + /*CStyle=*/Kind.isCStyleOrFunctionalCast())) { + // FIXME: Use the conversion function set stored in ICS to turn + // this into an overloading ambiguity diagnostic. However, we need + // to keep that set as an OverloadCandidateSet rather than as some + // other kind of set. + if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) + Sequence.SetOverloadFailure( + InitializationSequence::FK_ReferenceInitOverloadFailed, + ConvOvlResult); + else if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) + Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitFailed); + return; + } + + // [...] If T1 is reference-related to T2, cv1 must be the + // same cv-qualification as, or greater cv-qualification + // than, cv2; otherwise, the program is ill-formed. + unsigned T1CVRQuals = T1Quals.getCVRQualifiers(); + unsigned T2CVRQuals = T2Quals.getCVRQualifiers(); + if (RefRelationship == Sema::Ref_Related && + (T1CVRQuals | T2CVRQuals) != T1CVRQuals) { + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); + return; + } + + // [...] If T1 is reference-related to T2 and the reference is an rvalue + // reference, the initializer expression shall not be an lvalue. + if (RefRelationship >= Sema::Ref_Related && !isLValueRef && + InitCategory.isLValue()) { + Sequence.SetFailed( + InitializationSequence::FK_RValueReferenceBindingToLValue); + return; + } + + Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); + return; +} + +/// \brief Attempt character array initialization from a string literal +/// (C++ [dcl.init.string], C99 6.7.8). +static void TryStringLiteralInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + InitializationSequence &Sequence) { + Sequence.AddStringInitStep(Entity.getType()); +} + +/// \brief Attempt initialization by constructor (C++ [dcl.init]), which +/// enumerates the constructors of the initialized entity and performs overload +/// resolution to select the best. +static void TryConstructorInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, unsigned NumArgs, + QualType DestType, + InitializationSequence &Sequence) { + // Build the candidate set directly in the initialization sequence + // structure, so that it will persist if we fail. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + CandidateSet.clear(); + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct || + Kind.getKind() == InitializationKind::IK_Value || + Kind.getKind() == InitializationKind::IK_Default); + + // The type we're constructing needs to be complete. + if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + Sequence.SetFailed(InitializationSequence::FK_Incomplete); + return; + } + + // The type we're converting to is a class type. Enumerate its constructors + // to see if one is suitable. + const RecordType *DestRecordType = DestType->getAs<RecordType>(); + assert(DestRecordType && "Constructor initialization requires record type"); + CXXRecordDecl *DestRecordDecl + = cast<CXXRecordDecl>(DestRecordType->getDecl()); + + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + bool SuppressUserConversions = false; + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D); + if (ConstructorTmpl) + Constructor = cast<CXXConstructorDecl>( + ConstructorTmpl->getTemplatedDecl()); + else { + Constructor = cast<CXXConstructorDecl>(D); + + // If we're performing copy initialization using a copy constructor, we + // suppress user-defined conversions on the arguments. + // FIXME: Move constructors? + if (Kind.getKind() == InitializationKind::IK_Copy && + Constructor->isCopyConstructor()) + SuppressUserConversions = true; + } + + if (!Constructor->isInvalidDecl() && + (AllowExplicit || !Constructor->isExplicit())) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + Args, NumArgs, CandidateSet, + SuppressUserConversions); + else + S.AddOverloadCandidate(Constructor, FoundDecl, + Args, NumArgs, CandidateSet, + SuppressUserConversions); + } + } + + SourceLocation DeclLoc = Kind.getLocation(); + + // Perform overload resolution. If it fails, return the failed result. + OverloadCandidateSet::iterator Best; + if (OverloadingResult Result + = CandidateSet.BestViableFunction(S, DeclLoc, Best)) { + Sequence.SetOverloadFailure( + InitializationSequence::FK_ConstructorOverloadFailed, + Result); + return; + } + + // C++0x [dcl.init]p6: + // If a program calls for the default initialization of an object + // of a const-qualified type T, T shall be a class type with a + // user-provided default constructor. + if (Kind.getKind() == InitializationKind::IK_Default && + Entity.getType().isConstQualified() && + cast<CXXConstructorDecl>(Best->Function)->isImplicit()) { + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } + + // Add the constructor initialization step. Any cv-qualification conversion is + // subsumed by the initialization. + Sequence.AddConstructorInitializationStep( + cast<CXXConstructorDecl>(Best->Function), + Best->FoundDecl.getAccess(), + DestType); +} + +/// \brief Attempt value initialization (C++ [dcl.init]p7). +static void TryValueInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitializationSequence &Sequence) { + // C++ [dcl.init]p5: + // + // To value-initialize an object of type T means: + QualType T = Entity.getType(); + + // -- if T is an array type, then each element is value-initialized; + while (const ArrayType *AT = S.Context.getAsArrayType(T)) + T = AT->getElementType(); + + if (const RecordType *RT = T->getAs<RecordType>()) { + if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { + // -- if T is a class type (clause 9) with a user-declared + // constructor (12.1), then the default constructor for T is + // called (and the initialization is ill-formed if T has no + // accessible default constructor); + // + // FIXME: we really want to refer to a single subobject of the array, + // but Entity doesn't have a way to capture that (yet). + if (ClassDecl->hasUserDeclaredConstructor()) + return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); + + // -- if T is a (possibly cv-qualified) non-union class type + // without a user-provided constructor, then the object is + // zero-initialized and, if T's implicitly-declared default + // constructor is non-trivial, that constructor is called. + if ((ClassDecl->getTagKind() == TTK_Class || + ClassDecl->getTagKind() == TTK_Struct)) { + Sequence.AddZeroInitializationStep(Entity.getType()); + return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); + } + } + } + + Sequence.AddZeroInitializationStep(Entity.getType()); +} + +/// \brief Attempt default initialization (C++ [dcl.init]p6). +static void TryDefaultInitialization(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + InitializationSequence &Sequence) { + assert(Kind.getKind() == InitializationKind::IK_Default); + + // C++ [dcl.init]p6: + // To default-initialize an object of type T means: + // - if T is an array type, each element is default-initialized; + QualType DestType = Entity.getType(); + while (const ArrayType *Array = S.Context.getAsArrayType(DestType)) + DestType = Array->getElementType(); + + // - if T is a (possibly cv-qualified) class type (Clause 9), the default + // constructor for T is called (and the initialization is ill-formed if + // T has no accessible default constructor); + if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) { + TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence); + return; + } + + // - otherwise, no initialization is performed. + + // If a program calls for the default initialization of an object of + // a const-qualified type T, T shall be a class type with a user-provided + // default constructor. + if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); +} + +/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]), +/// which enumerates all conversion functions and performs overload resolution +/// to select the best. +static void TryUserDefinedConversion(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr *Initializer, + InitializationSequence &Sequence) { + QualType DestType = Entity.getType(); + assert(!DestType->isReferenceType() && "References are handled elsewhere"); + QualType SourceType = Initializer->getType(); + assert((DestType->isRecordType() || SourceType->isRecordType()) && + "Must have a class type to perform a user-defined conversion"); + + // Build the candidate set directly in the initialization sequence + // structure, so that it will persist if we fail. + OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet(); + CandidateSet.clear(); + + // Determine whether we are allowed to call explicit constructors or + // explicit conversion operators. + bool AllowExplicit = Kind.getKind() == InitializationKind::IK_Direct; + + if (const RecordType *DestRecordType = DestType->getAs<RecordType>()) { + // The type we're converting to is a class type. Enumerate its constructors + // to see if there is a suitable conversion. + CXXRecordDecl *DestRecordDecl + = cast<CXXRecordDecl>(DestRecordType->getDecl()); + + // Try to complete the type we're converting to. + if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl + = dyn_cast<FunctionTemplateDecl>(D); + if (ConstructorTmpl) + Constructor = cast<CXXConstructorDecl>( + ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast<CXXConstructorDecl>(D); + + if (!Constructor->isInvalidDecl() && + Constructor->isConvertingConstructor(AllowExplicit)) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + &Initializer, 1, CandidateSet, + /*SuppressUserConversions=*/true); + else + S.AddOverloadCandidate(Constructor, FoundDecl, + &Initializer, 1, CandidateSet, + /*SuppressUserConversions=*/true); + } + } + } + } + + SourceLocation DeclLoc = Initializer->getLocStart(); + + if (const RecordType *SourceRecordType = SourceType->getAs<RecordType>()) { + // The type we're converting from is a class type, enumerate its conversion + // functions. + + // We can only enumerate the conversion functions for a complete type; if + // the type isn't complete, simply skip this step. + if (!S.RequireCompleteType(DeclLoc, SourceType, 0)) { + CXXRecordDecl *SourceRecordDecl + = cast<CXXRecordDecl>(SourceRecordType->getDecl()); + + const UnresolvedSetImpl *Conversions + = SourceRecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::const_iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(D); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + Conv = cast<CXXConversionDecl>(D); + + if (AllowExplicit || !Conv->isExplicit()) { + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), + ActingDC, Initializer, DestType, + CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, + Initializer, DestType, CandidateSet); + } + } + } + } + + // Perform overload resolution. If it fails, return the failed result. + OverloadCandidateSet::iterator Best; + if (OverloadingResult Result + = CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) { + Sequence.SetOverloadFailure( + InitializationSequence::FK_UserConversionOverloadFailed, + Result); + return; + } + + FunctionDecl *Function = Best->Function; + S.MarkDeclarationReferenced(DeclLoc, Function); + + if (isa<CXXConstructorDecl>(Function)) { + // Add the user-defined conversion step. Any cv-qualification conversion is + // subsumed by the initialization. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType); + return; + } + + // Add the user-defined conversion step that calls the conversion function. + QualType ConvType = Function->getCallResultType(); + if (ConvType->getAs<RecordType>()) { + // If we're converting to a class type, there may be an copy if + // the resulting temporary object (possible to create an object of + // a base class type). That copy is not a separate conversion, so + // we just make a note of the actual destination type (possibly a + // base class of the type returned by the conversion function) and + // let the user-defined conversion step handle the conversion. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType); + return; + } + + Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType); + + // If the conversion following the call to the conversion function + // is interesting, add it as a separate step. + if (Best->FinalConversion.First || Best->FinalConversion.Second || + Best->FinalConversion.Third) { + ImplicitConversionSequence ICS; + ICS.setStandard(); + ICS.Standard = Best->FinalConversion; + Sequence.AddConversionSequenceStep(ICS, DestType); + } +} + +/// \brief Determine whether we have compatible array types for the +/// purposes of GNU by-copy array initialization. +static bool hasCompatibleArrayTypes(ASTContext &Context, + const ArrayType *Dest, + const ArrayType *Source) { + // If the source and destination array types are equivalent, we're + // done. + if (Context.hasSameType(QualType(Dest, 0), QualType(Source, 0))) + return true; + + // Make sure that the element types are the same. + if (!Context.hasSameType(Dest->getElementType(), Source->getElementType())) + return false; + + // The only mismatch we allow is when the destination is an + // incomplete array type and the source is a constant array type. + return Source->isConstantArrayType() && Dest->isIncompleteArrayType(); +} + +InitializationSequence::InitializationSequence(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, + unsigned NumArgs) + : FailedCandidateSet(Kind.getLocation()) { + ASTContext &Context = S.Context; + + // C++0x [dcl.init]p16: + // The semantics of initializers are as follows. The destination type is + // the type of the object or reference being initialized and the source + // type is the type of the initializer expression. The source type is not + // defined when the initializer is a braced-init-list or when it is a + // parenthesized list of expressions. + QualType DestType = Entity.getType(); + + if (DestType->isDependentType() || + Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { + SequenceKind = DependentSequence; + return; + } + + // Almost everything is a normal sequence. + setSequenceKind(NormalSequence); + + for (unsigned I = 0; I != NumArgs; ++I) + if (Args[I]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = S.ConvertPropertyForRValue(Args[I]); + if (Result.isInvalid()) { + SetFailed(FK_ConversionFromPropertyFailed); + return; + } + Args[I] = Result.take(); + } + + QualType SourceType; + Expr *Initializer = 0; + if (NumArgs == 1) { + Initializer = Args[0]; + if (!isa<InitListExpr>(Initializer)) + SourceType = Initializer->getType(); + } + + // - If the initializer is a braced-init-list, the object is + // list-initialized (8.5.4). + if (InitListExpr *InitList = dyn_cast_or_null<InitListExpr>(Initializer)) { + TryListInitialization(S, Entity, Kind, InitList, *this); + return; + } + + // - If the destination type is a reference type, see 8.5.3. + if (DestType->isReferenceType()) { + // C++0x [dcl.init.ref]p1: + // A variable declared to be a T& or T&&, that is, "reference to type T" + // (8.3.2), shall be initialized by an object, or function, of type T or + // by an object that can be converted into a T. + // (Therefore, multiple arguments are not permitted.) + if (NumArgs != 1) + SetFailed(FK_TooManyInitsForReference); + else + TryReferenceInitialization(S, Entity, Kind, Args[0], *this); + return; + } + + // - If the initializer is (), the object is value-initialized. + if (Kind.getKind() == InitializationKind::IK_Value || + (Kind.getKind() == InitializationKind::IK_Direct && NumArgs == 0)) { + TryValueInitialization(S, Entity, Kind, *this); + return; + } + + // Handle default initialization. + if (Kind.getKind() == InitializationKind::IK_Default) { + TryDefaultInitialization(S, Entity, Kind, *this); + return; + } + + // - If the destination type is an array of characters, an array of + // char16_t, an array of char32_t, or an array of wchar_t, and the + // initializer is a string literal, see 8.5.2. + // - Otherwise, if the destination type is an array, the program is + // ill-formed. + if (const ArrayType *DestAT = Context.getAsArrayType(DestType)) { + if (Initializer && IsStringInit(Initializer, DestAT, Context)) { + TryStringLiteralInitialization(S, Entity, Kind, Initializer, *this); + return; + } + + // Note: as an GNU C extension, we allow initialization of an + // array from a compound literal that creates an array of the same + // type, so long as the initializer has no side effects. + if (!S.getLangOptions().CPlusPlus && Initializer && + isa<CompoundLiteralExpr>(Initializer->IgnoreParens()) && + Initializer->getType()->isArrayType()) { + const ArrayType *SourceAT + = Context.getAsArrayType(Initializer->getType()); + if (!hasCompatibleArrayTypes(S.Context, DestAT, SourceAT)) + SetFailed(FK_ArrayTypeMismatch); + else if (Initializer->HasSideEffects(S.Context)) + SetFailed(FK_NonConstantArrayInit); + else { + AddArrayInitStep(DestType); + } + } else if (DestAT->getElementType()->isAnyCharacterType()) + SetFailed(FK_ArrayNeedsInitListOrStringLiteral); + else + SetFailed(FK_ArrayNeedsInitList); + + return; + } + + // Handle initialization in C + if (!S.getLangOptions().CPlusPlus) { + AddCAssignmentStep(DestType); + return; + } + + // - If the destination type is a (possibly cv-qualified) class type: + if (DestType->isRecordType()) { + // - If the initialization is direct-initialization, or if it is + // copy-initialization where the cv-unqualified version of the + // source type is the same class as, or a derived class of, the + // class of the destination, constructors are considered. [...] + if (Kind.getKind() == InitializationKind::IK_Direct || + (Kind.getKind() == InitializationKind::IK_Copy && + (Context.hasSameUnqualifiedType(SourceType, DestType) || + S.IsDerivedFrom(SourceType, DestType)))) + TryConstructorInitialization(S, Entity, Kind, Args, NumArgs, + Entity.getType(), *this); + // - Otherwise (i.e., for the remaining copy-initialization cases), + // user-defined conversion sequences that can convert from the source + // type to the destination type or (when a conversion function is + // used) to a derived class thereof are enumerated as described in + // 13.3.1.4, and the best one is chosen through overload resolution + // (13.3). + else + TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); + return; + } + + if (NumArgs > 1) { + SetFailed(FK_TooManyInitsForScalar); + return; + } + assert(NumArgs == 1 && "Zero-argument case handled above"); + + // - Otherwise, if the source type is a (possibly cv-qualified) class + // type, conversion functions are considered. + if (!SourceType.isNull() && SourceType->isRecordType()) { + TryUserDefinedConversion(S, Entity, Kind, Initializer, *this); + return; + } + + // - Otherwise, the initial value of the object being initialized is the + // (possibly converted) value of the initializer expression. Standard + // conversions (Clause 4) will be used, if necessary, to convert the + // initializer expression to the cv-unqualified version of the + // destination type; no user-defined conversions are considered. + if (S.TryImplicitConversion(*this, Entity, Initializer, + /*SuppressUserConversions*/ true, + /*AllowExplicitConversions*/ false, + /*InOverloadResolution*/ false, + /*CStyle=*/Kind.isCStyleOrFunctionalCast())) + { + DeclAccessPair dap; + if (Initializer->getType() == Context.OverloadTy && + !S.ResolveAddressOfOverloadedFunction(Initializer + , DestType, false, dap)) + SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); + else + SetFailed(InitializationSequence::FK_ConversionFailed); + } +} + +InitializationSequence::~InitializationSequence() { + for (llvm::SmallVectorImpl<Step>::iterator Step = Steps.begin(), + StepEnd = Steps.end(); + Step != StepEnd; ++Step) + Step->Destroy(); +} + +//===----------------------------------------------------------------------===// +// Perform initialization +//===----------------------------------------------------------------------===// +static Sema::AssignmentAction +getAssignmentAction(const InitializedEntity &Entity) { + switch(Entity.getKind()) { + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + return Sema::AA_Initializing; + + case InitializedEntity::EK_Parameter: + if (Entity.getDecl() && + isa<ObjCMethodDecl>(Entity.getDecl()->getDeclContext())) + return Sema::AA_Sending; + + return Sema::AA_Passing; + + case InitializedEntity::EK_Result: + return Sema::AA_Returning; + + case InitializedEntity::EK_Temporary: + // FIXME: Can we tell apart casting vs. converting? + return Sema::AA_Casting; + + case InitializedEntity::EK_Member: + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_BlockElement: + return Sema::AA_Initializing; + } + + return Sema::AA_Converting; +} + +/// \brief Whether we should binding a created object as a temporary when +/// initializing the given entity. +static bool shouldBindAsTemporary(const InitializedEntity &Entity) { + switch (Entity.getKind()) { + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_Result: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_Exception: + case InitializedEntity::EK_BlockElement: + return false; + + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + return true; + } + + llvm_unreachable("missed an InitializedEntity kind?"); +} + +/// \brief Whether the given entity, when initialized with an object +/// created for that initialization, requires destruction. +static bool shouldDestroyTemporary(const InitializedEntity &Entity) { + switch (Entity.getKind()) { + case InitializedEntity::EK_Member: + case InitializedEntity::EK_Result: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_BlockElement: + return false; + + case InitializedEntity::EK_Variable: + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Exception: + return true; + } + + llvm_unreachable("missed an InitializedEntity kind?"); +} + +/// \brief Make a (potentially elidable) temporary copy of the object +/// provided by the given initializer by calling the appropriate copy +/// constructor. +/// +/// \param S The Sema object used for type-checking. +/// +/// \param T The type of the temporary object, which must either be +/// the type of the initializer expression or a superclass thereof. +/// +/// \param Enter The entity being initialized. +/// +/// \param CurInit The initializer expression. +/// +/// \param IsExtraneousCopy Whether this is an "extraneous" copy that +/// is permitted in C++03 (but not C++0x) when binding a reference to +/// an rvalue. +/// +/// \returns An expression that copies the initializer expression into +/// a temporary object, or an error expression if a copy could not be +/// created. +static ExprResult CopyObject(Sema &S, + QualType T, + const InitializedEntity &Entity, + ExprResult CurInit, + bool IsExtraneousCopy) { + // Determine which class type we're copying to. + Expr *CurInitExpr = (Expr *)CurInit.get(); + CXXRecordDecl *Class = 0; + if (const RecordType *Record = T->getAs<RecordType>()) + Class = cast<CXXRecordDecl>(Record->getDecl()); + if (!Class) + return move(CurInit); + + // C++0x [class.copy]p32: + // When certain criteria are met, an implementation is allowed to + // omit the copy/move construction of a class object, even if the + // copy/move constructor and/or destructor for the object have + // side effects. [...] + // - when a temporary class object that has not been bound to a + // reference (12.2) would be copied/moved to a class object + // with the same cv-unqualified type, the copy/move operation + // can be omitted by constructing the temporary object + // directly into the target of the omitted copy/move + // + // Note that the other three bullets are handled elsewhere. Copy + // elision for return statements and throw expressions are handled as part + // of constructor initialization, while copy elision for exception handlers + // is handled by the run-time. + bool Elidable = CurInitExpr->isTemporaryObject(S.Context, Class); + SourceLocation Loc; + switch (Entity.getKind()) { + case InitializedEntity::EK_Result: + Loc = Entity.getReturnLoc(); + break; + + case InitializedEntity::EK_Exception: + Loc = Entity.getThrowLoc(); + break; + + case InitializedEntity::EK_Variable: + Loc = Entity.getDecl()->getLocation(); + break; + + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Member: + case InitializedEntity::EK_Parameter: + case InitializedEntity::EK_Temporary: + case InitializedEntity::EK_New: + case InitializedEntity::EK_Base: + case InitializedEntity::EK_Delegating: + case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_BlockElement: + Loc = CurInitExpr->getLocStart(); + break; + } + + // Make sure that the type we are copying is complete. + if (S.RequireCompleteType(Loc, T, S.PDiag(diag::err_temp_copy_incomplete))) + return move(CurInit); + + // Perform overload resolution using the class's copy/move constructors. + DeclContext::lookup_iterator Con, ConEnd; + OverloadCandidateSet CandidateSet(Loc); + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class); + Con != ConEnd; ++Con) { + // Only consider copy/move constructors and constructor templates. Per + // C++0x [dcl.init]p16, second bullet to class types, this + // initialization is direct-initialization. + CXXConstructorDecl *Constructor = 0; + + if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) { + // Handle copy/moveconstructors, only. + if (!Constructor || Constructor->isInvalidDecl() || + !Constructor->isCopyOrMoveConstructor() || + !Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + continue; + + DeclAccessPair FoundDecl + = DeclAccessPair::make(Constructor, Constructor->getAccess()); + S.AddOverloadCandidate(Constructor, FoundDecl, + &CurInitExpr, 1, CandidateSet); + continue; + } + + // Handle constructor templates. + FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con); + if (ConstructorTmpl->isInvalidDecl()) + continue; + + Constructor = cast<CXXConstructorDecl>( + ConstructorTmpl->getTemplatedDecl()); + if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true)) + continue; + + // FIXME: Do we need to limit this to copy-constructor-like + // candidates? + DeclAccessPair FoundDecl + = DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess()); + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, 0, + &CurInitExpr, 1, CandidateSet, true); + } + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, Loc, Best)) { + case OR_Success: + break; + + case OR_No_Viable_Function: + S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext() + ? diag::ext_rvalue_to_reference_temp_copy_no_viable + : diag::err_temp_copy_no_viable) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + CandidateSet.NoteCandidates(S, OCD_AllCandidates, &CurInitExpr, 1); + if (!IsExtraneousCopy || S.isSFINAEContext()) + return ExprError(); + return move(CurInit); + + case OR_Ambiguous: + S.Diag(Loc, diag::err_temp_copy_ambiguous) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + CandidateSet.NoteCandidates(S, OCD_ViableCandidates, &CurInitExpr, 1); + return ExprError(); + + case OR_Deleted: + S.Diag(Loc, diag::err_temp_copy_deleted) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange(); + S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) + << Best->Function->isDeleted(); + return ExprError(); + } + + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); + ASTOwningVector<Expr*> ConstructorArgs(S); + CurInit.release(); // Ownership transferred into MultiExprArg, below. + + S.CheckConstructorAccess(Loc, Constructor, Entity, + Best->FoundDecl.getAccess(), IsExtraneousCopy); + + if (IsExtraneousCopy) { + // If this is a totally extraneous copy for C++03 reference + // binding purposes, just return the original initialization + // expression. We don't generate an (elided) copy operation here + // because doing so would require us to pass down a flag to avoid + // infinite recursion, where each step adds another extraneous, + // elidable copy. + + // Instantiate the default arguments of any extra parameters in + // the selected copy constructor, as if we were going to create a + // proper call to the copy constructor. + for (unsigned I = 1, N = Constructor->getNumParams(); I != N; ++I) { + ParmVarDecl *Parm = Constructor->getParamDecl(I); + if (S.RequireCompleteType(Loc, Parm->getType(), + S.PDiag(diag::err_call_incomplete_argument))) + break; + + // Build the default argument expression; we don't actually care + // if this succeeds or not, because this routine will complain + // if there was a problem. + S.BuildCXXDefaultArgExpr(Loc, Constructor, Parm); + } + + return S.Owned(CurInitExpr); + } + + S.MarkDeclarationReferenced(Loc, Constructor); + + // Determine the arguments required to actually perform the + // constructor call (we might have derived-to-base conversions, or + // the copy constructor may have default arguments). + if (S.CompleteConstructorCall(Constructor, MultiExprArg(&CurInitExpr, 1), + Loc, ConstructorArgs)) + return ExprError(); + + // Actually perform the constructor call. + CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + + // If we're supposed to bind temporaries, do so. + if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + return move(CurInit); +} + +void InitializationSequence::PrintInitLocationNote(Sema &S, + const InitializedEntity &Entity) { + if (Entity.getKind() == InitializedEntity::EK_Parameter && Entity.getDecl()) { + if (Entity.getDecl()->getLocation().isInvalid()) + return; + + if (Entity.getDecl()->getDeclName()) + S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_named_here) + << Entity.getDecl()->getDeclName(); + else + S.Diag(Entity.getDecl()->getLocation(), diag::note_parameter_here); + } +} + +ExprResult +InitializationSequence::Perform(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + MultiExprArg Args, + QualType *ResultType) { + if (Failed()) { + unsigned NumArgs = Args.size(); + Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs); + return ExprError(); + } + + if (getKind() == DependentSequence) { + // If the declaration is a non-dependent, incomplete array type + // that has an initializer, then its type will be completed once + // the initializer is instantiated. + if (ResultType && !Entity.getType()->isDependentType() && + Args.size() == 1) { + QualType DeclType = Entity.getType(); + if (const IncompleteArrayType *ArrayT + = S.Context.getAsIncompleteArrayType(DeclType)) { + // FIXME: We don't currently have the ability to accurately + // compute the length of an initializer list without + // performing full type-checking of the initializer list + // (since we have to determine where braces are implicitly + // introduced and such). So, we fall back to making the array + // type a dependently-sized array type with no specified + // bound. + if (isa<InitListExpr>((Expr *)Args.get()[0])) { + SourceRange Brackets; + + // Scavange the location of the brackets from the entity, if we can. + if (DeclaratorDecl *DD = Entity.getDecl()) { + if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { + TypeLoc TL = TInfo->getTypeLoc(); + if (IncompleteArrayTypeLoc *ArrayLoc + = dyn_cast<IncompleteArrayTypeLoc>(&TL)) + Brackets = ArrayLoc->getBracketsRange(); + } + } + + *ResultType + = S.Context.getDependentSizedArrayType(ArrayT->getElementType(), + /*NumElts=*/0, + ArrayT->getSizeModifier(), + ArrayT->getIndexTypeCVRQualifiers(), + Brackets); + } + + } + } + + if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast()) + return ExprResult(Args.release()[0]); + + if (Args.size() == 0) + return S.Owned((Expr *)0); + + unsigned NumArgs = Args.size(); + return S.Owned(new (S.Context) ParenListExpr(S.Context, + SourceLocation(), + (Expr **)Args.release(), + NumArgs, + SourceLocation())); + } + + // No steps means no initialization. + if (Steps.empty()) + return S.Owned((Expr *)0); + + QualType DestType = Entity.getType().getNonReferenceType(); + // FIXME: Ugly hack around the fact that Entity.getType() is not + // the same as Entity.getDecl()->getType() in cases involving type merging, + // and we want latter when it makes sense. + if (ResultType) + *ResultType = Entity.getDecl() ? Entity.getDecl()->getType() : + Entity.getType(); + + ExprResult CurInit = S.Owned((Expr *)0); + + // For initialization steps that start with a single initializer, + // grab the only argument out the Args and place it into the "current" + // initializer. + switch (Steps.front().Kind) { + case SK_ResolveAddressOfOverloadedFunction: + case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseXValue: + case SK_CastDerivedToBaseLValue: + case SK_BindReference: + case SK_BindReferenceToTemporary: + case SK_ExtraneousCopyToTemporary: + case SK_UserConversion: + case SK_QualificationConversionLValue: + case SK_QualificationConversionXValue: + case SK_QualificationConversionRValue: + case SK_ConversionSequence: + case SK_ListInitialization: + case SK_CAssignment: + case SK_StringInit: + case SK_ObjCObjectConversion: + case SK_ArrayInit: { + assert(Args.size() == 1); + CurInit = Args.get()[0]; + if (!CurInit.get()) return ExprError(); + + // Read from a property when initializing something with it. + if (CurInit.get()->getObjectKind() == OK_ObjCProperty) { + CurInit = S.ConvertPropertyForRValue(CurInit.take()); + if (CurInit.isInvalid()) + return ExprError(); + } + break; + } + + case SK_ConstructorInitialization: + case SK_ZeroInitialization: + break; + } + + // Walk through the computed steps for the initialization sequence, + // performing the specified conversions along the way. + bool ConstructorInitRequiresZeroInit = false; + for (step_iterator Step = step_begin(), StepEnd = step_end(); + Step != StepEnd; ++Step) { + if (CurInit.isInvalid()) + return ExprError(); + + QualType SourceType = CurInit.get() ? CurInit.get()->getType() : QualType(); + + switch (Step->Kind) { + case SK_ResolveAddressOfOverloadedFunction: + // Overload resolution determined which function invoke; update the + // initializer to reflect that choice. + S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); + S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()); + CurInit = S.FixOverloadedFunctionReference(move(CurInit), + Step->Function.FoundDecl, + Step->Function.Function); + break; + + case SK_CastDerivedToBaseRValue: + case SK_CastDerivedToBaseXValue: + case SK_CastDerivedToBaseLValue: { + // We have a derived-to-base cast that produces either an rvalue or an + // lvalue. Perform that cast. + + CXXCastPath BasePath; + + // Casts to inaccessible base classes are allowed with C-style casts. + bool IgnoreBaseAccess = Kind.isCStyleOrFunctionalCast(); + if (S.CheckDerivedToBaseConversion(SourceType, Step->Type, + CurInit.get()->getLocStart(), + CurInit.get()->getSourceRange(), + &BasePath, IgnoreBaseAccess)) + return ExprError(); + + if (S.BasePathInvolvesVirtualBase(BasePath)) { + QualType T = SourceType; + if (const PointerType *Pointer = T->getAs<PointerType>()) + T = Pointer->getPointeeType(); + if (const RecordType *RecordTy = T->getAs<RecordType>()) + S.MarkVTableUsed(CurInit.get()->getLocStart(), + cast<CXXRecordDecl>(RecordTy->getDecl())); + } + + ExprValueKind VK = + Step->Kind == SK_CastDerivedToBaseLValue ? + VK_LValue : + (Step->Kind == SK_CastDerivedToBaseXValue ? + VK_XValue : + VK_RValue); + CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, + Step->Type, + CK_DerivedToBase, + CurInit.get(), + &BasePath, VK)); + break; + } + + case SK_BindReference: + if (FieldDecl *BitField = CurInit.get()->getBitField()) { + // References cannot bind to bit fields (C++ [dcl.init.ref]p5). + S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield) + << Entity.getType().isVolatileQualified() + << BitField->getDeclName() + << CurInit.get()->getSourceRange(); + S.Diag(BitField->getLocation(), diag::note_bitfield_decl); + return ExprError(); + } + + if (CurInit.get()->refersToVectorElement()) { + // References cannot bind to vector elements. + S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) + << Entity.getType().isVolatileQualified() + << CurInit.get()->getSourceRange(); + PrintInitLocationNote(S, Entity); + return ExprError(); + } + + // Reference binding does not have any corresponding ASTs. + + // Check exception specifications + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) + return ExprError(); + + break; + + case SK_BindReferenceToTemporary: + // Reference binding does not have any corresponding ASTs. + + // Check exception specifications + if (S.CheckExceptionSpecCompatibility(CurInit.get(), DestType)) + return ExprError(); + + break; + + case SK_ExtraneousCopyToTemporary: + CurInit = CopyObject(S, Step->Type, Entity, move(CurInit), + /*IsExtraneousCopy=*/true); + break; + + case SK_UserConversion: { + // We have a user-defined conversion that invokes either a constructor + // or a conversion function. + CastKind CastKind; + bool IsCopy = false; + FunctionDecl *Fn = Step->Function.Function; + DeclAccessPair FoundFn = Step->Function.FoundDecl; + bool CreatedObject = false; + bool IsLvalue = false; + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) { + // Build a call to the selected constructor. + ASTOwningVector<Expr*> ConstructorArgs(S); + SourceLocation Loc = CurInit.get()->getLocStart(); + CurInit.release(); // Ownership transferred into MultiExprArg, below. + + // Determine the arguments required to actually perform the constructor + // call. + Expr *Arg = CurInit.get(); + if (S.CompleteConstructorCall(Constructor, + MultiExprArg(&Arg, 1), + Loc, ConstructorArgs)) + return ExprError(); + + // Build the an expression that constructs a temporary. + CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, + move_arg(ConstructorArgs), + /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, + SourceRange()); + if (CurInit.isInvalid()) + return ExprError(); + + S.CheckConstructorAccess(Kind.getLocation(), Constructor, Entity, + FoundFn.getAccess()); + S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); + + CastKind = CK_ConstructorConversion; + QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); + if (S.Context.hasSameUnqualifiedType(SourceType, Class) || + S.IsDerivedFrom(SourceType, Class)) + IsCopy = true; + + CreatedObject = true; + } else { + // Build a call to the conversion function. + CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn); + IsLvalue = Conversion->getResultType()->isLValueReferenceType(); + S.CheckMemberOperatorAccess(Kind.getLocation(), CurInit.get(), 0, + FoundFn); + S.DiagnoseUseOfDecl(FoundFn, Kind.getLocation()); + + // FIXME: Should we move this initialization into a separate + // derived-to-base conversion? I believe the answer is "no", because + // we don't want to turn off access control here for c-style casts. + ExprResult CurInitExprRes = + S.PerformObjectArgumentInitialization(CurInit.take(), /*Qualifier=*/0, + FoundFn, Conversion); + if(CurInitExprRes.isInvalid()) + return ExprError(); + CurInit = move(CurInitExprRes); + + // Build the actual call to the conversion function. + CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion); + if (CurInit.isInvalid() || !CurInit.get()) + return ExprError(); + + CastKind = CK_UserDefinedConversion; + + CreatedObject = Conversion->getResultType()->isRecordType(); + } + + bool RequiresCopy = !IsCopy && + getKind() != InitializationSequence::ReferenceBinding; + if (RequiresCopy || shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + else if (CreatedObject && shouldDestroyTemporary(Entity)) { + QualType T = CurInit.get()->getType(); + if (const RecordType *Record = T->getAs<RecordType>()) { + CXXDestructorDecl *Destructor + = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl())); + S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor, + S.PDiag(diag::err_access_dtor_temp) << T); + S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor); + S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart()); + } + } + + // FIXME: xvalues + CurInit = S.Owned(ImplicitCastExpr::Create(S.Context, + CurInit.get()->getType(), + CastKind, CurInit.get(), 0, + IsLvalue ? VK_LValue : VK_RValue)); + + if (RequiresCopy) + CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity, + move(CurInit), /*IsExtraneousCopy=*/false); + + break; + } + + case SK_QualificationConversionLValue: + case SK_QualificationConversionXValue: + case SK_QualificationConversionRValue: { + // Perform a qualification conversion; these can never go wrong. + ExprValueKind VK = + Step->Kind == SK_QualificationConversionLValue ? + VK_LValue : + (Step->Kind == SK_QualificationConversionXValue ? + VK_XValue : + VK_RValue); + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, CK_NoOp, VK); + break; + } + + case SK_ConversionSequence: { + ExprResult CurInitExprRes = + S.PerformImplicitConversion(CurInit.get(), Step->Type, *Step->ICS, + getAssignmentAction(Entity), + Kind.isCStyleOrFunctionalCast()); + if (CurInitExprRes.isInvalid()) + return ExprError(); + CurInit = move(CurInitExprRes); + break; + } + + case SK_ListInitialization: { + InitListExpr *InitList = cast<InitListExpr>(CurInit.get()); + QualType Ty = Step->Type; + if (S.CheckInitList(Entity, InitList, ResultType? *ResultType : Ty)) + return ExprError(); + + CurInit.release(); + CurInit = S.Owned(InitList); + break; + } + + case SK_ConstructorInitialization: { + unsigned NumArgs = Args.size(); + CXXConstructorDecl *Constructor + = cast<CXXConstructorDecl>(Step->Function.Function); + + // Build a call to the selected constructor. + ASTOwningVector<Expr*> ConstructorArgs(S); + SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) + ? Kind.getEqualLoc() + : Kind.getLocation(); + + if (Kind.getKind() == InitializationKind::IK_Default) { + // Force even a trivial, implicit default constructor to be + // semantically checked. We do this explicitly because we don't build + // the definition for completely trivial constructors. + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(ClassDecl && "No parent class for constructor."); + if (Constructor->isDefaulted() && Constructor->isDefaultConstructor() && + ClassDecl->hasTrivialDefaultConstructor() && + !Constructor->isUsed(false)) + S.DefineImplicitDefaultConstructor(Loc, Constructor); + } + + // Determine the arguments required to actually perform the constructor + // call. + if (S.CompleteConstructorCall(Constructor, move(Args), + Loc, ConstructorArgs)) + return ExprError(); + + + if (Entity.getKind() == InitializedEntity::EK_Temporary && + NumArgs != 1 && // FIXME: Hack to work around cast weirdness + (Kind.getKind() == InitializationKind::IK_Direct || + Kind.getKind() == InitializationKind::IK_Value)) { + // An explicitly-constructed temporary, e.g., X(1, 2). + unsigned NumExprs = ConstructorArgs.size(); + Expr **Exprs = (Expr **)ConstructorArgs.take(); + S.MarkDeclarationReferenced(Loc, Constructor); + S.DiagnoseUseOfDecl(Constructor, Loc); + + TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); + if (!TSInfo) + TSInfo = S.Context.getTrivialTypeSourceInfo(Entity.getType(), Loc); + + CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, + Constructor, + TSInfo, + Exprs, + NumExprs, + Kind.getParenRange(), + ConstructorInitRequiresZeroInit)); + } else { + CXXConstructExpr::ConstructionKind ConstructKind = + CXXConstructExpr::CK_Complete; + + if (Entity.getKind() == InitializedEntity::EK_Base) { + ConstructKind = Entity.getBaseSpecifier()->isVirtual() ? + CXXConstructExpr::CK_VirtualBase : + CXXConstructExpr::CK_NonVirtualBase; + } else if (Entity.getKind() == InitializedEntity::EK_Delegating) { + ConstructKind = CXXConstructExpr::CK_Delegating; + } + + // Only get the parenthesis range if it is a direct construction. + SourceRange parenRange = + Kind.getKind() == InitializationKind::IK_Direct ? + Kind.getParenRange() : SourceRange(); + + // If the entity allows NRVO, mark the construction as elidable + // unconditionally. + if (Entity.allowsNRVO()) + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, /*Elidable=*/true, + move_arg(ConstructorArgs), + ConstructorInitRequiresZeroInit, + ConstructKind, + parenRange); + else + CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), + Constructor, + move_arg(ConstructorArgs), + ConstructorInitRequiresZeroInit, + ConstructKind, + parenRange); + } + if (CurInit.isInvalid()) + return ExprError(); + + // Only check access if all of that succeeded. + S.CheckConstructorAccess(Loc, Constructor, Entity, + Step->Function.FoundDecl.getAccess()); + S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Loc); + + if (shouldBindAsTemporary(Entity)) + CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); + + break; + } + + case SK_ZeroInitialization: { + step_iterator NextStep = Step; + ++NextStep; + if (NextStep != StepEnd && + NextStep->Kind == SK_ConstructorInitialization) { + // The need for zero-initialization is recorded directly into + // the call to the object's constructor within the next step. + ConstructorInitRequiresZeroInit = true; + } else if (Kind.getKind() == InitializationKind::IK_Value && + S.getLangOptions().CPlusPlus && + !Kind.isImplicitValueInit()) { + TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo(); + if (!TSInfo) + TSInfo = S.Context.getTrivialTypeSourceInfo(Step->Type, + Kind.getRange().getBegin()); + + CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr( + TSInfo->getType().getNonLValueExprType(S.Context), + TSInfo, + Kind.getRange().getEnd())); + } else { + CurInit = S.Owned(new (S.Context) ImplicitValueInitExpr(Step->Type)); + } + break; + } + + case SK_CAssignment: { + QualType SourceType = CurInit.get()->getType(); + ExprResult Result = move(CurInit); + Sema::AssignConvertType ConvTy = + S.CheckSingleAssignmentConstraints(Step->Type, Result); + if (Result.isInvalid()) + return ExprError(); + CurInit = move(Result); + + // If this is a call, allow conversion to a transparent union. + ExprResult CurInitExprRes = move(CurInit); + if (ConvTy != Sema::Compatible && + Entity.getKind() == InitializedEntity::EK_Parameter && + S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes) + == Sema::Compatible) + ConvTy = Sema::Compatible; + if (CurInitExprRes.isInvalid()) + return ExprError(); + CurInit = move(CurInitExprRes); + + bool Complained; + if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), + Step->Type, SourceType, + CurInit.get(), + getAssignmentAction(Entity), + &Complained)) { + PrintInitLocationNote(S, Entity); + return ExprError(); + } else if (Complained) + PrintInitLocationNote(S, Entity); + break; + } + + case SK_StringInit: { + QualType Ty = Step->Type; + CheckStringInit(CurInit.get(), ResultType ? *ResultType : Ty, + S.Context.getAsArrayType(Ty), S); + break; + } + + case SK_ObjCObjectConversion: + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, + CK_ObjCObjectLValueCast, + S.CastCategory(CurInit.get())); + break; + + case SK_ArrayInit: + // Okay: we checked everything before creating this step. Note that + // this is a GNU extension. + S.Diag(Kind.getLocation(), diag::ext_array_init_copy) + << Step->Type << CurInit.get()->getType() + << CurInit.get()->getSourceRange(); + + // If the destination type is an incomplete array type, update the + // type accordingly. + if (ResultType) { + if (const IncompleteArrayType *IncompleteDest + = S.Context.getAsIncompleteArrayType(Step->Type)) { + if (const ConstantArrayType *ConstantSource + = S.Context.getAsConstantArrayType(CurInit.get()->getType())) { + *ResultType = S.Context.getConstantArrayType( + IncompleteDest->getElementType(), + ConstantSource->getSize(), + ArrayType::Normal, 0); + } + } + } + + break; + } + } + + // Diagnose non-fatal problems with the completed initialization. + if (Entity.getKind() == InitializedEntity::EK_Member && + cast<FieldDecl>(Entity.getDecl())->isBitField()) + S.CheckBitFieldInitialization(Kind.getLocation(), + cast<FieldDecl>(Entity.getDecl()), + CurInit.get()); + + return move(CurInit); +} + +//===----------------------------------------------------------------------===// +// Diagnose initialization failures +//===----------------------------------------------------------------------===// +bool InitializationSequence::Diagnose(Sema &S, + const InitializedEntity &Entity, + const InitializationKind &Kind, + Expr **Args, unsigned NumArgs) { + if (!Failed()) + return false; + + QualType DestType = Entity.getType(); + switch (Failure) { + case FK_TooManyInitsForReference: + // FIXME: Customize for the initialized entity? + if (NumArgs == 0) + S.Diag(Kind.getLocation(), diag::err_reference_without_init) + << DestType.getNonReferenceType(); + else // FIXME: diagnostic below could be better! + S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) + << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); + break; + + case FK_ArrayNeedsInitList: + case FK_ArrayNeedsInitListOrStringLiteral: + S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) + << (Failure == FK_ArrayNeedsInitListOrStringLiteral); + break; + + case FK_ArrayTypeMismatch: + case FK_NonConstantArrayInit: + S.Diag(Kind.getLocation(), + (Failure == FK_ArrayTypeMismatch + ? diag::err_array_init_different_type + : diag::err_array_init_non_constant_array)) + << DestType.getNonReferenceType() + << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_AddressOfOverloadFailed: { + DeclAccessPair Found; + S.ResolveAddressOfOverloadedFunction(Args[0], + DestType.getNonReferenceType(), + true, + Found); + break; + } + + case FK_ReferenceInitOverloadFailed: + case FK_UserConversionOverloadFailed: + switch (FailedOverloadResult) { + case OR_Ambiguous: + if (Failure == FK_UserConversionOverloadFailed) + S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) + << Args[0]->getType() << DestType + << Args[0]->getSourceRange(); + else + S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) + << DestType << Args[0]->getType() + << Args[0]->getSourceRange(); + + FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args, NumArgs); + break; + + case OR_No_Viable_Function: + S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) + << Args[0]->getType() << DestType.getNonReferenceType() + << Args[0]->getSourceRange(); + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs); + break; + + case OR_Deleted: { + S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) + << Args[0]->getType() << DestType.getNonReferenceType() + << Args[0]->getSourceRange(); + OverloadCandidateSet::iterator Best; + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best, + true); + if (Ovl == OR_Deleted) { + S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) + << Best->Function->isDeleted(); + } else { + llvm_unreachable("Inconsistent overload resolution?"); + } + break; + } + + case OR_Success: + llvm_unreachable("Conversion did not fail!"); + break; + } + break; + + case FK_NonConstLValueReferenceBindingToTemporary: + case FK_NonConstLValueReferenceBindingToUnrelated: + S.Diag(Kind.getLocation(), + Failure == FK_NonConstLValueReferenceBindingToTemporary + ? diag::err_lvalue_reference_bind_to_temporary + : diag::err_lvalue_reference_bind_to_unrelated) + << DestType.getNonReferenceType().isVolatileQualified() + << DestType.getNonReferenceType() + << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_RValueReferenceBindingToLValue: + S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref) + << DestType.getNonReferenceType() << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_ReferenceInitDropsQualifiers: + S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals) + << DestType.getNonReferenceType() + << Args[0]->getType() + << Args[0]->getSourceRange(); + break; + + case FK_ReferenceInitFailed: + S.Diag(Kind.getLocation(), diag::err_reference_bind_failed) + << DestType.getNonReferenceType() + << Args[0]->isLValue() + << Args[0]->getType() + << Args[0]->getSourceRange(); + if (DestType.getNonReferenceType()->isObjCObjectPointerType() && + Args[0]->getType()->isObjCObjectPointerType()) + S.EmitRelatedResultTypeNote(Args[0]); + break; + + case FK_ConversionFailed: { + QualType FromType = Args[0]->getType(); + S.Diag(Kind.getLocation(), diag::err_init_conversion_failed) + << (int)Entity.getKind() + << DestType + << Args[0]->isLValue() + << FromType + << Args[0]->getSourceRange(); + if (DestType.getNonReferenceType()->isObjCObjectPointerType() && + Args[0]->getType()->isObjCObjectPointerType()) + S.EmitRelatedResultTypeNote(Args[0]); + break; + } + + case FK_ConversionFromPropertyFailed: + // No-op. This error has already been reported. + break; + + case FK_TooManyInitsForScalar: { + SourceRange R; + + if (InitListExpr *InitList = dyn_cast<InitListExpr>(Args[0])) + R = SourceRange(InitList->getInit(0)->getLocEnd(), + InitList->getLocEnd()); + else + R = SourceRange(Args[0]->getLocEnd(), Args[NumArgs - 1]->getLocEnd()); + + R.setBegin(S.PP.getLocForEndOfToken(R.getBegin())); + if (Kind.isCStyleOrFunctionalCast()) + S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg) + << R; + else + S.Diag(Kind.getLocation(), diag::err_excess_initializers) + << /*scalar=*/2 << R; + break; + } + + case FK_ReferenceBindingToInitList: + S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list) + << DestType.getNonReferenceType() << Args[0]->getSourceRange(); + break; + + case FK_InitListBadDestinationType: + S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type) + << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange(); + break; + + case FK_ConstructorOverloadFailed: { + SourceRange ArgsRange; + if (NumArgs) + ArgsRange = SourceRange(Args[0]->getLocStart(), + Args[NumArgs - 1]->getLocEnd()); + + // FIXME: Using "DestType" for the entity we're printing is probably + // bad. + switch (FailedOverloadResult) { + case OR_Ambiguous: + S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) + << DestType << ArgsRange; + FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, + Args, NumArgs); + break; + + case OR_No_Viable_Function: + if (Kind.getKind() == InitializationKind::IK_Default && + (Entity.getKind() == InitializedEntity::EK_Base || + Entity.getKind() == InitializedEntity::EK_Member) && + isa<CXXConstructorDecl>(S.CurContext)) { + // This is implicit default initialization of a member or + // base within a constructor. If no viable function was + // found, notify the user that she needs to explicitly + // initialize this base/member. + CXXConstructorDecl *Constructor + = cast<CXXConstructorDecl>(S.CurContext); + if (Entity.getKind() == InitializedEntity::EK_Base) { + S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*base=*/0 + << Entity.getType(); + + RecordDecl *BaseDecl + = Entity.getBaseSpecifier()->getType()->getAs<RecordType>() + ->getDecl(); + S.Diag(BaseDecl->getLocation(), diag::note_previous_decl) + << S.Context.getTagDeclType(BaseDecl); + } else { + S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*member=*/1 + << Entity.getName(); + S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl); + + if (const RecordType *Record + = Entity.getType()->getAs<RecordType>()) + S.Diag(Record->getDecl()->getLocation(), + diag::note_previous_decl) + << S.Context.getTagDeclType(Record->getDecl()); + } + break; + } + + S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) + << DestType << ArgsRange; + FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args, NumArgs); + break; + + case OR_Deleted: { + S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init) + << true << DestType << ArgsRange; + OverloadCandidateSet::iterator Best; + OverloadingResult Ovl + = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best); + if (Ovl == OR_Deleted) { + S.Diag(Best->Function->getLocation(), diag::note_unavailable_here) + << Best->Function->isDeleted(); + } else { + llvm_unreachable("Inconsistent overload resolution?"); + } + break; + } + + case OR_Success: + llvm_unreachable("Conversion did not fail!"); + break; + } + break; + } + + case FK_DefaultInitOfConst: + if (Entity.getKind() == InitializedEntity::EK_Member && + isa<CXXConstructorDecl>(S.CurContext)) { + // This is implicit default-initialization of a const member in + // a constructor. Complain that it needs to be explicitly + // initialized. + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext); + S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*const=*/1 + << Entity.getName(); + S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl) + << Entity.getName(); + } else { + S.Diag(Kind.getLocation(), diag::err_default_init_const) + << DestType << (bool)DestType->getAs<RecordType>(); + } + break; + + case FK_Incomplete: + S.RequireCompleteType(Kind.getLocation(), DestType, + diag::err_init_incomplete_type); + break; + } + + PrintInitLocationNote(S, Entity); + return true; +} + +void InitializationSequence::dump(llvm::raw_ostream &OS) const { + switch (SequenceKind) { + case FailedSequence: { + OS << "Failed sequence: "; + switch (Failure) { + case FK_TooManyInitsForReference: + OS << "too many initializers for reference"; + break; + + case FK_ArrayNeedsInitList: + OS << "array requires initializer list"; + break; + + case FK_ArrayNeedsInitListOrStringLiteral: + OS << "array requires initializer list or string literal"; + break; + + case FK_ArrayTypeMismatch: + OS << "array type mismatch"; + break; + + case FK_NonConstantArrayInit: + OS << "non-constant array initializer"; + break; + + case FK_AddressOfOverloadFailed: + OS << "address of overloaded function failed"; + break; + + case FK_ReferenceInitOverloadFailed: + OS << "overload resolution for reference initialization failed"; + break; + + case FK_NonConstLValueReferenceBindingToTemporary: + OS << "non-const lvalue reference bound to temporary"; + break; + + case FK_NonConstLValueReferenceBindingToUnrelated: + OS << "non-const lvalue reference bound to unrelated type"; + break; + + case FK_RValueReferenceBindingToLValue: + OS << "rvalue reference bound to an lvalue"; + break; + + case FK_ReferenceInitDropsQualifiers: + OS << "reference initialization drops qualifiers"; + break; + + case FK_ReferenceInitFailed: + OS << "reference initialization failed"; + break; + + case FK_ConversionFailed: + OS << "conversion failed"; + break; + + case FK_ConversionFromPropertyFailed: + OS << "conversion from property failed"; + break; + + case FK_TooManyInitsForScalar: + OS << "too many initializers for scalar"; + break; + + case FK_ReferenceBindingToInitList: + OS << "referencing binding to initializer list"; + break; + + case FK_InitListBadDestinationType: + OS << "initializer list for non-aggregate, non-scalar type"; + break; + + case FK_UserConversionOverloadFailed: + OS << "overloading failed for user-defined conversion"; + break; + + case FK_ConstructorOverloadFailed: + OS << "constructor overloading failed"; + break; + + case FK_DefaultInitOfConst: + OS << "default initialization of a const variable"; + break; + + case FK_Incomplete: + OS << "initialization of incomplete type"; + break; + } + OS << '\n'; + return; + } + + case DependentSequence: + OS << "Dependent sequence\n"; + return; + + case NormalSequence: + OS << "Normal sequence: "; + break; + + case ReferenceBinding: + OS << "Reference binding: "; + break; + } + + for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) { + if (S != step_begin()) { + OS << " -> "; + } + + switch (S->Kind) { + case SK_ResolveAddressOfOverloadedFunction: + OS << "resolve address of overloaded function"; + break; + + case SK_CastDerivedToBaseRValue: + OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")"; + break; + + case SK_CastDerivedToBaseXValue: + OS << "derived-to-base case (xvalue" << S->Type.getAsString() << ")"; + break; + + case SK_CastDerivedToBaseLValue: + OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")"; + break; + + case SK_BindReference: + OS << "bind reference to lvalue"; + break; + + case SK_BindReferenceToTemporary: + OS << "bind reference to a temporary"; + break; + + case SK_ExtraneousCopyToTemporary: + OS << "extraneous C++03 copy to temporary"; + break; + + case SK_UserConversion: + OS << "user-defined conversion via " << S->Function.Function; + break; + + case SK_QualificationConversionRValue: + OS << "qualification conversion (rvalue)"; + + case SK_QualificationConversionXValue: + OS << "qualification conversion (xvalue)"; + + case SK_QualificationConversionLValue: + OS << "qualification conversion (lvalue)"; + break; + + case SK_ConversionSequence: + OS << "implicit conversion sequence ("; + S->ICS->DebugPrint(); // FIXME: use OS + OS << ")"; + break; + + case SK_ListInitialization: + OS << "list initialization"; + break; + + case SK_ConstructorInitialization: + OS << "constructor initialization"; + break; + + case SK_ZeroInitialization: + OS << "zero initialization"; + break; + + case SK_CAssignment: + OS << "C assignment"; + break; + + case SK_StringInit: + OS << "string initialization"; + break; + + case SK_ObjCObjectConversion: + OS << "Objective-C object conversion"; + break; + + case SK_ArrayInit: + OS << "array initialization"; + break; + } + } +} + +void InitializationSequence::dump() const { + dump(llvm::errs()); +} + +//===----------------------------------------------------------------------===// +// Initialization helper functions +//===----------------------------------------------------------------------===// +bool +Sema::CanPerformCopyInitialization(const InitializedEntity &Entity, + ExprResult Init) { + if (Init.isInvalid()) + return false; + + Expr *InitE = Init.get(); + assert(InitE && "No initialization expression"); + + InitializationKind Kind = InitializationKind::CreateCopy(SourceLocation(), + SourceLocation()); + InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); + return !Seq.Failed(); +} + +ExprResult +Sema::PerformCopyInitialization(const InitializedEntity &Entity, + SourceLocation EqualLoc, + ExprResult Init) { + if (Init.isInvalid()) + return ExprError(); + + Expr *InitE = Init.get(); + assert(InitE && "No initialization expression?"); + + if (EqualLoc.isInvalid()) + EqualLoc = InitE->getLocStart(); + + InitializationKind Kind = InitializationKind::CreateCopy(InitE->getLocStart(), + EqualLoc); + InitializationSequence Seq(*this, Entity, Kind, &InitE, 1); + Init.release(); + return Seq.Perform(*this, Entity, Kind, MultiExprArg(&InitE, 1)); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp new file mode 100644 index 0000000..92ade1e --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -0,0 +1,3580 @@ +//===--------------------- SemaLookup.cpp - Name Lookup ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements name lookup for C, C++, Objective-C, and +// Objective-C++. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Basic/Builtins.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include <limits> +#include <list> +#include <set> +#include <vector> +#include <iterator> +#include <utility> +#include <algorithm> + +using namespace clang; +using namespace sema; + +namespace { + class UnqualUsingEntry { + const DeclContext *Nominated; + const DeclContext *CommonAncestor; + + public: + UnqualUsingEntry(const DeclContext *Nominated, + const DeclContext *CommonAncestor) + : Nominated(Nominated), CommonAncestor(CommonAncestor) { + } + + const DeclContext *getCommonAncestor() const { + return CommonAncestor; + } + + const DeclContext *getNominatedNamespace() const { + return Nominated; + } + + // Sort by the pointer value of the common ancestor. + struct Comparator { + bool operator()(const UnqualUsingEntry &L, const UnqualUsingEntry &R) { + return L.getCommonAncestor() < R.getCommonAncestor(); + } + + bool operator()(const UnqualUsingEntry &E, const DeclContext *DC) { + return E.getCommonAncestor() < DC; + } + + bool operator()(const DeclContext *DC, const UnqualUsingEntry &E) { + return DC < E.getCommonAncestor(); + } + }; + }; + + /// A collection of using directives, as used by C++ unqualified + /// lookup. + class UnqualUsingDirectiveSet { + typedef llvm::SmallVector<UnqualUsingEntry, 8> ListTy; + + ListTy list; + llvm::SmallPtrSet<DeclContext*, 8> visited; + + public: + UnqualUsingDirectiveSet() {} + + void visitScopeChain(Scope *S, Scope *InnermostFileScope) { + // C++ [namespace.udir]p1: + // During unqualified name lookup, the names appear as if they + // were declared in the nearest enclosing namespace which contains + // both the using-directive and the nominated namespace. + DeclContext *InnermostFileDC + = static_cast<DeclContext*>(InnermostFileScope->getEntity()); + assert(InnermostFileDC && InnermostFileDC->isFileContext()); + + for (; S; S = S->getParent()) { + if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) { + DeclContext *EffectiveDC = (Ctx->isFileContext() ? Ctx : InnermostFileDC); + visit(Ctx, EffectiveDC); + } else { + Scope::udir_iterator I = S->using_directives_begin(), + End = S->using_directives_end(); + + for (; I != End; ++I) + visit(*I, InnermostFileDC); + } + } + } + + // Visits a context and collect all of its using directives + // recursively. Treats all using directives as if they were + // declared in the context. + // + // A given context is only every visited once, so it is important + // that contexts be visited from the inside out in order to get + // the effective DCs right. + void visit(DeclContext *DC, DeclContext *EffectiveDC) { + if (!visited.insert(DC)) + return; + + addUsingDirectives(DC, EffectiveDC); + } + + // Visits a using directive and collects all of its using + // directives recursively. Treats all using directives as if they + // were declared in the effective DC. + void visit(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { + DeclContext *NS = UD->getNominatedNamespace(); + if (!visited.insert(NS)) + return; + + addUsingDirective(UD, EffectiveDC); + addUsingDirectives(NS, EffectiveDC); + } + + // Adds all the using directives in a context (and those nominated + // by its using directives, transitively) as if they appeared in + // the given effective context. + void addUsingDirectives(DeclContext *DC, DeclContext *EffectiveDC) { + llvm::SmallVector<DeclContext*,4> queue; + while (true) { + DeclContext::udir_iterator I, End; + for (llvm::tie(I, End) = DC->getUsingDirectives(); I != End; ++I) { + UsingDirectiveDecl *UD = *I; + DeclContext *NS = UD->getNominatedNamespace(); + if (visited.insert(NS)) { + addUsingDirective(UD, EffectiveDC); + queue.push_back(NS); + } + } + + if (queue.empty()) + return; + + DC = queue.back(); + queue.pop_back(); + } + } + + // Add a using directive as if it had been declared in the given + // context. This helps implement C++ [namespace.udir]p3: + // The using-directive is transitive: if a scope contains a + // using-directive that nominates a second namespace that itself + // contains using-directives, the effect is as if the + // using-directives from the second namespace also appeared in + // the first. + void addUsingDirective(UsingDirectiveDecl *UD, DeclContext *EffectiveDC) { + // Find the common ancestor between the effective context and + // the nominated namespace. + DeclContext *Common = UD->getNominatedNamespace(); + while (!Common->Encloses(EffectiveDC)) + Common = Common->getParent(); + Common = Common->getPrimaryContext(); + + list.push_back(UnqualUsingEntry(UD->getNominatedNamespace(), Common)); + } + + void done() { + std::sort(list.begin(), list.end(), UnqualUsingEntry::Comparator()); + } + + typedef ListTy::const_iterator const_iterator; + + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } + + std::pair<const_iterator,const_iterator> + getNamespacesFor(DeclContext *DC) const { + return std::equal_range(begin(), end(), DC->getPrimaryContext(), + UnqualUsingEntry::Comparator()); + } + }; +} + +// Retrieve the set of identifier namespaces that correspond to a +// specific kind of name lookup. +static inline unsigned getIDNS(Sema::LookupNameKind NameKind, + bool CPlusPlus, + bool Redeclaration) { + unsigned IDNS = 0; + switch (NameKind) { + case Sema::LookupOrdinaryName: + case Sema::LookupRedeclarationWithLinkage: + IDNS = Decl::IDNS_Ordinary; + if (CPlusPlus) { + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member | Decl::IDNS_Namespace; + if (Redeclaration) + IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend; + } + break; + + case Sema::LookupOperatorName: + // Operator lookup is its own crazy thing; it is not the same + // as (e.g.) looking up an operator name for redeclaration. + assert(!Redeclaration && "cannot do redeclaration operator lookup"); + IDNS = Decl::IDNS_NonMemberOperator; + break; + + case Sema::LookupTagName: + if (CPlusPlus) { + IDNS = Decl::IDNS_Type; + + // When looking for a redeclaration of a tag name, we add: + // 1) TagFriend to find undeclared friend decls + // 2) Namespace because they can't "overload" with tag decls. + // 3) Tag because it includes class templates, which can't + // "overload" with tag decls. + if (Redeclaration) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_TagFriend | Decl::IDNS_Namespace; + } else { + IDNS = Decl::IDNS_Tag; + } + break; + case Sema::LookupLabel: + IDNS = Decl::IDNS_Label; + break; + + case Sema::LookupMemberName: + IDNS = Decl::IDNS_Member; + if (CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary; + break; + + case Sema::LookupNestedNameSpecifierName: + IDNS = Decl::IDNS_Type | Decl::IDNS_Namespace; + break; + + case Sema::LookupNamespaceName: + IDNS = Decl::IDNS_Namespace; + break; + + case Sema::LookupUsingDeclName: + IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag + | Decl::IDNS_Member | Decl::IDNS_Using; + break; + + case Sema::LookupObjCProtocolName: + IDNS = Decl::IDNS_ObjCProtocol; + break; + + case Sema::LookupAnyName: + IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member + | Decl::IDNS_Using | Decl::IDNS_Namespace | Decl::IDNS_ObjCProtocol + | Decl::IDNS_Type; + break; + } + return IDNS; +} + +void LookupResult::configure() { + IDNS = getIDNS(LookupKind, SemaRef.getLangOptions().CPlusPlus, + isForRedeclaration()); + + // If we're looking for one of the allocation or deallocation + // operators, make sure that the implicitly-declared new and delete + // operators can be found. + if (!isForRedeclaration()) { + switch (NameInfo.getName().getCXXOverloadedOperator()) { + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + SemaRef.DeclareGlobalNewDelete(); + break; + + default: + break; + } + } +} + +void LookupResult::sanity() const { + assert(ResultKind != NotFound || Decls.size() == 0); + assert(ResultKind != Found || Decls.size() == 1); + assert(ResultKind != FoundOverloaded || Decls.size() > 1 || + (Decls.size() == 1 && + isa<FunctionTemplateDecl>((*begin())->getUnderlyingDecl()))); + assert(ResultKind != FoundUnresolvedValue || sanityCheckUnresolved()); + assert(ResultKind != Ambiguous || Decls.size() > 1 || + (Decls.size() == 1 && (Ambiguity == AmbiguousBaseSubobjects || + Ambiguity == AmbiguousBaseSubobjectTypes))); + assert((Paths != NULL) == (ResultKind == Ambiguous && + (Ambiguity == AmbiguousBaseSubobjectTypes || + Ambiguity == AmbiguousBaseSubobjects))); +} + +// Necessary because CXXBasePaths is not complete in Sema.h +void LookupResult::deletePaths(CXXBasePaths *Paths) { + delete Paths; +} + +/// Resolves the result kind of this lookup. +void LookupResult::resolveKind() { + unsigned N = Decls.size(); + + // Fast case: no possible ambiguity. + if (N == 0) { + assert(ResultKind == NotFound || ResultKind == NotFoundInCurrentInstantiation); + return; + } + + // If there's a single decl, we need to examine it to decide what + // kind of lookup this is. + if (N == 1) { + NamedDecl *D = (*Decls.begin())->getUnderlyingDecl(); + if (isa<FunctionTemplateDecl>(D)) + ResultKind = FoundOverloaded; + else if (isa<UnresolvedUsingValueDecl>(D)) + ResultKind = FoundUnresolvedValue; + return; + } + + // Don't do any extra resolution if we've already resolved as ambiguous. + if (ResultKind == Ambiguous) return; + + llvm::SmallPtrSet<NamedDecl*, 16> Unique; + llvm::SmallPtrSet<QualType, 16> UniqueTypes; + + bool Ambiguous = false; + bool HasTag = false, HasFunction = false, HasNonFunction = false; + bool HasFunctionTemplate = false, HasUnresolved = false; + + unsigned UniqueTagIndex = 0; + + unsigned I = 0; + while (I < N) { + NamedDecl *D = Decls[I]->getUnderlyingDecl(); + D = cast<NamedDecl>(D->getCanonicalDecl()); + + // Redeclarations of types via typedef can occur both within a scope + // and, through using declarations and directives, across scopes. There is + // no ambiguity if they all refer to the same type, so unique based on the + // canonical type. + if (TypeDecl *TD = dyn_cast<TypeDecl>(D)) { + if (!TD->getDeclContext()->isRecord()) { + QualType T = SemaRef.Context.getTypeDeclType(TD); + if (!UniqueTypes.insert(SemaRef.Context.getCanonicalType(T))) { + // The type is not unique; pull something off the back and continue + // at this index. + Decls[I] = Decls[--N]; + continue; + } + } + } + + if (!Unique.insert(D)) { + // If it's not unique, pull something off the back (and + // continue at this index). + Decls[I] = Decls[--N]; + continue; + } + + // Otherwise, do some decl type analysis and then continue. + + if (isa<UnresolvedUsingValueDecl>(D)) { + HasUnresolved = true; + } else if (isa<TagDecl>(D)) { + if (HasTag) + Ambiguous = true; + UniqueTagIndex = I; + HasTag = true; + } else if (isa<FunctionTemplateDecl>(D)) { + HasFunction = true; + HasFunctionTemplate = true; + } else if (isa<FunctionDecl>(D)) { + HasFunction = true; + } else { + if (HasNonFunction) + Ambiguous = true; + HasNonFunction = true; + } + I++; + } + + // C++ [basic.scope.hiding]p2: + // A class name or enumeration name can be hidden by the name of + // an object, function, or enumerator declared in the same + // scope. If a class or enumeration name and an object, function, + // or enumerator are declared in the same scope (in any order) + // with the same name, the class or enumeration name is hidden + // wherever the object, function, or enumerator name is visible. + // But it's still an error if there are distinct tag types found, + // even if they're not visible. (ref?) + if (HideTags && HasTag && !Ambiguous && + (HasFunction || HasNonFunction || HasUnresolved)) { + if (Decls[UniqueTagIndex]->getDeclContext()->getRedeclContext()->Equals( + Decls[UniqueTagIndex? 0 : N-1]->getDeclContext()->getRedeclContext())) + Decls[UniqueTagIndex] = Decls[--N]; + else + Ambiguous = true; + } + + Decls.set_size(N); + + if (HasNonFunction && (HasFunction || HasUnresolved)) + Ambiguous = true; + + if (Ambiguous) + setAmbiguous(LookupResult::AmbiguousReference); + else if (HasUnresolved) + ResultKind = LookupResult::FoundUnresolvedValue; + else if (N > 1 || HasFunctionTemplate) + ResultKind = LookupResult::FoundOverloaded; + else + ResultKind = LookupResult::Found; +} + +void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { + CXXBasePaths::const_paths_iterator I, E; + DeclContext::lookup_iterator DI, DE; + for (I = P.begin(), E = P.end(); I != E; ++I) + for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI) + addDecl(*DI); +} + +void LookupResult::setAmbiguousBaseSubobjects(CXXBasePaths &P) { + Paths = new CXXBasePaths; + Paths->swap(P); + addDeclsFromBasePaths(*Paths); + resolveKind(); + setAmbiguous(AmbiguousBaseSubobjects); +} + +void LookupResult::setAmbiguousBaseSubobjectTypes(CXXBasePaths &P) { + Paths = new CXXBasePaths; + Paths->swap(P); + addDeclsFromBasePaths(*Paths); + resolveKind(); + setAmbiguous(AmbiguousBaseSubobjectTypes); +} + +void LookupResult::print(llvm::raw_ostream &Out) { + Out << Decls.size() << " result(s)"; + if (isAmbiguous()) Out << ", ambiguous"; + if (Paths) Out << ", base paths present"; + + for (iterator I = begin(), E = end(); I != E; ++I) { + Out << "\n"; + (*I)->print(Out, 2); + } +} + +/// \brief Lookup a builtin function, when name lookup would otherwise +/// fail. +static bool LookupBuiltin(Sema &S, LookupResult &R) { + Sema::LookupNameKind NameKind = R.getLookupKind(); + + // If we didn't find a use of this identifier, and if the identifier + // corresponds to a compiler builtin, create the decl object for the builtin + // now, injecting it into translation unit scope, and return it. + if (NameKind == Sema::LookupOrdinaryName || + NameKind == Sema::LookupRedeclarationWithLinkage) { + IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); + if (II) { + // If this is a builtin on this (or all) targets, create the decl. + if (unsigned BuiltinID = II->getBuiltinID()) { + // In C++, we don't have any predefined library functions like + // 'malloc'. Instead, we'll just error. + if (S.getLangOptions().CPlusPlus && + S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return false; + + if (NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, + BuiltinID, S.TUScope, + R.isForRedeclaration(), + R.getNameLoc())) { + R.addDecl(D); + return true; + } + + if (R.isForRedeclaration()) { + // If we're redeclaring this function anyway, forget that + // this was a builtin at all. + S.Context.BuiltinInfo.ForgetBuiltin(BuiltinID, S.Context.Idents); + } + + return false; + } + } + } + + return false; +} + +/// \brief Determine whether we can declare a special member function within +/// the class at this point. +static bool CanDeclareSpecialMemberFunction(ASTContext &Context, + const CXXRecordDecl *Class) { + // Don't do it if the class is invalid. + if (Class->isInvalidDecl()) + return false; + + // We need to have a definition for the class. + if (!Class->getDefinition() || Class->isDependentContext()) + return false; + + // We can't be in the middle of defining the class. + if (const RecordType *RecordTy + = Context.getTypeDeclType(Class)->getAs<RecordType>()) + return !RecordTy->isBeingDefined(); + + return false; +} + +void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { + if (!CanDeclareSpecialMemberFunction(Context, Class)) + return; + + // If the default constructor has not yet been declared, do so now. + if (Class->needsImplicitDefaultConstructor()) + DeclareImplicitDefaultConstructor(Class); + + // If the copy constructor has not yet been declared, do so now. + if (!Class->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(Class); + + // If the copy assignment operator has not yet been declared, do so now. + if (!Class->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(Class); + + // If the destructor has not yet been declared, do so now. + if (!Class->hasDeclaredDestructor()) + DeclareImplicitDestructor(Class); +} + +/// \brief Determine whether this is the name of an implicitly-declared +/// special member function. +static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) { + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + return true; + + case DeclarationName::CXXOperatorName: + return Name.getCXXOverloadedOperator() == OO_Equal; + + default: + break; + } + + return false; +} + +/// \brief If there are any implicit member functions with the given name +/// that need to be declared in the given declaration context, do so. +static void DeclareImplicitMemberFunctionsWithName(Sema &S, + DeclarationName Name, + const DeclContext *DC) { + if (!DC) + return; + + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getDefinition() && + CanDeclareSpecialMemberFunction(S.Context, Record)) { + if (Record->needsImplicitDefaultConstructor()) + S.DeclareImplicitDefaultConstructor( + const_cast<CXXRecordDecl *>(Record)); + if (!Record->hasDeclaredCopyConstructor()) + S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record)); + } + break; + + case DeclarationName::CXXDestructorName: + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getDefinition() && !Record->hasDeclaredDestructor() && + CanDeclareSpecialMemberFunction(S.Context, Record)) + S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record)); + break; + + case DeclarationName::CXXOperatorName: + if (Name.getCXXOverloadedOperator() != OO_Equal) + break; + + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getDefinition() && !Record->hasDeclaredCopyAssignment() && + CanDeclareSpecialMemberFunction(S.Context, Record)) + S.DeclareImplicitCopyAssignment(const_cast<CXXRecordDecl *>(Record)); + break; + + default: + break; + } +} + +// Adds all qualifying matches for a name within a decl context to the +// given lookup result. Returns true if any matches were found. +static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { + bool Found = false; + + // Lazily declare C++ special member functions. + if (S.getLangOptions().CPlusPlus) + DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC); + + // Perform lookup into this declaration context. + DeclContext::lookup_const_iterator I, E; + for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) { + NamedDecl *D = *I; + if (R.isAcceptableDecl(D)) { + R.addDecl(D); + Found = true; + } + } + + if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R)) + return true; + + if (R.getLookupName().getNameKind() + != DeclarationName::CXXConversionFunctionName || + R.getLookupName().getCXXNameType()->isDependentType() || + !isa<CXXRecordDecl>(DC)) + return Found; + + // C++ [temp.mem]p6: + // A specialization of a conversion function template is not found by + // name lookup. Instead, any conversion function templates visible in the + // context of the use are considered. [...] + const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); + if (!Record->isDefinition()) + return Found; + + const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions(); + for (UnresolvedSetImpl::iterator U = Unresolved->begin(), + UEnd = Unresolved->end(); U != UEnd; ++U) { + FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U); + if (!ConvTemplate) + continue; + + // When we're performing lookup for the purposes of redeclaration, just + // add the conversion function template. When we deduce template + // arguments for specializations, we'll end up unifying the return + // type of the new declaration with the type of the function template. + if (R.isForRedeclaration()) { + R.addDecl(ConvTemplate); + Found = true; + continue; + } + + // C++ [temp.mem]p6: + // [...] For each such operator, if argument deduction succeeds + // (14.9.2.3), the resulting specialization is used as if found by + // name lookup. + // + // When referencing a conversion function for any purpose other than + // a redeclaration (such that we'll be building an expression with the + // result), perform template argument deduction and place the + // specialization into the result set. We do this to avoid forcing all + // callers to perform special deduction for conversion functions. + TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc()); + FunctionDecl *Specialization = 0; + + const FunctionProtoType *ConvProto + = ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>(); + assert(ConvProto && "Nonsensical conversion function template type"); + + // Compute the type of the function that we would expect the conversion + // function to have, if it were to match the name given. + // FIXME: Calling convention! + FunctionProtoType::ExtProtoInfo EPI = ConvProto->getExtProtoInfo(); + EPI.ExtInfo = EPI.ExtInfo.withCallingConv(CC_Default); + EPI.ExceptionSpecType = EST_None; + EPI.NumExceptions = 0; + QualType ExpectedType + = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), + 0, 0, EPI); + + // Perform template argument deduction against the type that we would + // expect the function to have. + if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType, + Specialization, Info) + == Sema::TDK_Success) { + R.addDecl(Specialization); + Found = true; + } + } + + return Found; +} + +// Performs C++ unqualified lookup into the given file context. +static bool +CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, + DeclContext *NS, UnqualUsingDirectiveSet &UDirs) { + + assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!"); + + // Perform direct name lookup into the LookupCtx. + bool Found = LookupDirect(S, R, NS); + + // Perform direct name lookup into the namespaces nominated by the + // using directives whose common ancestor is this namespace. + UnqualUsingDirectiveSet::const_iterator UI, UEnd; + llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS); + + for (; UI != UEnd; ++UI) + if (LookupDirect(S, R, UI->getNominatedNamespace())) + Found = true; + + R.resolveKind(); + + return Found; +} + +static bool isNamespaceOrTranslationUnitScope(Scope *S) { + if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) + return Ctx->isFileContext(); + return false; +} + +// Find the next outer declaration context from this scope. This +// routine actually returns the semantic outer context, which may +// differ from the lexical context (encoded directly in the Scope +// stack) when we are parsing a member of a class template. In this +// case, the second element of the pair will be true, to indicate that +// name lookup should continue searching in this semantic context when +// it leaves the current template parameter scope. +static std::pair<DeclContext *, bool> findOuterContext(Scope *S) { + DeclContext *DC = static_cast<DeclContext *>(S->getEntity()); + DeclContext *Lexical = 0; + for (Scope *OuterS = S->getParent(); OuterS; + OuterS = OuterS->getParent()) { + if (OuterS->getEntity()) { + Lexical = static_cast<DeclContext *>(OuterS->getEntity()); + break; + } + } + + // C++ [temp.local]p8: + // In the definition of a member of a class template that appears + // outside of the namespace containing the class template + // definition, the name of a template-parameter hides the name of + // a member of this namespace. + // + // Example: + // + // namespace N { + // class C { }; + // + // template<class T> class B { + // void f(T); + // }; + // } + // + // template<class C> void N::B<C>::f(C) { + // C b; // C is the template parameter, not N::C + // } + // + // In this example, the lexical context we return is the + // TranslationUnit, while the semantic context is the namespace N. + if (!Lexical || !DC || !S->getParent() || + !S->getParent()->isTemplateParamScope()) + return std::make_pair(Lexical, false); + + // Find the outermost template parameter scope. + // For the example, this is the scope for the template parameters of + // template<class C>. + Scope *OutermostTemplateScope = S->getParent(); + while (OutermostTemplateScope->getParent() && + OutermostTemplateScope->getParent()->isTemplateParamScope()) + OutermostTemplateScope = OutermostTemplateScope->getParent(); + + // Find the namespace context in which the original scope occurs. In + // the example, this is namespace N. + DeclContext *Semantic = DC; + while (!Semantic->isFileContext()) + Semantic = Semantic->getParent(); + + // Find the declaration context just outside of the template + // parameter scope. This is the context in which the template is + // being lexically declaration (a namespace context). In the + // example, this is the global scope. + if (Lexical->isFileContext() && !Lexical->Equals(Semantic) && + Lexical->Encloses(Semantic)) + return std::make_pair(Semantic, true); + + return std::make_pair(Lexical, false); +} + +bool Sema::CppLookupName(LookupResult &R, Scope *S) { + assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup"); + + DeclarationName Name = R.getLookupName(); + + // If this is the name of an implicitly-declared special member function, + // go through the scope stack to implicitly declare + if (isImplicitlyDeclaredMemberFunctionName(Name)) { + for (Scope *PreS = S; PreS; PreS = PreS->getParent()) + if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity())) + DeclareImplicitMemberFunctionsWithName(*this, Name, DC); + } + + // Implicitly declare member functions with the name we're looking for, if in + // fact we are in a scope where it matters. + + Scope *Initial = S; + IdentifierResolver::iterator + I = IdResolver.begin(Name), + IEnd = IdResolver.end(); + + // First we lookup local scope. + // We don't consider using-directives, as per 7.3.4.p1 [namespace.udir] + // ...During unqualified name lookup (3.4.1), the names appear as if + // they were declared in the nearest enclosing namespace which contains + // both the using-directive and the nominated namespace. + // [Note: in this context, "contains" means "contains directly or + // indirectly". + // + // For example: + // namespace A { int i; } + // void foo() { + // int i; + // { + // using namespace A; + // ++i; // finds local 'i', A::i appears at global scope + // } + // } + // + DeclContext *OutsideOfTemplateParamDC = 0; + for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) { + DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + + // Check whether the IdResolver has anything in this scope. + bool Found = false; + for (; I != IEnd && S->isDeclScope(*I); ++I) { + if (R.isAcceptableDecl(*I)) { + Found = true; + R.addDecl(*I); + } + } + if (Found) { + R.resolveKind(); + if (S->isClassScope()) + if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx)) + R.setNamingClass(Record); + return true; + } + + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && + S->getParent() && !S->getParent()->isTemplateParamScope()) { + // We've just searched the last template parameter scope and + // found nothing, so look into the the contexts between the + // lexical and semantic declaration contexts returned by + // findOuterContext(). This implements the name lookup behavior + // of C++ [temp.local]p8. + Ctx = OutsideOfTemplateParamDC; + OutsideOfTemplateParamDC = 0; + } + + if (Ctx) { + DeclContext *OuterCtx; + bool SearchAfterTemplateScope; + llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S); + if (SearchAfterTemplateScope) + OutsideOfTemplateParamDC = OuterCtx; + + for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { + // We do not directly look into transparent contexts, since + // those entities will be found in the nearest enclosing + // non-transparent context. + if (Ctx->isTransparentContext()) + continue; + + // We do not look directly into function or method contexts, + // since all of the local variables and parameters of the + // function/method are present within the Scope. + if (Ctx->isFunctionOrMethod()) { + // If we have an Objective-C instance method, look for ivars + // in the corresponding interface. + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) { + if (Method->isInstanceMethod() && Name.getAsIdentifierInfo()) + if (ObjCInterfaceDecl *Class = Method->getClassInterface()) { + ObjCInterfaceDecl *ClassDeclared; + if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable( + Name.getAsIdentifierInfo(), + ClassDeclared)) { + if (R.isAcceptableDecl(Ivar)) { + R.addDecl(Ivar); + R.resolveKind(); + return true; + } + } + } + } + + continue; + } + + // Perform qualified name lookup into this context. + // FIXME: In some cases, we know that every name that could be found by + // this qualified name lookup will also be on the identifier chain. For + // example, inside a class without any base classes, we never need to + // perform qualified lookup because all of the members are on top of the + // identifier chain. + if (LookupQualifiedName(R, Ctx, /*InUnqualifiedLookup=*/true)) + return true; + } + } + } + + // Stop if we ran out of scopes. + // FIXME: This really, really shouldn't be happening. + if (!S) return false; + + // If we are looking for members, no need to look into global/namespace scope. + if (R.getLookupKind() == LookupMemberName) + return false; + + // Collect UsingDirectiveDecls in all scopes, and recursively all + // nominated namespaces by those using-directives. + // + // FIXME: Cache this sorted list in Scope structure, and DeclContext, so we + // don't build it for each lookup! + + UnqualUsingDirectiveSet UDirs; + UDirs.visitScopeChain(Initial, S); + UDirs.done(); + + // Lookup namespace scope, and global scope. + // Unqualified name lookup in C++ requires looking into scopes + // that aren't strictly lexical, and therefore we walk through the + // context as well as walking through the scopes. + + for (; S; S = S->getParent()) { + // Check whether the IdResolver has anything in this scope. + bool Found = false; + for (; I != IEnd && S->isDeclScope(*I); ++I) { + if (R.isAcceptableDecl(*I)) { + // We found something. Look for anything else in our scope + // with this same name and in an acceptable identifier + // namespace, so that we can construct an overload set if we + // need to. + Found = true; + R.addDecl(*I); + } + } + + if (Found && S->isTemplateParamScope()) { + R.resolveKind(); + return true; + } + + DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); + if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC && + S->getParent() && !S->getParent()->isTemplateParamScope()) { + // We've just searched the last template parameter scope and + // found nothing, so look into the the contexts between the + // lexical and semantic declaration contexts returned by + // findOuterContext(). This implements the name lookup behavior + // of C++ [temp.local]p8. + Ctx = OutsideOfTemplateParamDC; + OutsideOfTemplateParamDC = 0; + } + + if (Ctx) { + DeclContext *OuterCtx; + bool SearchAfterTemplateScope; + llvm::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S); + if (SearchAfterTemplateScope) + OutsideOfTemplateParamDC = OuterCtx; + + for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) { + // We do not directly look into transparent contexts, since + // those entities will be found in the nearest enclosing + // non-transparent context. + if (Ctx->isTransparentContext()) + continue; + + // If we have a context, and it's not a context stashed in the + // template parameter scope for an out-of-line definition, also + // look into that context. + if (!(Found && S && S->isTemplateParamScope())) { + assert(Ctx->isFileContext() && + "We should have been looking only at file context here already."); + + // Look into context considering using-directives. + if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) + Found = true; + } + + if (Found) { + R.resolveKind(); + return true; + } + + if (R.isForRedeclaration() && !Ctx->isTransparentContext()) + return false; + } + } + + if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext()) + return false; + } + + return !R.empty(); +} + +/// @brief Perform unqualified name lookup starting from a given +/// scope. +/// +/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is +/// used to find names within the current scope. For example, 'x' in +/// @code +/// int x; +/// int f() { +/// return x; // unqualified name look finds 'x' in the global scope +/// } +/// @endcode +/// +/// Different lookup criteria can find different names. For example, a +/// particular scope can have both a struct and a function of the same +/// name, and each can be found by certain lookup criteria. For more +/// information about lookup criteria, see the documentation for the +/// class LookupCriteria. +/// +/// @param S The scope from which unqualified name lookup will +/// begin. If the lookup criteria permits, name lookup may also search +/// in the parent scopes. +/// +/// @param Name The name of the entity that we are searching for. +/// +/// @param Loc If provided, the source location where we're performing +/// name lookup. At present, this is only used to produce diagnostics when +/// C library functions (like "malloc") are implicitly declared. +/// +/// @returns The result of name lookup, which includes zero or more +/// declarations and possibly additional information used to diagnose +/// ambiguities. +bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { + DeclarationName Name = R.getLookupName(); + if (!Name) return false; + + LookupNameKind NameKind = R.getLookupKind(); + + if (!getLangOptions().CPlusPlus) { + // Unqualified name lookup in C/Objective-C is purely lexical, so + // search in the declarations attached to the name. + if (NameKind == Sema::LookupRedeclarationWithLinkage) { + // Find the nearest non-transparent declaration scope. + while (!(S->getFlags() & Scope::DeclScope) || + (S->getEntity() && + static_cast<DeclContext *>(S->getEntity()) + ->isTransparentContext())) + S = S->getParent(); + } + + unsigned IDNS = R.getIdentifierNamespace(); + + // Scan up the scope chain looking for a decl that matches this + // identifier that is in the appropriate namespace. This search + // should not take long, as shadowing of names is uncommon, and + // deep shadowing is extremely uncommon. + bool LeftStartingScope = false; + + for (IdentifierResolver::iterator I = IdResolver.begin(Name), + IEnd = IdResolver.end(); + I != IEnd; ++I) + if ((*I)->isInIdentifierNamespace(IDNS)) { + if (NameKind == LookupRedeclarationWithLinkage) { + // Determine whether this (or a previous) declaration is + // out-of-scope. + if (!LeftStartingScope && !S->isDeclScope(*I)) + LeftStartingScope = true; + + // If we found something outside of our starting scope that + // does not have linkage, skip it. + if (LeftStartingScope && !((*I)->hasLinkage())) + continue; + } + + R.addDecl(*I); + + if ((*I)->getAttr<OverloadableAttr>()) { + // If this declaration has the "overloadable" attribute, we + // might have a set of overloaded functions. + + // Figure out what scope the identifier is in. + while (!(S->getFlags() & Scope::DeclScope) || + !S->isDeclScope(*I)) + S = S->getParent(); + + // Find the last declaration in this scope (with the same + // name, naturally). + IdentifierResolver::iterator LastI = I; + for (++LastI; LastI != IEnd; ++LastI) { + if (!S->isDeclScope(*LastI)) + break; + R.addDecl(*LastI); + } + } + + R.resolveKind(); + + return true; + } + } else { + // Perform C++ unqualified name lookup. + if (CppLookupName(R, S)) + return true; + } + + // If we didn't find a use of this identifier, and if the identifier + // corresponds to a compiler builtin, create the decl object for the builtin + // now, injecting it into translation unit scope, and return it. + if (AllowBuiltinCreation && LookupBuiltin(*this, R)) + return true; + + // If we didn't find a use of this identifier, the ExternalSource + // may be able to handle the situation. + // Note: some lookup failures are expected! + // See e.g. R.isForRedeclaration(). + return (ExternalSource && ExternalSource->LookupUnqualified(R, S)); +} + +/// @brief Perform qualified name lookup in the namespaces nominated by +/// using directives by the given context. +/// +/// C++98 [namespace.qual]p2: +/// Given X::m (where X is a user-declared namespace), or given ::m +/// (where X is the global namespace), let S be the set of all +/// declarations of m in X and in the transitive closure of all +/// namespaces nominated by using-directives in X and its used +/// namespaces, except that using-directives are ignored in any +/// namespace, including X, directly containing one or more +/// declarations of m. No namespace is searched more than once in +/// the lookup of a name. If S is the empty set, the program is +/// ill-formed. Otherwise, if S has exactly one member, or if the +/// context of the reference is a using-declaration +/// (namespace.udecl), S is the required set of declarations of +/// m. Otherwise if the use of m is not one that allows a unique +/// declaration to be chosen from S, the program is ill-formed. +/// C++98 [namespace.qual]p5: +/// During the lookup of a qualified namespace member name, if the +/// lookup finds more than one declaration of the member, and if one +/// declaration introduces a class name or enumeration name and the +/// other declarations either introduce the same object, the same +/// enumerator or a set of functions, the non-type name hides the +/// class or enumeration name if and only if the declarations are +/// from the same namespace; otherwise (the declarations are from +/// different namespaces), the program is ill-formed. +static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, + DeclContext *StartDC) { + assert(StartDC->isFileContext() && "start context is not a file context"); + + DeclContext::udir_iterator I = StartDC->using_directives_begin(); + DeclContext::udir_iterator E = StartDC->using_directives_end(); + + if (I == E) return false; + + // We have at least added all these contexts to the queue. + llvm::DenseSet<DeclContext*> Visited; + Visited.insert(StartDC); + + // We have not yet looked into these namespaces, much less added + // their "using-children" to the queue. + llvm::SmallVector<NamespaceDecl*, 8> Queue; + + // We have already looked into the initial namespace; seed the queue + // with its using-children. + for (; I != E; ++I) { + NamespaceDecl *ND = (*I)->getNominatedNamespace()->getOriginalNamespace(); + if (Visited.insert(ND).second) + Queue.push_back(ND); + } + + // The easiest way to implement the restriction in [namespace.qual]p5 + // is to check whether any of the individual results found a tag + // and, if so, to declare an ambiguity if the final result is not + // a tag. + bool FoundTag = false; + bool FoundNonTag = false; + + LookupResult LocalR(LookupResult::Temporary, R); + + bool Found = false; + while (!Queue.empty()) { + NamespaceDecl *ND = Queue.back(); + Queue.pop_back(); + + // We go through some convolutions here to avoid copying results + // between LookupResults. + bool UseLocal = !R.empty(); + LookupResult &DirectR = UseLocal ? LocalR : R; + bool FoundDirect = LookupDirect(S, DirectR, ND); + + if (FoundDirect) { + // First do any local hiding. + DirectR.resolveKind(); + + // If the local result is a tag, remember that. + if (DirectR.isSingleTagDecl()) + FoundTag = true; + else + FoundNonTag = true; + + // Append the local results to the total results if necessary. + if (UseLocal) { + R.addAllDecls(LocalR); + LocalR.clear(); + } + } + + // If we find names in this namespace, ignore its using directives. + if (FoundDirect) { + Found = true; + continue; + } + + for (llvm::tie(I,E) = ND->getUsingDirectives(); I != E; ++I) { + NamespaceDecl *Nom = (*I)->getNominatedNamespace(); + if (Visited.insert(Nom).second) + Queue.push_back(Nom); + } + } + + if (Found) { + if (FoundTag && FoundNonTag) + R.setAmbiguousQualifiedTagHiding(); + else + R.resolveKind(); + } + + return Found; +} + +/// \brief Callback that looks for any member of a class with the given name. +static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, + void *Name) { + RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); + + DeclarationName N = DeclarationName::getFromOpaquePtr(Name); + Path.Decls = BaseRecord->lookup(N); + return Path.Decls.first != Path.Decls.second; +} + +/// \brief Determine whether the given set of member declarations contains only +/// static members, nested types, and enumerators. +template<typename InputIterator> +static bool HasOnlyStaticMembers(InputIterator First, InputIterator Last) { + Decl *D = (*First)->getUnderlyingDecl(); + if (isa<VarDecl>(D) || isa<TypeDecl>(D) || isa<EnumConstantDecl>(D)) + return true; + + if (isa<CXXMethodDecl>(D)) { + // Determine whether all of the methods are static. + bool AllMethodsAreStatic = true; + for(; First != Last; ++First) { + D = (*First)->getUnderlyingDecl(); + + if (!isa<CXXMethodDecl>(D)) { + assert(isa<TagDecl>(D) && "Non-function must be a tag decl"); + break; + } + + if (!cast<CXXMethodDecl>(D)->isStatic()) { + AllMethodsAreStatic = false; + break; + } + } + + if (AllMethodsAreStatic) + return true; + } + + return false; +} + +/// \brief Perform qualified name lookup into a given context. +/// +/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find +/// names when the context of those names is explicit specified, e.g., +/// "std::vector" or "x->member", or as part of unqualified name lookup. +/// +/// Different lookup criteria can find different names. For example, a +/// particular scope can have both a struct and a function of the same +/// name, and each can be found by certain lookup criteria. For more +/// information about lookup criteria, see the documentation for the +/// class LookupCriteria. +/// +/// \param R captures both the lookup criteria and any lookup results found. +/// +/// \param LookupCtx The context in which qualified name lookup will +/// search. If the lookup criteria permits, name lookup may also search +/// in the parent contexts or (for C++ classes) base classes. +/// +/// \param InUnqualifiedLookup true if this is qualified name lookup that +/// occurs as part of unqualified name lookup. +/// +/// \returns true if lookup succeeded, false if it failed. +bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + bool InUnqualifiedLookup) { + assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); + + if (!R.getLookupName()) + return false; + + // Make sure that the declaration context is complete. + assert((!isa<TagDecl>(LookupCtx) || + LookupCtx->isDependentContext() || + cast<TagDecl>(LookupCtx)->isDefinition() || + Context.getTypeDeclType(cast<TagDecl>(LookupCtx))->getAs<TagType>() + ->isBeingDefined()) && + "Declaration context must already be complete!"); + + // Perform qualified name lookup into the LookupCtx. + if (LookupDirect(*this, R, LookupCtx)) { + R.resolveKind(); + if (isa<CXXRecordDecl>(LookupCtx)) + R.setNamingClass(cast<CXXRecordDecl>(LookupCtx)); + return true; + } + + // Don't descend into implied contexts for redeclarations. + // C++98 [namespace.qual]p6: + // In a declaration for a namespace member in which the + // declarator-id is a qualified-id, given that the qualified-id + // for the namespace member has the form + // nested-name-specifier unqualified-id + // the unqualified-id shall name a member of the namespace + // designated by the nested-name-specifier. + // See also [class.mfct]p5 and [class.static.data]p2. + if (R.isForRedeclaration()) + return false; + + // If this is a namespace, look it up in the implied namespaces. + if (LookupCtx->isFileContext()) + return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx); + + // If this isn't a C++ class, we aren't allowed to look into base + // classes, we're done. + CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx); + if (!LookupRec || !LookupRec->getDefinition()) + return false; + + // If we're performing qualified name lookup into a dependent class, + // then we are actually looking into a current instantiation. If we have any + // dependent base classes, then we either have to delay lookup until + // template instantiation time (at which point all bases will be available) + // or we have to fail. + if (!InUnqualifiedLookup && LookupRec->isDependentContext() && + LookupRec->hasAnyDependentBases()) { + R.setNotFoundInCurrentInstantiation(); + return false; + } + + // Perform lookup into our base classes. + CXXBasePaths Paths; + Paths.setOrigin(LookupRec); + + // Look for this member in our base classes + CXXRecordDecl::BaseMatchesCallback *BaseCallback = 0; + switch (R.getLookupKind()) { + case LookupOrdinaryName: + case LookupMemberName: + case LookupRedeclarationWithLinkage: + BaseCallback = &CXXRecordDecl::FindOrdinaryMember; + break; + + case LookupTagName: + BaseCallback = &CXXRecordDecl::FindTagMember; + break; + + case LookupAnyName: + BaseCallback = &LookupAnyMember; + break; + + case LookupUsingDeclName: + // This lookup is for redeclarations only. + + case LookupOperatorName: + case LookupNamespaceName: + case LookupObjCProtocolName: + case LookupLabel: + // These lookups will never find a member in a C++ class (or base class). + return false; + + case LookupNestedNameSpecifierName: + BaseCallback = &CXXRecordDecl::FindNestedNameSpecifierMember; + break; + } + + if (!LookupRec->lookupInBases(BaseCallback, + R.getLookupName().getAsOpaquePtr(), Paths)) + return false; + + R.setNamingClass(LookupRec); + + // C++ [class.member.lookup]p2: + // [...] If the resulting set of declarations are not all from + // sub-objects of the same type, or the set has a nonstatic member + // and includes members from distinct sub-objects, there is an + // ambiguity and the program is ill-formed. Otherwise that set is + // the result of the lookup. + QualType SubobjectType; + int SubobjectNumber = 0; + AccessSpecifier SubobjectAccess = AS_none; + + for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end(); + Path != PathEnd; ++Path) { + const CXXBasePathElement &PathElement = Path->back(); + + // Pick the best (i.e. most permissive i.e. numerically lowest) access + // across all paths. + SubobjectAccess = std::min(SubobjectAccess, Path->Access); + + // Determine whether we're looking at a distinct sub-object or not. + if (SubobjectType.isNull()) { + // This is the first subobject we've looked at. Record its type. + SubobjectType = Context.getCanonicalType(PathElement.Base->getType()); + SubobjectNumber = PathElement.SubobjectNumber; + continue; + } + + if (SubobjectType + != Context.getCanonicalType(PathElement.Base->getType())) { + // We found members of the given name in two subobjects of + // different types. If the declaration sets aren't the same, this + // this lookup is ambiguous. + if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second)) { + CXXBasePaths::paths_iterator FirstPath = Paths.begin(); + DeclContext::lookup_iterator FirstD = FirstPath->Decls.first; + DeclContext::lookup_iterator CurrentD = Path->Decls.first; + + while (FirstD != FirstPath->Decls.second && + CurrentD != Path->Decls.second) { + if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() != + (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl()) + break; + + ++FirstD; + ++CurrentD; + } + + if (FirstD == FirstPath->Decls.second && + CurrentD == Path->Decls.second) + continue; + } + + R.setAmbiguousBaseSubobjectTypes(Paths); + return true; + } + + if (SubobjectNumber != PathElement.SubobjectNumber) { + // We have a different subobject of the same type. + + // C++ [class.member.lookup]p5: + // A static member, a nested type or an enumerator defined in + // a base class T can unambiguously be found even if an object + // has more than one base class subobject of type T. + if (HasOnlyStaticMembers(Path->Decls.first, Path->Decls.second)) + continue; + + // We have found a nonstatic member name in multiple, distinct + // subobjects. Name lookup is ambiguous. + R.setAmbiguousBaseSubobjects(Paths); + return true; + } + } + + // Lookup in a base class succeeded; return these results. + + DeclContext::lookup_iterator I, E; + for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I) { + NamedDecl *D = *I; + AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess, + D->getAccess()); + R.addDecl(D, AS); + } + R.resolveKind(); + return true; +} + +/// @brief Performs name lookup for a name that was parsed in the +/// source code, and may contain a C++ scope specifier. +/// +/// This routine is a convenience routine meant to be called from +/// contexts that receive a name and an optional C++ scope specifier +/// (e.g., "N::M::x"). It will then perform either qualified or +/// unqualified name lookup (with LookupQualifiedName or LookupName, +/// respectively) on the given name and return those results. +/// +/// @param S The scope from which unqualified name lookup will +/// begin. +/// +/// @param SS An optional C++ scope-specifier, e.g., "::N::M". +/// +/// @param EnteringContext Indicates whether we are going to enter the +/// context of the scope-specifier SS (if present). +/// +/// @returns True if any decls were found (but possibly ambiguous) +bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, + bool AllowBuiltinCreation, bool EnteringContext) { + if (SS && SS->isInvalid()) { + // When the scope specifier is invalid, don't even look for + // anything. + return false; + } + + if (SS && SS->isSet()) { + if (DeclContext *DC = computeDeclContext(*SS, EnteringContext)) { + // We have resolved the scope specifier to a particular declaration + // contex, and will perform name lookup in that context. + if (!DC->isDependentContext() && RequireCompleteDeclContext(*SS, DC)) + return false; + + R.setContextRange(SS->getRange()); + + return LookupQualifiedName(R, DC); + } + + // We could not resolve the scope specified to a specific declaration + // context, which means that SS refers to an unknown specialization. + // Name lookup can't find anything in this case. + return false; + } + + // Perform unqualified name lookup starting in the given scope. + return LookupName(R, S, AllowBuiltinCreation); +} + + +/// @brief Produce a diagnostic describing the ambiguity that resulted +/// from name lookup. +/// +/// @param Result The ambiguous name lookup result. +/// +/// @param Name The name of the entity that name lookup was +/// searching for. +/// +/// @param NameLoc The location of the name within the source code. +/// +/// @param LookupRange A source range that provides more +/// source-location information concerning the lookup itself. For +/// example, this range might highlight a nested-name-specifier that +/// precedes the name. +/// +/// @returns true +bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { + assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); + + DeclarationName Name = Result.getLookupName(); + SourceLocation NameLoc = Result.getNameLoc(); + SourceRange LookupRange = Result.getContextRange(); + + switch (Result.getAmbiguityKind()) { + case LookupResult::AmbiguousBaseSubobjects: { + CXXBasePaths *Paths = Result.getBasePaths(); + QualType SubobjectType = Paths->front().back().Base->getType(); + Diag(NameLoc, diag::err_ambiguous_member_multiple_subobjects) + << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths) + << LookupRange; + + DeclContext::lookup_iterator Found = Paths->front().Decls.first; + while (isa<CXXMethodDecl>(*Found) && + cast<CXXMethodDecl>(*Found)->isStatic()) + ++Found; + + Diag((*Found)->getLocation(), diag::note_ambiguous_member_found); + + return true; + } + + case LookupResult::AmbiguousBaseSubobjectTypes: { + Diag(NameLoc, diag::err_ambiguous_member_multiple_subobject_types) + << Name << LookupRange; + + CXXBasePaths *Paths = Result.getBasePaths(); + std::set<Decl *> DeclsPrinted; + for (CXXBasePaths::paths_iterator Path = Paths->begin(), + PathEnd = Paths->end(); + Path != PathEnd; ++Path) { + Decl *D = *Path->Decls.first; + if (DeclsPrinted.insert(D).second) + Diag(D->getLocation(), diag::note_ambiguous_member_found); + } + + return true; + } + + case LookupResult::AmbiguousTagHiding: { + Diag(NameLoc, diag::err_ambiguous_tag_hiding) << Name << LookupRange; + + llvm::SmallPtrSet<NamedDecl*,8> TagDecls; + + LookupResult::iterator DI, DE = Result.end(); + for (DI = Result.begin(); DI != DE; ++DI) + if (TagDecl *TD = dyn_cast<TagDecl>(*DI)) { + TagDecls.insert(TD); + Diag(TD->getLocation(), diag::note_hidden_tag); + } + + for (DI = Result.begin(); DI != DE; ++DI) + if (!isa<TagDecl>(*DI)) + Diag((*DI)->getLocation(), diag::note_hiding_object); + + // For recovery purposes, go ahead and implement the hiding. + LookupResult::Filter F = Result.makeFilter(); + while (F.hasNext()) { + if (TagDecls.count(F.next())) + F.erase(); + } + F.done(); + + return true; + } + + case LookupResult::AmbiguousReference: { + Diag(NameLoc, diag::err_ambiguous_reference) << Name << LookupRange; + + LookupResult::iterator DI = Result.begin(), DE = Result.end(); + for (; DI != DE; ++DI) + Diag((*DI)->getLocation(), diag::note_ambiguous_candidate) << *DI; + + return true; + } + } + + llvm_unreachable("unknown ambiguity kind"); + return true; +} + +namespace { + struct AssociatedLookup { + AssociatedLookup(Sema &S, + Sema::AssociatedNamespaceSet &Namespaces, + Sema::AssociatedClassSet &Classes) + : S(S), Namespaces(Namespaces), Classes(Classes) { + } + + Sema &S; + Sema::AssociatedNamespaceSet &Namespaces; + Sema::AssociatedClassSet &Classes; + }; +} + +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T); + +static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces, + DeclContext *Ctx) { + // Add the associated namespace for this class. + + // We don't use DeclContext::getEnclosingNamespaceContext() as this may + // be a locally scoped record. + + // We skip out of inline namespaces. The innermost non-inline namespace + // contains all names of all its nested inline namespaces anyway, so we can + // replace the entire inline namespace tree with its root. + while (Ctx->isRecord() || Ctx->isTransparentContext() || + Ctx->isInlineNamespace()) + Ctx = Ctx->getParent(); + + if (Ctx->isFileContext()) + Namespaces.insert(Ctx->getPrimaryContext()); +} + +// \brief Add the associated classes and namespaces for argument-dependent +// lookup that involves a template argument (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, + const TemplateArgument &Arg) { + // C++ [basic.lookup.koenig]p2, last bullet: + // -- [...] ; + switch (Arg.getKind()) { + case TemplateArgument::Null: + break; + + case TemplateArgument::Type: + // [...] the namespaces and classes associated with the types of the + // template arguments provided for template type parameters (excluding + // template template parameters) + addAssociatedClassesAndNamespaces(Result, Arg.getAsType()); + break; + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { + // [...] the namespaces in which any template template arguments are + // defined; and the classes in which any member templates used as + // template template arguments are defined. + TemplateName Template = Arg.getAsTemplateOrTemplatePattern(); + if (ClassTemplateDecl *ClassTemplate + = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) { + DeclContext *Ctx = ClassTemplate->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + Result.Classes.insert(EnclosingClass); + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + } + break; + } + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + case TemplateArgument::Expression: + // [Note: non-type template arguments do not contribute to the set of + // associated namespaces. ] + break; + + case TemplateArgument::Pack: + for (TemplateArgument::pack_iterator P = Arg.pack_begin(), + PEnd = Arg.pack_end(); + P != PEnd; ++P) + addAssociatedClassesAndNamespaces(Result, *P); + break; + } +} + +// \brief Add the associated classes and namespaces for +// argument-dependent lookup with an argument of class type +// (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, + CXXRecordDecl *Class) { + + // Just silently ignore anything whose name is __va_list_tag. + if (Class->getDeclName() == Result.S.VAListTagName) + return; + + // C++ [basic.lookup.koenig]p2: + // [...] + // -- If T is a class type (including unions), its associated + // classes are: the class itself; the class of which it is a + // member, if any; and its direct and indirect base + // classes. Its associated namespaces are the namespaces in + // which its associated classes are defined. + + // Add the class of which it is a member, if any. + DeclContext *Ctx = Class->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + Result.Classes.insert(EnclosingClass); + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + + // Add the class itself. If we've already seen this class, we don't + // need to visit base classes. + if (!Result.Classes.insert(Class)) + return; + + // -- If T is a template-id, its associated namespaces and classes are + // the namespace in which the template is defined; for member + // templates, the member template's class; the namespaces and classes + // associated with the types of the template arguments provided for + // template type parameters (excluding template template parameters); the + // namespaces in which any template template arguments are defined; and + // the classes in which any member templates used as template template + // arguments are defined. [Note: non-type template arguments do not + // contribute to the set of associated namespaces. ] + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Class)) { + DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + Result.Classes.insert(EnclosingClass); + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + + const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]); + } + + // Only recurse into base classes for complete types. + if (!Class->hasDefinition()) { + // FIXME: we might need to instantiate templates here + return; + } + + // Add direct and indirect base classes along with their associated + // namespaces. + llvm::SmallVector<CXXRecordDecl *, 32> Bases; + Bases.push_back(Class); + while (!Bases.empty()) { + // Pop this class off the stack. + Class = Bases.back(); + Bases.pop_back(); + + // Visit the base classes. + for (CXXRecordDecl::base_class_iterator Base = Class->bases_begin(), + BaseEnd = Class->bases_end(); + Base != BaseEnd; ++Base) { + const RecordType *BaseType = Base->getType()->getAs<RecordType>(); + // In dependent contexts, we do ADL twice, and the first time around, + // the base type might be a dependent TemplateSpecializationType, or a + // TemplateTypeParmType. If that happens, simply ignore it. + // FIXME: If we want to support export, we probably need to add the + // namespace of the template in a TemplateSpecializationType, or even + // the classes and namespaces of known non-dependent arguments. + if (!BaseType) + continue; + CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + if (Result.Classes.insert(BaseDecl)) { + // Find the associated namespace for this base class. + DeclContext *BaseCtx = BaseDecl->getDeclContext(); + CollectEnclosingNamespace(Result.Namespaces, BaseCtx); + + // Make sure we visit the bases of this base class. + if (BaseDecl->bases_begin() != BaseDecl->bases_end()) + Bases.push_back(BaseDecl); + } + } + } +} + +// \brief Add the associated classes and namespaces for +// argument-dependent lookup with an argument of type T +// (C++ [basic.lookup.koenig]p2). +static void +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { + // C++ [basic.lookup.koenig]p2: + // + // For each argument type T in the function call, there is a set + // of zero or more associated namespaces and a set of zero or more + // associated classes to be considered. The sets of namespaces and + // classes is determined entirely by the types of the function + // arguments (and the namespace of any template template + // argument). Typedef names and using-declarations used to specify + // the types do not contribute to this set. The sets of namespaces + // and classes are determined in the following way: + + llvm::SmallVector<const Type *, 16> Queue; + const Type *T = Ty->getCanonicalTypeInternal().getTypePtr(); + + while (true) { + switch (T->getTypeClass()) { + +#define TYPE(Class, Base) +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + // T is canonical. We can also ignore dependent types because + // we don't need to do ADL at the definition point, but if we + // wanted to implement template export (or if we find some other + // use for associated classes and namespaces...) this would be + // wrong. + break; + + // -- If T is a pointer to U or an array of U, its associated + // namespaces and classes are those associated with U. + case Type::Pointer: + T = cast<PointerType>(T)->getPointeeType().getTypePtr(); + continue; + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + T = cast<ArrayType>(T)->getElementType().getTypePtr(); + continue; + + // -- If T is a fundamental type, its associated sets of + // namespaces and classes are both empty. + case Type::Builtin: + break; + + // -- If T is a class type (including unions), its associated + // classes are: the class itself; the class of which it is a + // member, if any; and its direct and indirect base + // classes. Its associated namespaces are the namespaces in + // which its associated classes are defined. + case Type::Record: { + CXXRecordDecl *Class + = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl()); + addAssociatedClassesAndNamespaces(Result, Class); + break; + } + + // -- If T is an enumeration type, its associated namespace is + // the namespace in which it is defined. If it is class + // member, its associated class is the member's class; else + // it has no associated class. + case Type::Enum: { + EnumDecl *Enum = cast<EnumType>(T)->getDecl(); + + DeclContext *Ctx = Enum->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + Result.Classes.insert(EnclosingClass); + + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); + + break; + } + + // -- If T is a function type, its associated namespaces and + // classes are those associated with the function parameter + // types and those associated with the return type. + case Type::FunctionProto: { + const FunctionProtoType *Proto = cast<FunctionProtoType>(T); + for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), + ArgEnd = Proto->arg_type_end(); + Arg != ArgEnd; ++Arg) + Queue.push_back(Arg->getTypePtr()); + // fallthrough + } + case Type::FunctionNoProto: { + const FunctionType *FnType = cast<FunctionType>(T); + T = FnType->getResultType().getTypePtr(); + continue; + } + + // -- If T is a pointer to a member function of a class X, its + // associated namespaces and classes are those associated + // with the function parameter types and return type, + // together with those associated with X. + // + // -- If T is a pointer to a data member of class X, its + // associated namespaces and classes are those associated + // with the member type together with those associated with + // X. + case Type::MemberPointer: { + const MemberPointerType *MemberPtr = cast<MemberPointerType>(T); + + // Queue up the class type into which this points. + Queue.push_back(MemberPtr->getClass()); + + // And directly continue with the pointee type. + T = MemberPtr->getPointeeType().getTypePtr(); + continue; + } + + // As an extension, treat this like a normal pointer. + case Type::BlockPointer: + T = cast<BlockPointerType>(T)->getPointeeType().getTypePtr(); + continue; + + // References aren't covered by the standard, but that's such an + // obvious defect that we cover them anyway. + case Type::LValueReference: + case Type::RValueReference: + T = cast<ReferenceType>(T)->getPointeeType().getTypePtr(); + continue; + + // These are fundamental types. + case Type::Vector: + case Type::ExtVector: + case Type::Complex: + break; + + // If T is an Objective-C object or interface type, or a pointer to an + // object or interface type, the associated namespace is the global + // namespace. + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + Result.Namespaces.insert(Result.S.Context.getTranslationUnitDecl()); + break; + } + + if (Queue.empty()) break; + T = Queue.back(); + Queue.pop_back(); + } +} + +/// \brief Find the associated classes and namespaces for +/// argument-dependent lookup for a call with the given set of +/// arguments. +/// +/// This routine computes the sets of associated classes and associated +/// namespaces searched by argument-dependent lookup +/// (C++ [basic.lookup.argdep]) for a given set of arguments. +void +Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, + AssociatedNamespaceSet &AssociatedNamespaces, + AssociatedClassSet &AssociatedClasses) { + AssociatedNamespaces.clear(); + AssociatedClasses.clear(); + + AssociatedLookup Result(*this, AssociatedNamespaces, AssociatedClasses); + + // C++ [basic.lookup.koenig]p2: + // For each argument type T in the function call, there is a set + // of zero or more associated namespaces and a set of zero or more + // associated classes to be considered. The sets of namespaces and + // classes is determined entirely by the types of the function + // arguments (and the namespace of any template template + // argument). + for (unsigned ArgIdx = 0; ArgIdx != NumArgs; ++ArgIdx) { + Expr *Arg = Args[ArgIdx]; + + if (Arg->getType() != Context.OverloadTy) { + addAssociatedClassesAndNamespaces(Result, Arg->getType()); + continue; + } + + // [...] In addition, if the argument is the name or address of a + // set of overloaded functions and/or function templates, its + // associated classes and namespaces are the union of those + // associated with each of the members of the set: the namespace + // in which the function or function template is defined and the + // classes and namespaces associated with its (non-dependent) + // parameter types and return type. + Arg = Arg->IgnoreParens(); + if (UnaryOperator *unaryOp = dyn_cast<UnaryOperator>(Arg)) + if (unaryOp->getOpcode() == UO_AddrOf) + Arg = unaryOp->getSubExpr(); + + UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg); + if (!ULE) continue; + + for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end(); + I != E; ++I) { + // Look through any using declarations to find the underlying function. + NamedDecl *Fn = (*I)->getUnderlyingDecl(); + + FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn); + if (!FDecl) + FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl(); + + // Add the classes and namespaces associated with the parameter + // types and return type of this function. + addAssociatedClassesAndNamespaces(Result, FDecl->getType()); + } + } +} + +/// IsAcceptableNonMemberOperatorCandidate - Determine whether Fn is +/// an acceptable non-member overloaded operator for a call whose +/// arguments have types T1 (and, if non-empty, T2). This routine +/// implements the check in C++ [over.match.oper]p3b2 concerning +/// enumeration types. +static bool +IsAcceptableNonMemberOperatorCandidate(FunctionDecl *Fn, + QualType T1, QualType T2, + ASTContext &Context) { + if (T1->isDependentType() || (!T2.isNull() && T2->isDependentType())) + return true; + + if (T1->isRecordType() || (!T2.isNull() && T2->isRecordType())) + return true; + + const FunctionProtoType *Proto = Fn->getType()->getAs<FunctionProtoType>(); + if (Proto->getNumArgs() < 1) + return false; + + if (T1->isEnumeralType()) { + QualType ArgType = Proto->getArgType(0).getNonReferenceType(); + if (Context.hasSameUnqualifiedType(T1, ArgType)) + return true; + } + + if (Proto->getNumArgs() < 2) + return false; + + if (!T2.isNull() && T2->isEnumeralType()) { + QualType ArgType = Proto->getArgType(1).getNonReferenceType(); + if (Context.hasSameUnqualifiedType(T2, ArgType)) + return true; + } + + return false; +} + +NamedDecl *Sema::LookupSingleName(Scope *S, DeclarationName Name, + SourceLocation Loc, + LookupNameKind NameKind, + RedeclarationKind Redecl) { + LookupResult R(*this, Name, Loc, NameKind, Redecl); + LookupName(R, S); + return R.getAsSingle<NamedDecl>(); +} + +/// \brief Find the protocol with the given name, if any. +ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II, + SourceLocation IdLoc) { + Decl *D = LookupSingleName(TUScope, II, IdLoc, + LookupObjCProtocolName); + return cast_or_null<ObjCProtocolDecl>(D); +} + +void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, + QualType T1, QualType T2, + UnresolvedSetImpl &Functions) { + // C++ [over.match.oper]p3: + // -- The set of non-member candidates is the result of the + // unqualified lookup of operator@ in the context of the + // expression according to the usual rules for name lookup in + // unqualified function calls (3.4.2) except that all member + // functions are ignored. However, if no operand has a class + // type, only those non-member functions in the lookup set + // that have a first parameter of type T1 or "reference to + // (possibly cv-qualified) T1", when T1 is an enumeration + // type, or (if there is a right operand) a second parameter + // of type T2 or "reference to (possibly cv-qualified) T2", + // when T2 is an enumeration type, are candidate functions. + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + LookupResult Operators(*this, OpName, SourceLocation(), LookupOperatorName); + LookupName(Operators, S); + + assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous"); + + if (Operators.empty()) + return; + + for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end(); + Op != OpEnd; ++Op) { + NamedDecl *Found = (*Op)->getUnderlyingDecl(); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Found)) { + if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) + Functions.addDecl(*Op, Op.getAccess()); // FIXME: canonical FD + } else if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(Found)) { + // FIXME: friend operators? + // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, + // later? + if (!FunTmpl->getDeclContext()->isRecord()) + Functions.addDecl(*Op, Op.getAccess()); + } + } +} + +Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *D, + CXXSpecialMember SM, + bool ConstArg, + bool VolatileArg, + bool RValueThis, + bool ConstThis, + bool VolatileThis) { + D = D->getDefinition(); + assert((D && !D->isBeingDefined()) && + "doing special member lookup into record that isn't fully complete"); + if (RValueThis || ConstThis || VolatileThis) + assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && + "constructors and destructors always have unqualified lvalue this"); + if (ConstArg || VolatileArg) + assert((SM != CXXDefaultConstructor && SM != CXXDestructor) && + "parameter-less special members can't have qualified arguments"); + + llvm::FoldingSetNodeID ID; + ID.AddPointer(D); + ID.AddInteger(SM); + ID.AddInteger(ConstArg); + ID.AddInteger(VolatileArg); + ID.AddInteger(RValueThis); + ID.AddInteger(ConstThis); + ID.AddInteger(VolatileThis); + + void *InsertPoint; + SpecialMemberOverloadResult *Result = + SpecialMemberCache.FindNodeOrInsertPos(ID, InsertPoint); + + // This was already cached + if (Result) + return Result; + + Result = BumpAlloc.Allocate<SpecialMemberOverloadResult>(); + Result = new (Result) SpecialMemberOverloadResult(ID); + SpecialMemberCache.InsertNode(Result, InsertPoint); + + if (SM == CXXDestructor) { + if (!D->hasDeclaredDestructor()) + DeclareImplicitDestructor(D); + CXXDestructorDecl *DD = D->getDestructor(); + assert(DD && "record without a destructor"); + Result->setMethod(DD); + Result->setSuccess(DD->isDeleted()); + Result->setConstParamMatch(false); + return Result; + } + + // Prepare for overload resolution. Here we construct a synthetic argument + // if necessary and make sure that implicit functions are declared. + CanQualType CanTy = Context.getCanonicalType(Context.getTagDeclType(D)); + DeclarationName Name; + Expr *Arg = 0; + unsigned NumArgs; + + if (SM == CXXDefaultConstructor) { + Name = Context.DeclarationNames.getCXXConstructorName(CanTy); + NumArgs = 0; + if (D->needsImplicitDefaultConstructor()) + DeclareImplicitDefaultConstructor(D); + } else { + if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { + Name = Context.DeclarationNames.getCXXConstructorName(CanTy); + if (!D->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(D); + // TODO: Move constructors + } else { + Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + if (!D->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(D); + // TODO: Move assignment + } + + QualType ArgType = CanTy; + if (ConstArg) + ArgType.addConst(); + if (VolatileArg) + ArgType.addVolatile(); + + // This isn't /really/ specified by the standard, but it's implied + // we should be working from an RValue in the case of move to ensure + // that we prefer to bind to rvalue references, and an LValue in the + // case of copy to ensure we don't bind to rvalue references. + // Possibly an XValue is actually correct in the case of move, but + // there is no semantic difference for class types in this restricted + // case. + ExprValueKind VK; + if (SM == CXXCopyAssignment || SM == CXXMoveAssignment) + VK = VK_LValue; + else + VK = VK_RValue; + + NumArgs = 1; + Arg = new (Context) OpaqueValueExpr(SourceLocation(), ArgType, VK); + } + + // Create the object argument + QualType ThisTy = CanTy; + if (ConstThis) + ThisTy.addConst(); + if (VolatileThis) + ThisTy.addVolatile(); + Expr::Classification ObjectClassification = + (new (Context) OpaqueValueExpr(SourceLocation(), ThisTy, + RValueThis ? VK_RValue : VK_LValue))-> + Classify(Context); + + // Now we perform lookup on the name we computed earlier and do overload + // resolution. Lookup is only performed directly into the class since there + // will always be a (possibly implicit) declaration to shadow any others. + OverloadCandidateSet OCS((SourceLocation())); + DeclContext::lookup_iterator I, E; + Result->setConstParamMatch(false); + + llvm::tie(I, E) = D->lookup(Name); + assert((I != E) && + "lookup for a constructor or assignment operator was empty"); + for ( ; I != E; ++I) { + if ((*I)->isInvalidDecl()) + continue; + + if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(*I)) { + AddOverloadCandidate(M, DeclAccessPair::make(M, AS_public), &Arg, NumArgs, + OCS, true); + + // Here we're looking for a const parameter to speed up creation of + // implicit copy methods. + if ((SM == CXXCopyAssignment && M->isCopyAssignmentOperator()) || + (SM == CXXCopyConstructor && + cast<CXXConstructorDecl>(M)->isCopyConstructor())) { + QualType ArgType = M->getType()->getAs<FunctionProtoType>()->getArgType(0); + if (ArgType->getPointeeType().isConstQualified()) + Result->setConstParamMatch(true); + } + } else { + FunctionTemplateDecl *Tmpl = cast<FunctionTemplateDecl>(*I); + AddTemplateOverloadCandidate(Tmpl, DeclAccessPair::make(Tmpl, AS_public), + 0, &Arg, NumArgs, OCS, true); + } + } + + OverloadCandidateSet::iterator Best; + switch (OCS.BestViableFunction(*this, SourceLocation(), Best)) { + case OR_Success: + Result->setMethod(cast<CXXMethodDecl>(Best->Function)); + Result->setSuccess(true); + break; + + case OR_Deleted: + Result->setMethod(cast<CXXMethodDecl>(Best->Function)); + Result->setSuccess(false); + break; + + case OR_Ambiguous: + case OR_No_Viable_Function: + Result->setMethod(0); + Result->setSuccess(false); + break; + } + + return Result; +} + +/// \brief Look up the default constructor for the given class. +CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXDefaultConstructor, false, false, false, + false, false); + + return cast_or_null<CXXConstructorDecl>(Result->getMethod()); +} + +/// \brief Look up the copy constructor for the given class. +CXXConstructorDecl *Sema::LookupCopyConstructor(CXXRecordDecl *Class, + unsigned Quals, + bool *ConstParamMatch) { + assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && + "non-const, non-volatile qualifiers for copy ctor arg"); + SpecialMemberOverloadResult *Result = + LookupSpecialMember(Class, CXXCopyConstructor, Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, false, false, false); + + if (ConstParamMatch) + *ConstParamMatch = Result->hasConstParamMatch(); + + return cast_or_null<CXXConstructorDecl>(Result->getMethod()); +} + +/// \brief Look up the constructors for the given class. +DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { + // If the implicit constructors have not yet been declared, do so now. + if (CanDeclareSpecialMemberFunction(Context, Class)) { + if (Class->needsImplicitDefaultConstructor()) + DeclareImplicitDefaultConstructor(Class); + if (!Class->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(Class); + } + + CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class)); + DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T); + return Class->lookup(Name); +} + +/// \brief Look for the destructor of the given class. +/// +/// During semantic analysis, this routine should be used in lieu of +/// CXXRecordDecl::getDestructor(). +/// +/// \returns The destructor for this class. +CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { + return cast<CXXDestructorDecl>(LookupSpecialMember(Class, CXXDestructor, + false, false, false, + false, false)->getMethod()); +} + +void ADLResult::insert(NamedDecl *New) { + NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())]; + + // If we haven't yet seen a decl for this key, or the last decl + // was exactly this one, we're done. + if (Old == 0 || Old == New) { + Old = New; + return; + } + + // Otherwise, decide which is a more recent redeclaration. + FunctionDecl *OldFD, *NewFD; + if (isa<FunctionTemplateDecl>(New)) { + OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl(); + NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl(); + } else { + OldFD = cast<FunctionDecl>(Old); + NewFD = cast<FunctionDecl>(New); + } + + FunctionDecl *Cursor = NewFD; + while (true) { + Cursor = Cursor->getPreviousDeclaration(); + + // If we got to the end without finding OldFD, OldFD is the newer + // declaration; leave things as they are. + if (!Cursor) return; + + // If we do find OldFD, then NewFD is newer. + if (Cursor == OldFD) break; + + // Otherwise, keep looking. + } + + Old = New; +} + +void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, + Expr **Args, unsigned NumArgs, + ADLResult &Result, + bool StdNamespaceIsAssociated) { + // Find all of the associated namespaces and classes based on the + // arguments we have. + AssociatedNamespaceSet AssociatedNamespaces; + AssociatedClassSet AssociatedClasses; + FindAssociatedClassesAndNamespaces(Args, NumArgs, + AssociatedNamespaces, + AssociatedClasses); + if (StdNamespaceIsAssociated && StdNamespace) + AssociatedNamespaces.insert(getStdNamespace()); + + QualType T1, T2; + if (Operator) { + T1 = Args[0]->getType(); + if (NumArgs >= 2) + T2 = Args[1]->getType(); + } + + // C++ [basic.lookup.argdep]p3: + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains [...] then Y is + // empty. Otherwise Y is the set of declarations found in the + // namespaces associated with the argument types as described + // below. The set of declarations found by the lookup of the name + // is the union of X and Y. + // + // Here, we compute Y and add its members to the overloaded + // candidate set. + for (AssociatedNamespaceSet::iterator NS = AssociatedNamespaces.begin(), + NSEnd = AssociatedNamespaces.end(); + NS != NSEnd; ++NS) { + // When considering an associated namespace, the lookup is the + // same as the lookup performed when the associated namespace is + // used as a qualifier (3.4.3.2) except that: + // + // -- Any using-directives in the associated namespace are + // ignored. + // + // -- Any namespace-scope friend functions declared in + // associated classes are visible within their respective + // namespaces even if they are not visible during an ordinary + // lookup (11.4). + DeclContext::lookup_iterator I, E; + for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) { + NamedDecl *D = *I; + // If the only declaration here is an ordinary friend, consider + // it only if it was declared in an associated classes. + if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) { + DeclContext *LexDC = D->getLexicalDeclContext(); + if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) + continue; + } + + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + if (isa<FunctionDecl>(D)) { + if (Operator && + !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D), + T1, T2, Context)) + continue; + } else if (!isa<FunctionTemplateDecl>(D)) + continue; + + Result.insert(D); + } + } +} + +//---------------------------------------------------------------------------- +// Search for all visible declarations. +//---------------------------------------------------------------------------- +VisibleDeclConsumer::~VisibleDeclConsumer() { } + +namespace { + +class ShadowContextRAII; + +class VisibleDeclsRecord { +public: + /// \brief An entry in the shadow map, which is optimized to store a + /// single declaration (the common case) but can also store a list + /// of declarations. + class ShadowMapEntry { + typedef llvm::SmallVector<NamedDecl *, 4> DeclVector; + + /// \brief Contains either the solitary NamedDecl * or a vector + /// of declarations. + llvm::PointerUnion<NamedDecl *, DeclVector*> DeclOrVector; + + public: + ShadowMapEntry() : DeclOrVector() { } + + void Add(NamedDecl *ND); + void Destroy(); + + // Iteration. + typedef NamedDecl * const *iterator; + iterator begin(); + iterator end(); + }; + +private: + /// \brief A mapping from declaration names to the declarations that have + /// this name within a particular scope. + typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; + + /// \brief A list of shadow maps, which is used to model name hiding. + std::list<ShadowMap> ShadowMaps; + + /// \brief The declaration contexts we have already visited. + llvm::SmallPtrSet<DeclContext *, 8> VisitedContexts; + + friend class ShadowContextRAII; + +public: + /// \brief Determine whether we have already visited this context + /// (and, if not, note that we are going to visit that context now). + bool visitedContext(DeclContext *Ctx) { + return !VisitedContexts.insert(Ctx); + } + + bool alreadyVisitedContext(DeclContext *Ctx) { + return VisitedContexts.count(Ctx); + } + + /// \brief Determine whether the given declaration is hidden in the + /// current scope. + /// + /// \returns the declaration that hides the given declaration, or + /// NULL if no such declaration exists. + NamedDecl *checkHidden(NamedDecl *ND); + + /// \brief Add a declaration to the current shadow map. + void add(NamedDecl *ND) { ShadowMaps.back()[ND->getDeclName()].Add(ND); } +}; + +/// \brief RAII object that records when we've entered a shadow context. +class ShadowContextRAII { + VisibleDeclsRecord &Visible; + + typedef VisibleDeclsRecord::ShadowMap ShadowMap; + +public: + ShadowContextRAII(VisibleDeclsRecord &Visible) : Visible(Visible) { + Visible.ShadowMaps.push_back(ShadowMap()); + } + + ~ShadowContextRAII() { + for (ShadowMap::iterator E = Visible.ShadowMaps.back().begin(), + EEnd = Visible.ShadowMaps.back().end(); + E != EEnd; + ++E) + E->second.Destroy(); + + Visible.ShadowMaps.pop_back(); + } +}; + +} // end anonymous namespace + +void VisibleDeclsRecord::ShadowMapEntry::Add(NamedDecl *ND) { + if (DeclOrVector.isNull()) { + // 0 - > 1 elements: just set the single element information. + DeclOrVector = ND; + return; + } + + if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) { + // 1 -> 2 elements: create the vector of results and push in the + // existing declaration. + DeclVector *Vec = new DeclVector; + Vec->push_back(PrevND); + DeclOrVector = Vec; + } + + // Add the new element to the end of the vector. + DeclOrVector.get<DeclVector*>()->push_back(ND); +} + +void VisibleDeclsRecord::ShadowMapEntry::Destroy() { + if (DeclVector *Vec = DeclOrVector.dyn_cast<DeclVector *>()) { + delete Vec; + DeclOrVector = ((NamedDecl *)0); + } +} + +VisibleDeclsRecord::ShadowMapEntry::iterator +VisibleDeclsRecord::ShadowMapEntry::begin() { + if (DeclOrVector.isNull()) + return 0; + + if (DeclOrVector.is<NamedDecl *>()) + return DeclOrVector.getAddrOf<NamedDecl *>(); + + return DeclOrVector.get<DeclVector *>()->begin(); +} + +VisibleDeclsRecord::ShadowMapEntry::iterator +VisibleDeclsRecord::ShadowMapEntry::end() { + if (DeclOrVector.isNull()) + return 0; + + if (DeclOrVector.is<NamedDecl *>()) + return DeclOrVector.getAddrOf<NamedDecl *>() + 1; + + return DeclOrVector.get<DeclVector *>()->end(); +} + +NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { + // Look through using declarations. + ND = ND->getUnderlyingDecl(); + + unsigned IDNS = ND->getIdentifierNamespace(); + std::list<ShadowMap>::reverse_iterator SM = ShadowMaps.rbegin(); + for (std::list<ShadowMap>::reverse_iterator SMEnd = ShadowMaps.rend(); + SM != SMEnd; ++SM) { + ShadowMap::iterator Pos = SM->find(ND->getDeclName()); + if (Pos == SM->end()) + continue; + + for (ShadowMapEntry::iterator I = Pos->second.begin(), + IEnd = Pos->second.end(); + I != IEnd; ++I) { + // A tag declaration does not hide a non-tag declaration. + if ((*I)->hasTagIdentifierNamespace() && + (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | + Decl::IDNS_ObjCProtocol))) + continue; + + // Protocols are in distinct namespaces from everything else. + if ((((*I)->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) + || (IDNS & Decl::IDNS_ObjCProtocol)) && + (*I)->getIdentifierNamespace() != IDNS) + continue; + + // Functions and function templates in the same scope overload + // rather than hide. FIXME: Look for hiding based on function + // signatures! + if ((*I)->isFunctionOrFunctionTemplate() && + ND->isFunctionOrFunctionTemplate() && + SM == ShadowMaps.rbegin()) + continue; + + // We've found a declaration that hides this one. + return *I; + } + } + + return 0; +} + +static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, + bool QualifiedNameLookup, + bool InBaseClass, + VisibleDeclConsumer &Consumer, + VisibleDeclsRecord &Visited) { + if (!Ctx) + return; + + // Make sure we don't visit the same context twice. + if (Visited.visitedContext(Ctx->getPrimaryContext())) + return; + + if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) + Result.getSema().ForceDeclarationOfImplicitMembers(Class); + + // Enumerate all of the results in this context. + for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; + CurCtx = CurCtx->getNextContext()) { + for (DeclContext::decl_iterator D = CurCtx->decls_begin(), + DEnd = CurCtx->decls_end(); + D != DEnd; ++D) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) { + if (Result.isAcceptableDecl(ND)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass); + Visited.add(ND); + } + } else if (ObjCForwardProtocolDecl *ForwardProto + = dyn_cast<ObjCForwardProtocolDecl>(*D)) { + for (ObjCForwardProtocolDecl::protocol_iterator + P = ForwardProto->protocol_begin(), + PEnd = ForwardProto->protocol_end(); + P != PEnd; + ++P) { + if (Result.isAcceptableDecl(*P)) { + Consumer.FoundDecl(*P, Visited.checkHidden(*P), InBaseClass); + Visited.add(*P); + } + } + } else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) { + for (ObjCClassDecl::iterator I = Class->begin(), IEnd = Class->end(); + I != IEnd; ++I) { + ObjCInterfaceDecl *IFace = I->getInterface(); + if (Result.isAcceptableDecl(IFace)) { + Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), InBaseClass); + Visited.add(IFace); + } + } + } + + // Visit transparent contexts and inline namespaces inside this context. + if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) { + if (InnerCtx->isTransparentContext() || InnerCtx->isInlineNamespace()) + LookupVisibleDecls(InnerCtx, Result, QualifiedNameLookup, InBaseClass, + Consumer, Visited); + } + } + } + + // Traverse using directives for qualified name lookup. + if (QualifiedNameLookup) { + ShadowContextRAII Shadow(Visited); + DeclContext::udir_iterator I, E; + for (llvm::tie(I, E) = Ctx->getUsingDirectives(); I != E; ++I) { + LookupVisibleDecls((*I)->getNominatedNamespace(), Result, + QualifiedNameLookup, InBaseClass, Consumer, Visited); + } + } + + // Traverse the contexts of inherited C++ classes. + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) { + if (!Record->hasDefinition()) + return; + + for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(), + BEnd = Record->bases_end(); + B != BEnd; ++B) { + QualType BaseType = B->getType(); + + // Don't look into dependent bases, because name lookup can't look + // there anyway. + if (BaseType->isDependentType()) + continue; + + const RecordType *Record = BaseType->getAs<RecordType>(); + if (!Record) + continue; + + // FIXME: It would be nice to be able to determine whether referencing + // a particular member would be ambiguous. For example, given + // + // struct A { int member; }; + // struct B { int member; }; + // struct C : A, B { }; + // + // void f(C *c) { c->### } + // + // accessing 'member' would result in an ambiguity. However, we + // could be smart enough to qualify the member with the base + // class, e.g., + // + // c->B::member + // + // or + // + // c->A::member + + // Find results in this base class (and its bases). + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(Record->getDecl(), Result, QualifiedNameLookup, + true, Consumer, Visited); + } + } + + // Traverse the contexts of Objective-C classes. + if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Ctx)) { + // Traverse categories. + for (ObjCCategoryDecl *Category = IFace->getCategoryList(); + Category; Category = Category->getNextClassCategory()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(Category, Result, QualifiedNameLookup, false, + Consumer, Visited); + } + + // Traverse protocols. + for (ObjCInterfaceDecl::all_protocol_iterator + I = IFace->all_referenced_protocol_begin(), + E = IFace->all_referenced_protocol_end(); I != E; ++I) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, + Visited); + } + + // Traverse the superclass. + if (IFace->getSuperClass()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(IFace->getSuperClass(), Result, QualifiedNameLookup, + true, Consumer, Visited); + } + + // If there is an implementation, traverse it. We do this to find + // synthesized ivars. + if (IFace->getImplementation()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(IFace->getImplementation(), Result, + QualifiedNameLookup, true, Consumer, Visited); + } + } else if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Ctx)) { + for (ObjCProtocolDecl::protocol_iterator I = Protocol->protocol_begin(), + E = Protocol->protocol_end(); I != E; ++I) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, + Visited); + } + } else if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Ctx)) { + for (ObjCCategoryDecl::protocol_iterator I = Category->protocol_begin(), + E = Category->protocol_end(); I != E; ++I) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, + Visited); + } + + // If there is an implementation, traverse it. + if (Category->getImplementation()) { + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(Category->getImplementation(), Result, + QualifiedNameLookup, true, Consumer, Visited); + } + } +} + +static void LookupVisibleDecls(Scope *S, LookupResult &Result, + UnqualUsingDirectiveSet &UDirs, + VisibleDeclConsumer &Consumer, + VisibleDeclsRecord &Visited) { + if (!S) + return; + + if (!S->getEntity() || + (!S->getParent() && + !Visited.alreadyVisitedContext((DeclContext *)S->getEntity())) || + ((DeclContext *)S->getEntity())->isFunctionOrMethod()) { + // Walk through the declarations in this Scope. + for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); + D != DEnd; ++D) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) + if (Result.isAcceptableDecl(ND)) { + Consumer.FoundDecl(ND, Visited.checkHidden(ND), false); + Visited.add(ND); + } + } + } + + // FIXME: C++ [temp.local]p8 + DeclContext *Entity = 0; + if (S->getEntity()) { + // Look into this scope's declaration context, along with any of its + // parent lookup contexts (e.g., enclosing classes), up to the point + // where we hit the context stored in the next outer scope. + Entity = (DeclContext *)S->getEntity(); + DeclContext *OuterCtx = findOuterContext(S).first; // FIXME + + for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx); + Ctx = Ctx->getLookupParent()) { + if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(Ctx)) { + if (Method->isInstanceMethod()) { + // For instance methods, look for ivars in the method's interface. + LookupResult IvarResult(Result.getSema(), Result.getLookupName(), + Result.getNameLoc(), Sema::LookupMemberName); + if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) { + LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + + // Look for properties from which we can synthesize ivars, if + // permitted. + if (Result.getSema().getLangOptions().ObjCNonFragileABI2 && + IFace->getImplementation() && + Result.getLookupKind() == Sema::LookupOrdinaryName) { + for (ObjCInterfaceDecl::prop_iterator + P = IFace->prop_begin(), + PEnd = IFace->prop_end(); + P != PEnd; ++P) { + if (Result.getSema().canSynthesizeProvisionalIvar(*P) && + !IFace->lookupInstanceVariable((*P)->getIdentifier())) { + Consumer.FoundDecl(*P, Visited.checkHidden(*P), false); + Visited.add(*P); + } + } + } + } + } + + // We've already performed all of the name lookup that we need + // to for Objective-C methods; the next context will be the + // outer scope. + break; + } + + if (Ctx->isFunctionOrMethod()) + continue; + + LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + } + } else if (!S->getParent()) { + // Look into the translation unit scope. We walk through the translation + // unit's declaration context, because the Scope itself won't have all of + // the declarations if we loaded a precompiled header. + // FIXME: We would like the translation unit's Scope object to point to the + // translation unit, so we don't need this special "if" branch. However, + // doing so would force the normal C++ name-lookup code to look into the + // translation unit decl when the IdentifierInfo chains would suffice. + // Once we fix that problem (which is part of a more general "don't look + // in DeclContexts unless we have to" optimization), we can eliminate this. + Entity = Result.getSema().Context.getTranslationUnitDecl(); + LookupVisibleDecls(Entity, Result, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + } + + if (Entity) { + // Lookup visible declarations in any namespaces found by using + // directives. + UnqualUsingDirectiveSet::const_iterator UI, UEnd; + llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(Entity); + for (; UI != UEnd; ++UI) + LookupVisibleDecls(const_cast<DeclContext *>(UI->getNominatedNamespace()), + Result, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); + } + + // Lookup names in the parent scope. + ShadowContextRAII Shadow(Visited); + LookupVisibleDecls(S->getParent(), Result, UDirs, Consumer, Visited); +} + +void Sema::LookupVisibleDecls(Scope *S, LookupNameKind Kind, + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope) { + // Determine the set of using directives available during + // unqualified name lookup. + Scope *Initial = S; + UnqualUsingDirectiveSet UDirs; + if (getLangOptions().CPlusPlus) { + // Find the first namespace or translation-unit scope. + while (S && !isNamespaceOrTranslationUnitScope(S)) + S = S->getParent(); + + UDirs.visitScopeChain(Initial, S); + } + UDirs.done(); + + // Look for visible declarations. + LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + VisibleDeclsRecord Visited; + if (!IncludeGlobalScope) + Visited.visitedContext(Context.getTranslationUnitDecl()); + ShadowContextRAII Shadow(Visited); + ::LookupVisibleDecls(Initial, Result, UDirs, Consumer, Visited); +} + +void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, + VisibleDeclConsumer &Consumer, + bool IncludeGlobalScope) { + LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind); + VisibleDeclsRecord Visited; + if (!IncludeGlobalScope) + Visited.visitedContext(Context.getTranslationUnitDecl()); + ShadowContextRAII Shadow(Visited); + ::LookupVisibleDecls(Ctx, Result, /*QualifiedNameLookup=*/true, + /*InBaseClass=*/false, Consumer, Visited); +} + +/// LookupOrCreateLabel - Do a name lookup of a label with the specified name. +/// If GnuLabelLoc is a valid source location, then this is a definition +/// of an __label__ label name, otherwise it is a normal label definition +/// or use. +LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, + SourceLocation GnuLabelLoc) { + // Do a lookup to see if we have a label with this name already. + NamedDecl *Res = 0; + + if (GnuLabelLoc.isValid()) { + // Local label definitions always shadow existing labels. + Res = LabelDecl::Create(Context, CurContext, Loc, II, GnuLabelLoc); + Scope *S = CurScope; + PushOnScopeChains(Res, S, true); + return cast<LabelDecl>(Res); + } + + // Not a GNU local label. + Res = LookupSingleName(CurScope, II, Loc, LookupLabel, NotForRedeclaration); + // If we found a label, check to see if it is in the same context as us. + // When in a Block, we don't want to reuse a label in an enclosing function. + if (Res && Res->getDeclContext() != CurContext) + Res = 0; + if (Res == 0) { + // If not forward referenced or defined already, create the backing decl. + Res = LabelDecl::Create(Context, CurContext, Loc, II); + Scope *S = CurScope->getFnParent(); + assert(S && "Not in a function?"); + PushOnScopeChains(Res, S, true); + } + return cast<LabelDecl>(Res); +} + +//===----------------------------------------------------------------------===// +// Typo correction +//===----------------------------------------------------------------------===// + +namespace { +class TypoCorrectionConsumer : public VisibleDeclConsumer { + /// \brief The name written that is a typo in the source. + llvm::StringRef Typo; + + /// \brief The results found that have the smallest edit distance + /// found (so far) with the typo name. + /// + /// The boolean value indicates whether there is a keyword with this name. + llvm::StringMap<bool, llvm::BumpPtrAllocator> BestResults; + + /// \brief The best edit distance found so far. + unsigned BestEditDistance; + +public: + explicit TypoCorrectionConsumer(IdentifierInfo *Typo) + : Typo(Typo->getName()), + BestEditDistance((std::numeric_limits<unsigned>::max)()) { } + + virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass); + void FoundName(llvm::StringRef Name); + void addKeywordResult(ASTContext &Context, llvm::StringRef Keyword); + + typedef llvm::StringMap<bool, llvm::BumpPtrAllocator>::iterator iterator; + iterator begin() { return BestResults.begin(); } + iterator end() { return BestResults.end(); } + void erase(iterator I) { BestResults.erase(I); } + unsigned size() const { return BestResults.size(); } + bool empty() const { return BestResults.empty(); } + + bool &operator[](llvm::StringRef Name) { + return BestResults[Name]; + } + + unsigned getBestEditDistance() const { return BestEditDistance; } +}; + +} + +void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, + bool InBaseClass) { + // Don't consider hidden names for typo correction. + if (Hiding) + return; + + // Only consider entities with identifiers for names, ignoring + // special names (constructors, overloaded operators, selectors, + // etc.). + IdentifierInfo *Name = ND->getIdentifier(); + if (!Name) + return; + + FoundName(Name->getName()); +} + +void TypoCorrectionConsumer::FoundName(llvm::StringRef Name) { + // Use a simple length-based heuristic to determine the minimum possible + // edit distance. If the minimum isn't good enough, bail out early. + unsigned MinED = abs((int)Name.size() - (int)Typo.size()); + if (MinED > BestEditDistance || (MinED && Typo.size() / MinED < 3)) + return; + + // Compute an upper bound on the allowable edit distance, so that the + // edit-distance algorithm can short-circuit. + unsigned UpperBound = + std::min(unsigned((Typo.size() + 2) / 3), BestEditDistance); + + // Compute the edit distance between the typo and the name of this + // entity. If this edit distance is not worse than the best edit + // distance we've seen so far, add it to the list of results. + unsigned ED = Typo.edit_distance(Name, true, UpperBound); + if (ED == 0) + return; + + if (ED < BestEditDistance) { + // This result is better than any we've seen before; clear out + // the previous results. + BestResults.clear(); + BestEditDistance = ED; + } else if (ED > BestEditDistance) { + // This result is worse than the best results we've seen so far; + // ignore it. + return; + } + + // Add this name to the list of results. By not assigning a value, we + // keep the current value if we've seen this name before (either as a + // keyword or as a declaration), or get the default value (not a keyword) + // if we haven't seen it before. + (void)BestResults[Name]; +} + +void TypoCorrectionConsumer::addKeywordResult(ASTContext &Context, + llvm::StringRef Keyword) { + // Compute the edit distance between the typo and this keyword. + // If this edit distance is not worse than the best edit + // distance we've seen so far, add it to the list of results. + unsigned ED = Typo.edit_distance(Keyword); + if (ED < BestEditDistance) { + BestResults.clear(); + BestEditDistance = ED; + } else if (ED > BestEditDistance) { + // This result is worse than the best results we've seen so far; + // ignore it. + return; + } + + BestResults[Keyword] = true; +} + +/// \brief Perform name lookup for a possible result for typo correction. +static void LookupPotentialTypoResult(Sema &SemaRef, + LookupResult &Res, + IdentifierInfo *Name, + Scope *S, CXXScopeSpec *SS, + DeclContext *MemberContext, + bool EnteringContext, + Sema::CorrectTypoContext CTC) { + Res.suppressDiagnostics(); + Res.clear(); + Res.setLookupName(Name); + if (MemberContext) { + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) { + if (CTC == Sema::CTC_ObjCIvarLookup) { + if (ObjCIvarDecl *Ivar = Class->lookupInstanceVariable(Name)) { + Res.addDecl(Ivar); + Res.resolveKind(); + return; + } + } + + if (ObjCPropertyDecl *Prop = Class->FindPropertyDeclaration(Name)) { + Res.addDecl(Prop); + Res.resolveKind(); + return; + } + } + + SemaRef.LookupQualifiedName(Res, MemberContext); + return; + } + + SemaRef.LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, + EnteringContext); + + // Fake ivar lookup; this should really be part of + // LookupParsedName. + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { + if (Method->isInstanceMethod() && Method->getClassInterface() && + (Res.empty() || + (Res.isSingleResult() && + Res.getFoundDecl()->isDefinedOutsideFunctionOrMethod()))) { + if (ObjCIvarDecl *IV + = Method->getClassInterface()->lookupInstanceVariable(Name)) { + Res.addDecl(IV); + Res.resolveKind(); + } + } + } +} + +/// \brief Try to "correct" a typo in the source code by finding +/// visible declarations whose names are similar to the name that was +/// present in the source code. +/// +/// \param Res the \c LookupResult structure that contains the name +/// that was present in the source code along with the name-lookup +/// criteria used to search for the name. On success, this structure +/// will contain the results of name lookup. +/// +/// \param S the scope in which name lookup occurs. +/// +/// \param SS the nested-name-specifier that precedes the name we're +/// looking for, if present. +/// +/// \param MemberContext if non-NULL, the context in which to look for +/// a member access expression. +/// +/// \param EnteringContext whether we're entering the context described by +/// the nested-name-specifier SS. +/// +/// \param CTC The context in which typo correction occurs, which impacts the +/// set of keywords permitted. +/// +/// \param OPT when non-NULL, the search for visible declarations will +/// also walk the protocols in the qualified interfaces of \p OPT. +/// +/// \returns the corrected name if the typo was corrected, otherwise returns an +/// empty \c DeclarationName. When a typo was corrected, the result structure +/// may contain the results of name lookup for the correct name or it may be +/// empty. +DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, + DeclContext *MemberContext, + bool EnteringContext, + CorrectTypoContext CTC, + const ObjCObjectPointerType *OPT) { + if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking) + return DeclarationName(); + + // We only attempt to correct typos for identifiers. + IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo(); + if (!Typo) + return DeclarationName(); + + // If the scope specifier itself was invalid, don't try to correct + // typos. + if (SS && SS->isInvalid()) + return DeclarationName(); + + // Never try to correct typos during template deduction or + // instantiation. + if (!ActiveTemplateInstantiations.empty()) + return DeclarationName(); + + TypoCorrectionConsumer Consumer(Typo); + + // Perform name lookup to find visible, similarly-named entities. + bool IsUnqualifiedLookup = false; + if (MemberContext) { + LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer); + + // Look in qualified interfaces. + if (OPT) { + for (ObjCObjectPointerType::qual_iterator + I = OPT->qual_begin(), E = OPT->qual_end(); + I != E; ++I) + LookupVisibleDecls(*I, Res.getLookupKind(), Consumer); + } + } else if (SS && SS->isSet()) { + DeclContext *DC = computeDeclContext(*SS, EnteringContext); + if (!DC) + return DeclarationName(); + + // Provide a stop gap for files that are just seriously broken. Trying + // to correct all typos can turn into a HUGE performance penalty, causing + // some files to take minutes to get rejected by the parser. + if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20) + return DeclarationName(); + ++TyposCorrected; + + LookupVisibleDecls(DC, Res.getLookupKind(), Consumer); + } else { + IsUnqualifiedLookup = true; + UnqualifiedTyposCorrectedMap::iterator Cached + = UnqualifiedTyposCorrected.find(Typo); + if (Cached == UnqualifiedTyposCorrected.end()) { + // Provide a stop gap for files that are just seriously broken. Trying + // to correct all typos can turn into a HUGE performance penalty, causing + // some files to take minutes to get rejected by the parser. + if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20) + return DeclarationName(); + + // For unqualified lookup, look through all of the names that we have + // seen in this translation unit. + for (IdentifierTable::iterator I = Context.Idents.begin(), + IEnd = Context.Idents.end(); + I != IEnd; ++I) + Consumer.FoundName(I->getKey()); + + // Walk through identifiers in external identifier sources. + if (IdentifierInfoLookup *External + = Context.Idents.getExternalIdentifierLookup()) { + llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers()); + do { + llvm::StringRef Name = Iter->Next(); + if (Name.empty()) + break; + + Consumer.FoundName(Name); + } while (true); + } + } else { + // Use the cached value, unless it's a keyword. In the keyword case, we'll + // end up adding the keyword below. + if (Cached->second.first.empty()) + return DeclarationName(); + + if (!Cached->second.second) + Consumer.FoundName(Cached->second.first); + } + } + + // Add context-dependent keywords. + bool WantTypeSpecifiers = false; + bool WantExpressionKeywords = false; + bool WantCXXNamedCasts = false; + bool WantRemainingKeywords = false; + switch (CTC) { + case CTC_Unknown: + WantTypeSpecifiers = true; + WantExpressionKeywords = true; + WantCXXNamedCasts = true; + WantRemainingKeywords = true; + + if (ObjCMethodDecl *Method = getCurMethodDecl()) + if (Method->getClassInterface() && + Method->getClassInterface()->getSuperClass()) + Consumer.addKeywordResult(Context, "super"); + + break; + + case CTC_NoKeywords: + break; + + case CTC_Type: + WantTypeSpecifiers = true; + break; + + case CTC_ObjCMessageReceiver: + Consumer.addKeywordResult(Context, "super"); + // Fall through to handle message receivers like expressions. + + case CTC_Expression: + if (getLangOptions().CPlusPlus) + WantTypeSpecifiers = true; + WantExpressionKeywords = true; + // Fall through to get C++ named casts. + + case CTC_CXXCasts: + WantCXXNamedCasts = true; + break; + + case CTC_ObjCPropertyLookup: + // FIXME: Add "isa"? + break; + + case CTC_MemberLookup: + if (getLangOptions().CPlusPlus) + Consumer.addKeywordResult(Context, "template"); + break; + + case CTC_ObjCIvarLookup: + break; + } + + if (WantTypeSpecifiers) { + // Add type-specifier keywords to the set of results. + const char *CTypeSpecs[] = { + "char", "const", "double", "enum", "float", "int", "long", "short", + "signed", "struct", "union", "unsigned", "void", "volatile", "_Bool", + "_Complex", "_Imaginary", + // storage-specifiers as well + "extern", "inline", "static", "typedef" + }; + + const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]); + for (unsigned I = 0; I != NumCTypeSpecs; ++I) + Consumer.addKeywordResult(Context, CTypeSpecs[I]); + + if (getLangOptions().C99) + Consumer.addKeywordResult(Context, "restrict"); + if (getLangOptions().Bool || getLangOptions().CPlusPlus) + Consumer.addKeywordResult(Context, "bool"); + + if (getLangOptions().CPlusPlus) { + Consumer.addKeywordResult(Context, "class"); + Consumer.addKeywordResult(Context, "typename"); + Consumer.addKeywordResult(Context, "wchar_t"); + + if (getLangOptions().CPlusPlus0x) { + Consumer.addKeywordResult(Context, "char16_t"); + Consumer.addKeywordResult(Context, "char32_t"); + Consumer.addKeywordResult(Context, "constexpr"); + Consumer.addKeywordResult(Context, "decltype"); + Consumer.addKeywordResult(Context, "thread_local"); + } + } + + if (getLangOptions().GNUMode) + Consumer.addKeywordResult(Context, "typeof"); + } + + if (WantCXXNamedCasts && getLangOptions().CPlusPlus) { + Consumer.addKeywordResult(Context, "const_cast"); + Consumer.addKeywordResult(Context, "dynamic_cast"); + Consumer.addKeywordResult(Context, "reinterpret_cast"); + Consumer.addKeywordResult(Context, "static_cast"); + } + + if (WantExpressionKeywords) { + Consumer.addKeywordResult(Context, "sizeof"); + if (getLangOptions().Bool || getLangOptions().CPlusPlus) { + Consumer.addKeywordResult(Context, "false"); + Consumer.addKeywordResult(Context, "true"); + } + + if (getLangOptions().CPlusPlus) { + const char *CXXExprs[] = { + "delete", "new", "operator", "throw", "typeid" + }; + const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]); + for (unsigned I = 0; I != NumCXXExprs; ++I) + Consumer.addKeywordResult(Context, CXXExprs[I]); + + if (isa<CXXMethodDecl>(CurContext) && + cast<CXXMethodDecl>(CurContext)->isInstance()) + Consumer.addKeywordResult(Context, "this"); + + if (getLangOptions().CPlusPlus0x) { + Consumer.addKeywordResult(Context, "alignof"); + Consumer.addKeywordResult(Context, "nullptr"); + } + } + } + + if (WantRemainingKeywords) { + if (getCurFunctionOrMethodDecl() || getCurBlock()) { + // Statements. + const char *CStmts[] = { + "do", "else", "for", "goto", "if", "return", "switch", "while" }; + const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]); + for (unsigned I = 0; I != NumCStmts; ++I) + Consumer.addKeywordResult(Context, CStmts[I]); + + if (getLangOptions().CPlusPlus) { + Consumer.addKeywordResult(Context, "catch"); + Consumer.addKeywordResult(Context, "try"); + } + + if (S && S->getBreakParent()) + Consumer.addKeywordResult(Context, "break"); + + if (S && S->getContinueParent()) + Consumer.addKeywordResult(Context, "continue"); + + if (!getCurFunction()->SwitchStack.empty()) { + Consumer.addKeywordResult(Context, "case"); + Consumer.addKeywordResult(Context, "default"); + } + } else { + if (getLangOptions().CPlusPlus) { + Consumer.addKeywordResult(Context, "namespace"); + Consumer.addKeywordResult(Context, "template"); + } + + if (S && S->isClassScope()) { + Consumer.addKeywordResult(Context, "explicit"); + Consumer.addKeywordResult(Context, "friend"); + Consumer.addKeywordResult(Context, "mutable"); + Consumer.addKeywordResult(Context, "private"); + Consumer.addKeywordResult(Context, "protected"); + Consumer.addKeywordResult(Context, "public"); + Consumer.addKeywordResult(Context, "virtual"); + } + } + + if (getLangOptions().CPlusPlus) { + Consumer.addKeywordResult(Context, "using"); + + if (getLangOptions().CPlusPlus0x) + Consumer.addKeywordResult(Context, "static_assert"); + } + } + + // If we haven't found anything, we're done. + if (Consumer.empty()) { + // If this was an unqualified lookup, note that no correction was found. + if (IsUnqualifiedLookup) + (void)UnqualifiedTyposCorrected[Typo]; + + return DeclarationName(); + } + + // Make sure that the user typed at least 3 characters for each correction + // made. Otherwise, we don't even both looking at the results. + + // We also suppress exact matches; those should be handled by a + // different mechanism (e.g., one that introduces qualification in + // C++). + unsigned ED = Consumer.getBestEditDistance(); + if (ED > 0 && Typo->getName().size() / ED < 3) { + // If this was an unqualified lookup, note that no correction was found. + if (IsUnqualifiedLookup) + (void)UnqualifiedTyposCorrected[Typo]; + + return DeclarationName(); + } + + // Weed out any names that could not be found by name lookup. + bool LastLookupWasAccepted = false; + for (TypoCorrectionConsumer::iterator I = Consumer.begin(), + IEnd = Consumer.end(); + I != IEnd; /* Increment in loop. */) { + // Keywords are always found. + if (I->second) { + ++I; + continue; + } + + // Perform name lookup on this name. + IdentifierInfo *Name = &Context.Idents.get(I->getKey()); + LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext, + EnteringContext, CTC); + + switch (Res.getResultKind()) { + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + case LookupResult::Ambiguous: + // We didn't find this name in our scope, or didn't like what we found; + // ignore it. + Res.suppressDiagnostics(); + { + TypoCorrectionConsumer::iterator Next = I; + ++Next; + Consumer.erase(I); + I = Next; + } + LastLookupWasAccepted = false; + break; + + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + ++I; + LastLookupWasAccepted = true; + break; + } + + if (Res.isAmbiguous()) { + // We don't deal with ambiguities. + Res.suppressDiagnostics(); + Res.clear(); + return DeclarationName(); + } + } + + // If only a single name remains, return that result. + if (Consumer.size() == 1) { + IdentifierInfo *Name = &Context.Idents.get(Consumer.begin()->getKey()); + if (Consumer.begin()->second) { + Res.suppressDiagnostics(); + Res.clear(); + + // Don't correct to a keyword that's the same as the typo; the keyword + // wasn't actually in scope. + if (ED == 0) { + Res.setLookupName(Typo); + return DeclarationName(); + } + + } else if (!LastLookupWasAccepted) { + // Perform name lookup on this name. + LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext, + EnteringContext, CTC); + } + + // Record the correction for unqualified lookup. + if (IsUnqualifiedLookup) + UnqualifiedTyposCorrected[Typo] + = std::make_pair(Name->getName(), Consumer.begin()->second); + + return &Context.Idents.get(Consumer.begin()->getKey()); + } + else if (Consumer.size() > 1 && CTC == CTC_ObjCMessageReceiver + && Consumer["super"]) { + // Prefix 'super' when we're completing in a message-receiver + // context. + Res.suppressDiagnostics(); + Res.clear(); + + // Don't correct to a keyword that's the same as the typo; the keyword + // wasn't actually in scope. + if (ED == 0) { + Res.setLookupName(Typo); + return DeclarationName(); + } + + // Record the correction for unqualified lookup. + if (IsUnqualifiedLookup) + UnqualifiedTyposCorrected[Typo] + = std::make_pair("super", Consumer.begin()->second); + + return &Context.Idents.get("super"); + } + + Res.suppressDiagnostics(); + Res.setLookupName(Typo); + Res.clear(); + // Record the correction for unqualified lookup. + if (IsUnqualifiedLookup) + (void)UnqualifiedTyposCorrected[Typo]; + + return DeclarationName(); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp new file mode 100644 index 0000000..6c4469c --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -0,0 +1,1371 @@ +//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for Objective C @property and +// @synthesize declarations. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Initialization.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprObjC.h" +#include "llvm/ADT/DenseSet.h" + +using namespace clang; + +//===----------------------------------------------------------------------===// +// Grammar actions. +//===----------------------------------------------------------------------===// + +Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, + FieldDeclarator &FD, + ObjCDeclSpec &ODS, + Selector GetterSel, + Selector SetterSel, + Decl *ClassCategory, + bool *isOverridingProperty, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC) { + unsigned Attributes = ODS.getPropertyAttributes(); + bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || + // default is readwrite! + !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); + // property is defaulted to 'assign' if it is readwrite and is + // not retain or copy + bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || + (isReadWrite && + !(Attributes & ObjCDeclSpec::DQ_PR_retain) && + !(Attributes & ObjCDeclSpec::DQ_PR_copy))); + + TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); + + // Proceed with constructing the ObjCPropertDecls. + ObjCContainerDecl *ClassDecl = + cast<ObjCContainerDecl>(ClassCategory); + + if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) + if (CDecl->IsClassExtension()) { + Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc, + FD, GetterSel, SetterSel, + isAssign, isReadWrite, + Attributes, + isOverridingProperty, TSI, + MethodImplKind); + if (Res) + CheckObjCPropertyAttributes(Res, AtLoc, Attributes); + return Res; + } + + Decl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD, + GetterSel, SetterSel, + isAssign, isReadWrite, + Attributes, TSI, MethodImplKind); + if (lexicalDC) + Res->setLexicalDeclContext(lexicalDC); + + // Validate the attributes on the @property. + CheckObjCPropertyAttributes(Res, AtLoc, Attributes); + return Res; +} + +Decl * +Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, + SourceLocation AtLoc, FieldDeclarator &FD, + Selector GetterSel, Selector SetterSel, + const bool isAssign, + const bool isReadWrite, + const unsigned Attributes, + bool *isOverridingProperty, + TypeSourceInfo *T, + tok::ObjCKeywordKind MethodImplKind) { + + // Diagnose if this property is already in continuation class. + DeclContext *DC = cast<DeclContext>(CDecl); + IdentifierInfo *PropertyId = FD.D.getIdentifier(); + ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); + + if (CCPrimary) + // Check for duplicate declaration of this property in current and + // other class extensions. + for (const ObjCCategoryDecl *ClsExtDecl = + CCPrimary->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + if (ObjCPropertyDecl *prevDecl = + ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) { + Diag(AtLoc, diag::err_duplicate_property); + Diag(prevDecl->getLocation(), diag::note_property_declare); + return 0; + } + } + + // Create a new ObjCPropertyDecl with the DeclContext being + // the class extension. + // FIXME. We should really be using CreatePropertyDecl for this. + ObjCPropertyDecl *PDecl = + ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), + PropertyId, AtLoc, T); + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); + if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); + // Set setter/getter selector name. Needed later. + PDecl->setGetterName(GetterSel); + PDecl->setSetterName(SetterSel); + DC->addDecl(PDecl); + + // We need to look in the @interface to see if the @property was + // already declared. + if (!CCPrimary) { + Diag(CDecl->getLocation(), diag::err_continuation_class); + *isOverridingProperty = true; + return 0; + } + + // Find the property in continuation class's primary class only. + ObjCPropertyDecl *PIDecl = + CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); + + if (!PIDecl) { + // No matching property found in the primary class. Just fall thru + // and add property to continuation class's primary class. + ObjCPropertyDecl *PDecl = + CreatePropertyDecl(S, CCPrimary, AtLoc, + FD, GetterSel, SetterSel, isAssign, isReadWrite, + Attributes, T, MethodImplKind, DC); + // Mark written attribute as having no attribute because + // this is not a user-written property declaration in primary + // class. + PDecl->setPropertyAttributesAsWritten(ObjCPropertyDecl::OBJC_PR_noattr); + + // A case of continuation class adding a new property in the class. This + // is not what it was meant for. However, gcc supports it and so should we. + // Make sure setter/getters are declared here. + ProcessPropertyDecl(PDecl, CCPrimary, /* redeclaredProperty = */ 0, + /* lexicalDC = */ CDecl); + return PDecl; + } + + // The property 'PIDecl's readonly attribute will be over-ridden + // with continuation class's readwrite property attribute! + unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); + if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { + unsigned retainCopyNonatomic = + (ObjCPropertyDecl::OBJC_PR_retain | + ObjCPropertyDecl::OBJC_PR_copy | + ObjCPropertyDecl::OBJC_PR_nonatomic); + if ((Attributes & retainCopyNonatomic) != + (PIkind & retainCopyNonatomic)) { + Diag(AtLoc, diag::warn_property_attr_mismatch); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + DeclContext *DC = cast<DeclContext>(CCPrimary); + if (!ObjCPropertyDecl::findPropertyDecl(DC, + PIDecl->getDeclName().getAsIdentifierInfo())) { + // Protocol is not in the primary class. Must build one for it. + ObjCDeclSpec ProtocolPropertyODS; + // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind + // and ObjCPropertyDecl::PropertyAttributeKind have identical + // values. Should consolidate both into one enum type. + ProtocolPropertyODS. + setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) + PIkind); + + Decl *ProtocolPtrTy = + ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, + PIDecl->getGetterName(), + PIDecl->getSetterName(), + CCPrimary, isOverridingProperty, + MethodImplKind, + /* lexicalDC = */ CDecl); + PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); + } + PIDecl->makeitReadWriteAttribute(); + if (Attributes & ObjCDeclSpec::DQ_PR_retain) + PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); + if (Attributes & ObjCDeclSpec::DQ_PR_copy) + PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); + PIDecl->setSetterName(SetterSel); + } else { + // Tailor the diagnostics for the common case where a readwrite + // property is declared both in the @interface and the continuation. + // This is a common error where the user often intended the original + // declaration to be readonly. + unsigned diag = + (Attributes & ObjCDeclSpec::DQ_PR_readwrite) && + (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) + ? diag::err_use_continuation_class_redeclaration_readwrite + : diag::err_use_continuation_class; + Diag(AtLoc, diag) + << CCPrimary->getDeclName(); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } + *isOverridingProperty = true; + // Make sure setter decl is synthesized, and added to primary class's list. + ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); + return 0; +} + +ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, + ObjCContainerDecl *CDecl, + SourceLocation AtLoc, + FieldDeclarator &FD, + Selector GetterSel, + Selector SetterSel, + const bool isAssign, + const bool isReadWrite, + const unsigned Attributes, + TypeSourceInfo *TInfo, + tok::ObjCKeywordKind MethodImplKind, + DeclContext *lexicalDC){ + IdentifierInfo *PropertyId = FD.D.getIdentifier(); + QualType T = TInfo->getType(); + + // Issue a warning if property is 'assign' as default and its object, which is + // gc'able conforms to NSCopying protocol + if (getLangOptions().getGCMode() != LangOptions::NonGC && + isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) + if (const ObjCObjectPointerType *ObjPtrTy = + T->getAs<ObjCObjectPointerType>()) { + ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); + if (IDecl) + if (ObjCProtocolDecl* PNSCopying = + LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) + if (IDecl->ClassImplementsProtocol(PNSCopying, true)) + Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; + } + if (T->isObjCObjectType()) + Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object); + + DeclContext *DC = cast<DeclContext>(CDecl); + ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, + FD.D.getIdentifierLoc(), + PropertyId, AtLoc, TInfo); + + if (ObjCPropertyDecl *prevDecl = + ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { + Diag(PDecl->getLocation(), diag::err_duplicate_property); + Diag(prevDecl->getLocation(), diag::note_property_declare); + PDecl->setInvalidDecl(); + } + else { + DC->addDecl(PDecl); + if (lexicalDC) + PDecl->setLexicalDeclContext(lexicalDC); + } + + if (T->isArrayType() || T->isFunctionType()) { + Diag(AtLoc, diag::err_property_type) << T; + PDecl->setInvalidDecl(); + } + + ProcessDeclAttributes(S, PDecl, FD.D); + + // Regardless of setter/getter attribute, we save the default getter/setter + // selector names in anticipation of declaration of setter/getter methods. + PDecl->setGetterName(GetterSel); + PDecl->setSetterName(SetterSel); + + if (Attributes & ObjCDeclSpec::DQ_PR_readonly) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); + + if (Attributes & ObjCDeclSpec::DQ_PR_getter) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); + + if (Attributes & ObjCDeclSpec::DQ_PR_setter) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); + + if (isReadWrite) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); + + if (Attributes & ObjCDeclSpec::DQ_PR_retain) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); + + if (Attributes & ObjCDeclSpec::DQ_PR_copy) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); + + if (isAssign) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); + + if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); + else if (Attributes & ObjCDeclSpec::DQ_PR_atomic) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); + + PDecl->setPropertyAttributesAsWritten(PDecl->getPropertyAttributes()); + + if (MethodImplKind == tok::objc_required) + PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); + else if (MethodImplKind == tok::objc_optional) + PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); + + return PDecl; +} + + +/// ActOnPropertyImplDecl - This routine performs semantic checks and +/// builds the AST node for a property implementation declaration; declared +/// as @synthesize or @dynamic. +/// +Decl *Sema::ActOnPropertyImplDecl(Scope *S, + SourceLocation AtLoc, + SourceLocation PropertyLoc, + bool Synthesize, + Decl *ClassCatImpDecl, + IdentifierInfo *PropertyId, + IdentifierInfo *PropertyIvar, + SourceLocation PropertyIvarLoc) { + ObjCContainerDecl *ClassImpDecl = + cast_or_null<ObjCContainerDecl>(ClassCatImpDecl); + // Make sure we have a context for the property implementation declaration. + if (!ClassImpDecl) { + Diag(AtLoc, diag::error_missing_property_context); + return 0; + } + ObjCPropertyDecl *property = 0; + ObjCInterfaceDecl* IDecl = 0; + // Find the class or category class where this property must have + // a declaration. + ObjCImplementationDecl *IC = 0; + ObjCCategoryImplDecl* CatImplClass = 0; + if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { + IDecl = IC->getClassInterface(); + // We always synthesize an interface for an implementation + // without an interface decl. So, IDecl is always non-zero. + assert(IDecl && + "ActOnPropertyImplDecl - @implementation without @interface"); + + // Look for this property declaration in the @implementation's @interface + property = IDecl->FindPropertyDeclaration(PropertyId); + if (!property) { + Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); + return 0; + } + unsigned PIkind = property->getPropertyAttributesAsWritten(); + if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic | + ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) { + if (AtLoc.isValid()) + Diag(AtLoc, diag::warn_implicit_atomic_property); + else + Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property); + Diag(property->getLocation(), diag::note_property_declare); + } + + if (const ObjCCategoryDecl *CD = + dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { + if (!CD->IsClassExtension()) { + Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); + Diag(property->getLocation(), diag::note_property_declare); + return 0; + } + } + } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { + if (Synthesize) { + Diag(AtLoc, diag::error_synthesize_category_decl); + return 0; + } + IDecl = CatImplClass->getClassInterface(); + if (!IDecl) { + Diag(AtLoc, diag::error_missing_property_interface); + return 0; + } + ObjCCategoryDecl *Category = + IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); + + // If category for this implementation not found, it is an error which + // has already been reported eralier. + if (!Category) + return 0; + // Look for this property declaration in @implementation's category + property = Category->FindPropertyDeclaration(PropertyId); + if (!property) { + Diag(PropertyLoc, diag::error_bad_category_property_decl) + << Category->getDeclName(); + return 0; + } + } else { + Diag(AtLoc, diag::error_bad_property_context); + return 0; + } + ObjCIvarDecl *Ivar = 0; + // Check that we have a valid, previously declared ivar for @synthesize + if (Synthesize) { + // @synthesize + if (!PropertyIvar) + PropertyIvar = PropertyId; + QualType PropType = Context.getCanonicalType(property->getType()); + QualType PropertyIvarType = PropType; + if (PropType->isReferenceType()) + PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType(); + // Check that this is a previously declared 'ivar' in 'IDecl' interface + ObjCInterfaceDecl *ClassDeclared; + Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); + if (!Ivar) { + Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, + PropertyLoc, PropertyLoc, PropertyIvar, + PropertyIvarType, /*Dinfo=*/0, + ObjCIvarDecl::Private, + (Expr *)0, true); + ClassImpDecl->addDecl(Ivar); + IDecl->makeDeclVisibleInContext(Ivar, false); + property->setPropertyIvarDecl(Ivar); + + if (!getLangOptions().ObjCNonFragileABI) + Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; + // Note! I deliberately want it to fall thru so, we have a + // a property implementation and to avoid future warnings. + } else if (getLangOptions().ObjCNonFragileABI && + ClassDeclared != IDecl) { + Diag(PropertyLoc, diag::error_ivar_in_superclass_use) + << property->getDeclName() << Ivar->getDeclName() + << ClassDeclared->getDeclName(); + Diag(Ivar->getLocation(), diag::note_previous_access_declaration) + << Ivar << Ivar->getName(); + // Note! I deliberately want it to fall thru so more errors are caught. + } + QualType IvarType = Context.getCanonicalType(Ivar->getType()); + + // Check that type of property and its ivar are type compatible. + if (PropertyIvarType != IvarType) { + bool compat = false; + if (isa<ObjCObjectPointerType>(PropertyIvarType) + && isa<ObjCObjectPointerType>(IvarType)) + compat = + Context.canAssignObjCInterfaces( + PropertyIvarType->getAs<ObjCObjectPointerType>(), + IvarType->getAs<ObjCObjectPointerType>()); + else { + SourceLocation Loc = PropertyIvarLoc; + if (Loc.isInvalid()) + Loc = PropertyLoc; + compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType) + == Compatible); + } + if (!compat) { + Diag(PropertyLoc, diag::error_property_ivar_type) + << property->getDeclName() << PropType + << Ivar->getDeclName() << IvarType; + Diag(Ivar->getLocation(), diag::note_ivar_decl); + // Note! I deliberately want it to fall thru so, we have a + // a property implementation and to avoid future warnings. + } + + // FIXME! Rules for properties are somewhat different that those + // for assignments. Use a new routine to consolidate all cases; + // specifically for property redeclarations as well as for ivars. + QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); + QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); + if (lhsType != rhsType && + lhsType->isArithmeticType()) { + Diag(PropertyLoc, diag::error_property_ivar_type) + << property->getDeclName() << PropType + << Ivar->getDeclName() << IvarType; + Diag(Ivar->getLocation(), diag::note_ivar_decl); + // Fall thru - see previous comment + } + // __weak is explicit. So it works on Canonical type. + if (PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && + getLangOptions().getGCMode() != LangOptions::NonGC) { + Diag(PropertyLoc, diag::error_weak_property) + << property->getDeclName() << Ivar->getDeclName(); + // Fall thru - see previous comment + } + if ((property->getType()->isObjCObjectPointerType() || + PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && + getLangOptions().getGCMode() != LangOptions::NonGC) { + Diag(PropertyLoc, diag::error_strong_property) + << property->getDeclName() << Ivar->getDeclName(); + // Fall thru - see previous comment + } + } + } else if (PropertyIvar) + // @dynamic + Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl); + assert (property && "ActOnPropertyImplDecl - property declaration missing"); + ObjCPropertyImplDecl *PIDecl = + ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, + property, + (Synthesize ? + ObjCPropertyImplDecl::Synthesize + : ObjCPropertyImplDecl::Dynamic), + Ivar, PropertyIvarLoc); + if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { + getterMethod->createImplicitParams(Context, IDecl); + if (getLangOptions().CPlusPlus && Synthesize && + Ivar->getType()->isRecordType()) { + // For Objective-C++, need to synthesize the AST for the IVAR object to be + // returned by the getter as it must conform to C++'s copy-return rules. + // FIXME. Eventually we want to do this for Objective-C as well. + ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); + DeclRefExpr *SelfExpr = + new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), + VK_RValue, SourceLocation()); + Expr *IvarRefExpr = + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + SelfExpr, true, true); + ExprResult Res = + PerformCopyInitialization(InitializedEntity::InitializeResult( + SourceLocation(), + getterMethod->getResultType(), + /*NRVO=*/false), + SourceLocation(), + Owned(IvarRefExpr)); + if (!Res.isInvalid()) { + Expr *ResExpr = Res.takeAs<Expr>(); + if (ResExpr) + ResExpr = MaybeCreateExprWithCleanups(ResExpr); + PIDecl->setGetterCXXConstructor(ResExpr); + } + } + } + if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { + setterMethod->createImplicitParams(Context, IDecl); + if (getLangOptions().CPlusPlus && Synthesize + && Ivar->getType()->isRecordType()) { + // FIXME. Eventually we want to do this for Objective-C as well. + ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); + DeclRefExpr *SelfExpr = + new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), + VK_RValue, SourceLocation()); + Expr *lhs = + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + SelfExpr, true, true); + ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); + ParmVarDecl *Param = (*P); + QualType T = Param->getType(); + if (T->isReferenceType()) + T = T->getAs<ReferenceType>()->getPointeeType(); + Expr *rhs = new (Context) DeclRefExpr(Param, T, + VK_LValue, SourceLocation()); + ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), + BO_Assign, lhs, rhs); + PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>()); + } + } + + if (IC) { + if (Synthesize) + if (ObjCPropertyImplDecl *PPIDecl = + IC->FindPropertyImplIvarDecl(PropertyIvar)) { + Diag(PropertyLoc, diag::error_duplicate_ivar_use) + << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() + << PropertyIvar; + Diag(PPIDecl->getLocation(), diag::note_previous_use); + } + + if (ObjCPropertyImplDecl *PPIDecl + = IC->FindPropertyImplDecl(PropertyId)) { + Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; + Diag(PPIDecl->getLocation(), diag::note_previous_declaration); + return 0; + } + IC->addPropertyImplementation(PIDecl); + if (getLangOptions().ObjCDefaultSynthProperties && + getLangOptions().ObjCNonFragileABI2) { + // Diagnose if an ivar was lazily synthesdized due to a previous + // use and if 1) property is @dynamic or 2) property is synthesized + // but it requires an ivar of different name. + ObjCInterfaceDecl *ClassDeclared=0; + ObjCIvarDecl *Ivar = 0; + if (!Synthesize) + Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); + else { + if (PropertyIvar && PropertyIvar != PropertyId) + Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); + } + // Issue diagnostics only if Ivar belongs to current class. + if (Ivar && Ivar->getSynthesize() && + IC->getClassInterface() == ClassDeclared) { + Diag(Ivar->getLocation(), diag::err_undeclared_var_use) + << PropertyId; + Ivar->setInvalidDecl(); + } + } + } else { + if (Synthesize) + if (ObjCPropertyImplDecl *PPIDecl = + CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { + Diag(PropertyLoc, diag::error_duplicate_ivar_use) + << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() + << PropertyIvar; + Diag(PPIDecl->getLocation(), diag::note_previous_use); + } + + if (ObjCPropertyImplDecl *PPIDecl = + CatImplClass->FindPropertyImplDecl(PropertyId)) { + Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; + Diag(PPIDecl->getLocation(), diag::note_previous_declaration); + return 0; + } + CatImplClass->addPropertyImplementation(PIDecl); + } + + return PIDecl; +} + +//===----------------------------------------------------------------------===// +// Helper methods. +//===----------------------------------------------------------------------===// + +/// DiagnosePropertyMismatch - Compares two properties for their +/// attributes and types and warns on a variety of inconsistencies. +/// +void +Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, + ObjCPropertyDecl *SuperProperty, + const IdentifierInfo *inheritedName) { + ObjCPropertyDecl::PropertyAttributeKind CAttr = + Property->getPropertyAttributes(); + ObjCPropertyDecl::PropertyAttributeKind SAttr = + SuperProperty->getPropertyAttributes(); + if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) + && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) + Diag(Property->getLocation(), diag::warn_readonly_property) + << Property->getDeclName() << inheritedName; + if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) + != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "copy" << inheritedName; + else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain) + != (SAttr & ObjCPropertyDecl::OBJC_PR_retain)) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "retain" << inheritedName; + + if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) + != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "atomic" << inheritedName; + if (Property->getSetterName() != SuperProperty->getSetterName()) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "setter" << inheritedName; + if (Property->getGetterName() != SuperProperty->getGetterName()) + Diag(Property->getLocation(), diag::warn_property_attribute) + << Property->getDeclName() << "getter" << inheritedName; + + QualType LHSType = + Context.getCanonicalType(SuperProperty->getType()); + QualType RHSType = + Context.getCanonicalType(Property->getType()); + + if (!Context.typesAreCompatible(LHSType, RHSType)) { + // FIXME: Incorporate this test with typesAreCompatible. + if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType()) + if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false)) + return; + Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) + << Property->getType() << SuperProperty->getType() << inheritedName; + } +} + +bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, + ObjCMethodDecl *GetterMethod, + SourceLocation Loc) { + if (GetterMethod && + GetterMethod->getResultType() != property->getType()) { + AssignConvertType result = Incompatible; + if (property->getType()->isObjCObjectPointerType()) + result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), + property->getType()); + if (result != Compatible) { + Diag(Loc, diag::warn_accessor_property_type_mismatch) + << property->getDeclName() + << GetterMethod->getSelector(); + Diag(GetterMethod->getLocation(), diag::note_declared_at); + return true; + } + } + return false; +} + +/// ComparePropertiesInBaseAndSuper - This routine compares property +/// declarations in base and its super class, if any, and issues +/// diagnostics in a variety of inconsistent situations. +/// +void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { + ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); + if (!SDecl) + return; + // FIXME: O(N^2) + for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(), + E = SDecl->prop_end(); S != E; ++S) { + ObjCPropertyDecl *SuperPDecl = (*S); + // Does property in super class has declaration in current class? + for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(), + E = IDecl->prop_end(); I != E; ++I) { + ObjCPropertyDecl *PDecl = (*I); + if (SuperPDecl->getIdentifier() == PDecl->getIdentifier()) + DiagnosePropertyMismatch(PDecl, SuperPDecl, + SDecl->getIdentifier()); + } + } +} + +/// MatchOneProtocolPropertiesInClass - This routine goes thru the list +/// of properties declared in a protocol and compares their attribute against +/// the same property declared in the class or category. +void +Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, + ObjCProtocolDecl *PDecl) { + ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); + if (!IDecl) { + // Category + ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); + assert (CatDecl && "MatchOneProtocolPropertiesInClass"); + if (!CatDecl->IsClassExtension()) + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Pr = (*P); + ObjCCategoryDecl::prop_iterator CP, CE; + // Is this property already in category's list of properties? + for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP) + if ((*CP)->getIdentifier() == Pr->getIdentifier()) + break; + if (CP != CE) + // Property protocol already exist in class. Diagnose any mismatch. + DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); + } + return; + } + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Pr = (*P); + ObjCInterfaceDecl::prop_iterator CP, CE; + // Is this property already in class's list of properties? + for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP) + if ((*CP)->getIdentifier() == Pr->getIdentifier()) + break; + if (CP != CE) + // Property protocol already exist in class. Diagnose any mismatch. + DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); + } +} + +/// CompareProperties - This routine compares properties +/// declared in 'ClassOrProtocol' objects (which can be a class or an +/// inherited protocol with the list of properties for class/category 'CDecl' +/// +void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) { + Decl *ClassDecl = ClassOrProtocol; + ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); + + if (!IDecl) { + // Category + ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); + assert (CatDecl && "CompareProperties"); + if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { + for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(), + E = MDecl->protocol_end(); P != E; ++P) + // Match properties of category with those of protocol (*P) + MatchOneProtocolPropertiesInClass(CatDecl, *P); + + // Go thru the list of protocols for this category and recursively match + // their properties with those in the category. + for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), + E = CatDecl->protocol_end(); P != E; ++P) + CompareProperties(CatDecl, *P); + } else { + ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); + for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), + E = MD->protocol_end(); P != E; ++P) + MatchOneProtocolPropertiesInClass(CatDecl, *P); + } + return; + } + + if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { + for (ObjCInterfaceDecl::all_protocol_iterator + P = MDecl->all_referenced_protocol_begin(), + E = MDecl->all_referenced_protocol_end(); P != E; ++P) + // Match properties of class IDecl with those of protocol (*P). + MatchOneProtocolPropertiesInClass(IDecl, *P); + + // Go thru the list of protocols for this class and recursively match + // their properties with those declared in the class. + for (ObjCInterfaceDecl::all_protocol_iterator + P = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); P != E; ++P) + CompareProperties(IDecl, *P); + } else { + ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); + for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), + E = MD->protocol_end(); P != E; ++P) + MatchOneProtocolPropertiesInClass(IDecl, *P); + } +} + +/// isPropertyReadonly - Return true if property is readonly, by searching +/// for the property in the class and in its categories and implementations +/// +bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, + ObjCInterfaceDecl *IDecl) { + // by far the most common case. + if (!PDecl->isReadOnly()) + return false; + // Even if property is ready only, if interface has a user defined setter, + // it is not considered read only. + if (IDecl->getInstanceMethod(PDecl->getSetterName())) + return false; + + // Main class has the property as 'readonly'. Must search + // through the category list to see if the property's + // attribute has been over-ridden to 'readwrite'. + for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); + Category; Category = Category->getNextClassCategory()) { + // Even if property is ready only, if a category has a user defined setter, + // it is not considered read only. + if (Category->getInstanceMethod(PDecl->getSetterName())) + return false; + ObjCPropertyDecl *P = + Category->FindPropertyDeclaration(PDecl->getIdentifier()); + if (P && !P->isReadOnly()) + return false; + } + + // Also, check for definition of a setter method in the implementation if + // all else failed. + if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) { + if (ObjCImplementationDecl *IMD = + dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) { + if (IMD->getInstanceMethod(PDecl->getSetterName())) + return false; + } else if (ObjCCategoryImplDecl *CIMD = + dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { + if (CIMD->getInstanceMethod(PDecl->getSetterName())) + return false; + } + } + // Lastly, look through the implementation (if one is in scope). + if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation()) + if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) + return false; + // If all fails, look at the super class. + if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) + return isPropertyReadonly(PDecl, SIDecl); + return true; +} + +/// CollectImmediateProperties - This routine collects all properties in +/// the class and its conforming protocols; but not those it its super class. +void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) { + if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } + // scan through class's protocols. + for (ObjCInterfaceDecl::all_protocol_iterator + PI = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) + CollectImmediateProperties((*PI), PropMap, SuperPropMap); + } + if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { + if (!CATDecl->IsClassExtension()) + for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), + E = CATDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } + // scan through class's protocols. + for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(), + E = CATDecl->protocol_end(); PI != E; ++PI) + CollectImmediateProperties((*PI), PropMap, SuperPropMap); + } + else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; + // Exclude property for protocols which conform to class's super-class, + // as super-class has to implement the property. + if (!PropertyFromSuper || PropertyFromSuper != Prop) { + ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; + if (!PropEntry) + PropEntry = Prop; + } + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + CollectImmediateProperties((*PI), PropMap, SuperPropMap); + } +} + +/// CollectClassPropertyImplementations - This routine collects list of +/// properties to be implemented in the class. This includes, class's +/// and its conforming protocols' properties. +static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { + if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } + for (ObjCInterfaceDecl::all_protocol_iterator + PI = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) + CollectClassPropertyImplementations((*PI), PropMap); + } + else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) + CollectClassPropertyImplementations((*PI), PropMap); + } +} + +/// CollectSuperClassPropertyImplementations - This routine collects list of +/// properties to be implemented in super class(s) and also coming from their +/// conforming protocols. +static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { + if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { + while (SDecl) { + CollectClassPropertyImplementations(SDecl, PropMap); + SDecl = SDecl->getSuperClass(); + } + } +} + +/// LookupPropertyDecl - Looks up a property in the current class and all +/// its protocols. +ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, + IdentifierInfo *II) { + if (const ObjCInterfaceDecl *IDecl = + dyn_cast<ObjCInterfaceDecl>(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through class's protocols. + for (ObjCInterfaceDecl::all_protocol_iterator + PI = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) { + ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); + if (Prop) + return Prop; + } + } + else if (const ObjCProtocolDecl *PDecl = + dyn_cast<ObjCProtocolDecl>(CDecl)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) { + ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); + if (Prop) + return Prop; + } + } + return 0; +} + +/// DefaultSynthesizeProperties - This routine default synthesizes all +/// properties which must be synthesized in class's @implementation. +void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, + ObjCInterfaceDecl *IDecl) { + + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; + CollectClassPropertyImplementations(IDecl, PropMap); + if (PropMap.empty()) + return; + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; + CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); + + for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator + P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { + ObjCPropertyDecl *Prop = P->second; + // If property to be implemented in the super class, ignore. + if (SuperPropMap[Prop->getIdentifier()]) + continue; + // Is there a matching propery synthesize/dynamic? + if (Prop->isInvalidDecl() || + Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || + IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) + continue; + // Property may have been synthesized by user. + if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) + continue; + if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { + if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) + continue; + if (IMPDecl->getInstanceMethod(Prop->getSetterName())) + continue; + } + + + // We use invalid SourceLocations for the synthesized ivars since they + // aren't really synthesized at a particular location; they just exist. + // Saying that they are located at the @implementation isn't really going + // to help users. + ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), + true,IMPDecl, + Prop->getIdentifier(), Prop->getIdentifier(), + SourceLocation()); + } +} + +void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, + ObjCContainerDecl *CDecl, + const llvm::DenseSet<Selector>& InsMap) { + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; + if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) + CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); + + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; + CollectImmediateProperties(CDecl, PropMap, SuperPropMap); + if (PropMap.empty()) + return; + + llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; + for (ObjCImplDecl::propimpl_iterator + I = IMPDecl->propimpl_begin(), + EI = IMPDecl->propimpl_end(); I != EI; ++I) + PropImplMap.insert((*I)->getPropertyDecl()); + + for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator + P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { + ObjCPropertyDecl *Prop = P->second; + // Is there a matching propery synthesize/dynamic? + if (Prop->isInvalidDecl() || + Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || + PropImplMap.count(Prop)) + continue; + if (!InsMap.count(Prop->getGetterName())) { + Diag(Prop->getLocation(), + isa<ObjCCategoryDecl>(CDecl) ? + diag::warn_setter_getter_impl_required_in_category : + diag::warn_setter_getter_impl_required) + << Prop->getDeclName() << Prop->getGetterName(); + Diag(IMPDecl->getLocation(), + diag::note_property_impl_required); + } + + if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { + Diag(Prop->getLocation(), + isa<ObjCCategoryDecl>(CDecl) ? + diag::warn_setter_getter_impl_required_in_category : + diag::warn_setter_getter_impl_required) + << Prop->getDeclName() << Prop->getSetterName(); + Diag(IMPDecl->getLocation(), + diag::note_property_impl_required); + } + } +} + +void +Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, + ObjCContainerDecl* IDecl) { + // Rules apply in non-GC mode only + if (getLangOptions().getGCMode() != LangOptions::NonGC) + return; + for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), + E = IDecl->prop_end(); + I != E; ++I) { + ObjCPropertyDecl *Property = (*I); + ObjCMethodDecl *GetterMethod = 0; + ObjCMethodDecl *SetterMethod = 0; + bool LookedUpGetterSetter = false; + + unsigned Attributes = Property->getPropertyAttributes(); + unsigned AttributesAsWrittern = Property->getPropertyAttributesAsWritten(); + + if (!(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_atomic) && + !(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_nonatomic)) { + GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + LookedUpGetterSetter = true; + if (GetterMethod) { + Diag(GetterMethod->getLocation(), + diag::warn_default_atomic_custom_getter_setter) + << Property->getIdentifier() << 0; + Diag(Property->getLocation(), diag::note_property_declare); + } + if (SetterMethod) { + Diag(SetterMethod->getLocation(), + diag::warn_default_atomic_custom_getter_setter) + << Property->getIdentifier() << 1; + Diag(Property->getLocation(), diag::note_property_declare); + } + } + + // We only care about readwrite atomic property. + if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || + !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) + continue; + if (const ObjCPropertyImplDecl *PIDecl + = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { + if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + continue; + if (!LookedUpGetterSetter) { + GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); + SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); + LookedUpGetterSetter = true; + } + if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { + SourceLocation MethodLoc = + (GetterMethod ? GetterMethod->getLocation() + : SetterMethod->getLocation()); + Diag(MethodLoc, diag::warn_atomic_property_rule) + << Property->getIdentifier(); + Diag(Property->getLocation(), diag::note_property_declare); + } + } + } +} + +/// AddPropertyAttrs - Propagates attributes from a property to the +/// implicitly-declared getter or setter for that property. +static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, + ObjCPropertyDecl *Property) { + // Should we just clone all attributes over? + for (Decl::attr_iterator A = Property->attr_begin(), + AEnd = Property->attr_end(); + A != AEnd; ++A) { + if (isa<DeprecatedAttr>(*A) || + isa<UnavailableAttr>(*A) || + isa<AvailabilityAttr>(*A)) + PropertyMethod->addAttr((*A)->clone(S.Context)); + } +} + +/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods +/// have the property type and issue diagnostics if they don't. +/// Also synthesize a getter/setter method if none exist (and update the +/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized +/// methods is the "right" thing to do. +void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, + ObjCContainerDecl *CD, + ObjCPropertyDecl *redeclaredProperty, + ObjCContainerDecl *lexicalDC) { + + ObjCMethodDecl *GetterMethod, *SetterMethod; + + GetterMethod = CD->getInstanceMethod(property->getGetterName()); + SetterMethod = CD->getInstanceMethod(property->getSetterName()); + DiagnosePropertyAccessorMismatch(property, GetterMethod, + property->getLocation()); + + if (SetterMethod) { + ObjCPropertyDecl::PropertyAttributeKind CAttr = + property->getPropertyAttributes(); + if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && + Context.getCanonicalType(SetterMethod->getResultType()) != + Context.VoidTy) + Diag(SetterMethod->getLocation(), diag::err_setter_type_void); + if (SetterMethod->param_size() != 1 || + ((*SetterMethod->param_begin())->getType() != property->getType())) { + Diag(property->getLocation(), + diag::warn_accessor_property_type_mismatch) + << property->getDeclName() + << SetterMethod->getSelector(); + Diag(SetterMethod->getLocation(), diag::note_declared_at); + } + } + + // Synthesize getter/setter methods if none exist. + // Find the default getter and if one not found, add one. + // FIXME: The synthesized property we set here is misleading. We almost always + // synthesize these methods unless the user explicitly provided prototypes + // (which is odd, but allowed). Sema should be typechecking that the + // declarations jive in that situation (which it is not currently). + if (!GetterMethod) { + // No instance method of same name as property getter name was found. + // Declare a getter method and add it to the list of methods + // for this class. + SourceLocation Loc = redeclaredProperty ? + redeclaredProperty->getLocation() : + property->getLocation(); + + GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, + property->getGetterName(), + property->getType(), 0, CD, true, false, true, + false, + (property->getPropertyImplementation() == + ObjCPropertyDecl::Optional) ? + ObjCMethodDecl::Optional : + ObjCMethodDecl::Required); + CD->addDecl(GetterMethod); + + AddPropertyAttrs(*this, GetterMethod, property); + + // FIXME: Eventually this shouldn't be needed, as the lexical context + // and the real context should be the same. + if (lexicalDC) + GetterMethod->setLexicalDeclContext(lexicalDC); + } else + // A user declared getter will be synthesize when @synthesize of + // the property with the same name is seen in the @implementation + GetterMethod->setSynthesized(true); + property->setGetterMethodDecl(GetterMethod); + + // Skip setter if property is read-only. + if (!property->isReadOnly()) { + // Find the default setter and if one not found, add one. + if (!SetterMethod) { + // No instance method of same name as property setter name was found. + // Declare a setter method and add it to the list of methods + // for this class. + SourceLocation Loc = redeclaredProperty ? + redeclaredProperty->getLocation() : + property->getLocation(); + + SetterMethod = + ObjCMethodDecl::Create(Context, Loc, Loc, + property->getSetterName(), Context.VoidTy, 0, + CD, true, false, true, false, + (property->getPropertyImplementation() == + ObjCPropertyDecl::Optional) ? + ObjCMethodDecl::Optional : + ObjCMethodDecl::Required); + + // Invent the arguments for the setter. We don't bother making a + // nice name for the argument. + ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, + Loc, Loc, + property->getIdentifier(), + property->getType(), + /*TInfo=*/0, + SC_None, + SC_None, + 0); + SetterMethod->setMethodParams(Context, &Argument, 1, 1); + + AddPropertyAttrs(*this, SetterMethod, property); + + CD->addDecl(SetterMethod); + // FIXME: Eventually this shouldn't be needed, as the lexical context + // and the real context should be the same. + if (lexicalDC) + SetterMethod->setLexicalDeclContext(lexicalDC); + } else + // A user declared setter will be synthesize when @synthesize of + // the property with the same name is seen in the @implementation + SetterMethod->setSynthesized(true); + property->setSetterMethodDecl(SetterMethod); + } + // Add any synthesized methods to the global pool. This allows us to + // handle the following, which is supported by GCC (and part of the design). + // + // @interface Foo + // @property double bar; + // @end + // + // void thisIsUnfortunate() { + // id foo; + // double bar = [foo bar]; + // } + // + if (GetterMethod) + AddInstanceMethodToGlobalPool(GetterMethod); + if (SetterMethod) + AddInstanceMethodToGlobalPool(SetterMethod); +} + +void Sema::CheckObjCPropertyAttributes(Decl *PDecl, + SourceLocation Loc, + unsigned &Attributes) { + // FIXME: Improve the reported location. + if (!PDecl) + return; + + ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); + QualType PropertyTy = PropertyDecl->getType(); + + // readonly and readwrite/assign/retain/copy conflict. + if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && + (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | + ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain))) { + const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? + "readwrite" : + (Attributes & ObjCDeclSpec::DQ_PR_assign) ? + "assign" : + (Attributes & ObjCDeclSpec::DQ_PR_copy) ? + "copy" : "retain"; + + Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? + diag::err_objc_property_attr_mutually_exclusive : + diag::warn_objc_property_attr_mutually_exclusive) + << "readonly" << which; + } + + // Check for copy or retain on non-object types. + if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) && + !PropertyTy->isObjCObjectPointerType() && + !PropertyTy->isBlockPointerType() && + !Context.isObjCNSObjectType(PropertyTy) && + !PropertyDecl->getAttr<ObjCNSObjectAttr>()) { + Diag(Loc, diag::err_objc_property_requires_object) + << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain"); + Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain); + } + + // Check for more than one of { assign, copy, retain }. + if (Attributes & ObjCDeclSpec::DQ_PR_assign) { + if (Attributes & ObjCDeclSpec::DQ_PR_copy) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "assign" << "copy"; + Attributes &= ~ObjCDeclSpec::DQ_PR_copy; + } + if (Attributes & ObjCDeclSpec::DQ_PR_retain) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "assign" << "retain"; + Attributes &= ~ObjCDeclSpec::DQ_PR_retain; + } + } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { + if (Attributes & ObjCDeclSpec::DQ_PR_retain) { + Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) + << "copy" << "retain"; + Attributes &= ~ObjCDeclSpec::DQ_PR_retain; + } + } + + // Warn if user supplied no assignment attribute, property is + // readwrite, and this is an object type. + if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain)) && + !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && + PropertyTy->isObjCObjectPointerType()) { + // Skip this warning in gc-only mode. + if (getLangOptions().getGCMode() != LangOptions::GCOnly) + Diag(Loc, diag::warn_objc_property_no_assignment_attribute); + + // If non-gc code warn that this is likely inappropriate. + if (getLangOptions().getGCMode() == LangOptions::NonGC) + Diag(Loc, diag::warn_objc_property_default_assign_on_object); + + // FIXME: Implement warning dependent on NSCopying being + // implemented. See also: + // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> + // (please trim this list while you are at it). + } + + if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) + &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly) + && getLangOptions().getGCMode() == LangOptions::GCOnly + && PropertyTy->isBlockPointerType()) + Diag(Loc, diag::warn_objc_property_copy_missing_on_block); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp new file mode 100644 index 0000000..4bba6f8 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -0,0 +1,9513 @@ +//===--- SemaOverload.cpp - C++ Overloading ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides Sema routines for C++ overloading. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/TypeOrdering.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/STLExtras.h" +#include <algorithm> + +namespace clang { +using namespace sema; + +/// A convenience routine for creating a decayed reference to a +/// function. +static ExprResult +CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, + SourceLocation Loc = SourceLocation()) { + ExprResult E = S.Owned(new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc)); + E = S.DefaultFunctionArrayConversion(E.take()); + if (E.isInvalid()) + return ExprError(); + return move(E); +} + +static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle); + +static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, + QualType &ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle); +static OverloadingResult +IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, + UserDefinedConversionSequence& User, + OverloadCandidateSet& Conversions, + bool AllowExplicit); + + +static ImplicitConversionSequence::CompareKind +CompareStandardConversionSequences(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2); + +static ImplicitConversionSequence::CompareKind +CompareQualificationConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2); + +static ImplicitConversionSequence::CompareKind +CompareDerivedToBaseConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2); + + + +/// GetConversionCategory - Retrieve the implicit conversion +/// category corresponding to the given implicit conversion kind. +ImplicitConversionCategory +GetConversionCategory(ImplicitConversionKind Kind) { + static const ImplicitConversionCategory + Category[(int)ICK_Num_Conversion_Kinds] = { + ICC_Identity, + ICC_Lvalue_Transformation, + ICC_Lvalue_Transformation, + ICC_Lvalue_Transformation, + ICC_Identity, + ICC_Qualification_Adjustment, + ICC_Promotion, + ICC_Promotion, + ICC_Promotion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion, + ICC_Conversion + }; + return Category[(int)Kind]; +} + +/// GetConversionRank - Retrieve the implicit conversion rank +/// corresponding to the given implicit conversion kind. +ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) { + static const ImplicitConversionRank + Rank[(int)ICK_Num_Conversion_Kinds] = { + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Promotion, + ICR_Promotion, + ICR_Promotion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Complex_Real_Conversion, + ICR_Conversion, + ICR_Conversion + }; + return Rank[(int)Kind]; +} + +/// GetImplicitConversionName - Return the name of this kind of +/// implicit conversion. +const char* GetImplicitConversionName(ImplicitConversionKind Kind) { + static const char* const Name[(int)ICK_Num_Conversion_Kinds] = { + "No conversion", + "Lvalue-to-rvalue", + "Array-to-pointer", + "Function-to-pointer", + "Noreturn adjustment", + "Qualification", + "Integral promotion", + "Floating point promotion", + "Complex promotion", + "Integral conversion", + "Floating conversion", + "Complex conversion", + "Floating-integral conversion", + "Pointer conversion", + "Pointer-to-member conversion", + "Boolean conversion", + "Compatible-types conversion", + "Derived-to-base conversion", + "Vector conversion", + "Vector splat", + "Complex-real conversion", + "Block Pointer conversion", + "Transparent Union Conversion" + }; + return Name[Kind]; +} + +/// StandardConversionSequence - Set the standard conversion +/// sequence to the identity conversion. +void StandardConversionSequence::setAsIdentityConversion() { + First = ICK_Identity; + Second = ICK_Identity; + Third = ICK_Identity; + DeprecatedStringLiteralToCharPtr = false; + ReferenceBinding = false; + DirectBinding = false; + IsLvalueReference = true; + BindsToFunctionLvalue = false; + BindsToRvalue = false; + BindsImplicitObjectArgumentWithoutRefQualifier = false; + CopyConstructor = 0; +} + +/// getRank - Retrieve the rank of this standard conversion sequence +/// (C++ 13.3.3.1.1p3). The rank is the largest rank of each of the +/// implicit conversions. +ImplicitConversionRank StandardConversionSequence::getRank() const { + ImplicitConversionRank Rank = ICR_Exact_Match; + if (GetConversionRank(First) > Rank) + Rank = GetConversionRank(First); + if (GetConversionRank(Second) > Rank) + Rank = GetConversionRank(Second); + if (GetConversionRank(Third) > Rank) + Rank = GetConversionRank(Third); + return Rank; +} + +/// isPointerConversionToBool - Determines whether this conversion is +/// a conversion of a pointer or pointer-to-member to bool. This is +/// used as part of the ranking of standard conversion sequences +/// (C++ 13.3.3.2p4). +bool StandardConversionSequence::isPointerConversionToBool() const { + // Note that FromType has not necessarily been transformed by the + // array-to-pointer or function-to-pointer implicit conversions, so + // check for their presence as well as checking whether FromType is + // a pointer. + if (getToType(1)->isBooleanType() && + (getFromType()->isPointerType() || + getFromType()->isObjCObjectPointerType() || + getFromType()->isBlockPointerType() || + getFromType()->isNullPtrType() || + First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer)) + return true; + + return false; +} + +/// isPointerConversionToVoidPointer - Determines whether this +/// conversion is a conversion of a pointer to a void pointer. This is +/// used as part of the ranking of standard conversion sequences (C++ +/// 13.3.3.2p4). +bool +StandardConversionSequence:: +isPointerConversionToVoidPointer(ASTContext& Context) const { + QualType FromType = getFromType(); + QualType ToType = getToType(1); + + // Note that FromType has not necessarily been transformed by the + // array-to-pointer implicit conversion, so check for its presence + // and redo the conversion to get a pointer. + if (First == ICK_Array_To_Pointer) + FromType = Context.getArrayDecayedType(FromType); + + if (Second == ICK_Pointer_Conversion && FromType->isAnyPointerType()) + if (const PointerType* ToPtrType = ToType->getAs<PointerType>()) + return ToPtrType->getPointeeType()->isVoidType(); + + return false; +} + +/// DebugPrint - Print this standard conversion sequence to standard +/// error. Useful for debugging overloading issues. +void StandardConversionSequence::DebugPrint() const { + llvm::raw_ostream &OS = llvm::errs(); + bool PrintedSomething = false; + if (First != ICK_Identity) { + OS << GetImplicitConversionName(First); + PrintedSomething = true; + } + + if (Second != ICK_Identity) { + if (PrintedSomething) { + OS << " -> "; + } + OS << GetImplicitConversionName(Second); + + if (CopyConstructor) { + OS << " (by copy constructor)"; + } else if (DirectBinding) { + OS << " (direct reference binding)"; + } else if (ReferenceBinding) { + OS << " (reference binding)"; + } + PrintedSomething = true; + } + + if (Third != ICK_Identity) { + if (PrintedSomething) { + OS << " -> "; + } + OS << GetImplicitConversionName(Third); + PrintedSomething = true; + } + + if (!PrintedSomething) { + OS << "No conversions required"; + } +} + +/// DebugPrint - Print this user-defined conversion sequence to standard +/// error. Useful for debugging overloading issues. +void UserDefinedConversionSequence::DebugPrint() const { + llvm::raw_ostream &OS = llvm::errs(); + if (Before.First || Before.Second || Before.Third) { + Before.DebugPrint(); + OS << " -> "; + } + OS << '\'' << ConversionFunction << '\''; + if (After.First || After.Second || After.Third) { + OS << " -> "; + After.DebugPrint(); + } +} + +/// DebugPrint - Print this implicit conversion sequence to standard +/// error. Useful for debugging overloading issues. +void ImplicitConversionSequence::DebugPrint() const { + llvm::raw_ostream &OS = llvm::errs(); + switch (ConversionKind) { + case StandardConversion: + OS << "Standard conversion: "; + Standard.DebugPrint(); + break; + case UserDefinedConversion: + OS << "User-defined conversion: "; + UserDefined.DebugPrint(); + break; + case EllipsisConversion: + OS << "Ellipsis conversion"; + break; + case AmbiguousConversion: + OS << "Ambiguous conversion"; + break; + case BadConversion: + OS << "Bad conversion"; + break; + } + + OS << "\n"; +} + +void AmbiguousConversionSequence::construct() { + new (&conversions()) ConversionSet(); +} + +void AmbiguousConversionSequence::destruct() { + conversions().~ConversionSet(); +} + +void +AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { + FromTypePtr = O.FromTypePtr; + ToTypePtr = O.ToTypePtr; + new (&conversions()) ConversionSet(O.conversions()); +} + +namespace { + // Structure used by OverloadCandidate::DeductionFailureInfo to store + // template parameter and template argument information. + struct DFIParamWithArguments { + TemplateParameter Param; + TemplateArgument FirstArg; + TemplateArgument SecondArg; + }; +} + +/// \brief Convert from Sema's representation of template deduction information +/// to the form used in overload-candidate information. +OverloadCandidate::DeductionFailureInfo +static MakeDeductionFailureInfo(ASTContext &Context, + Sema::TemplateDeductionResult TDK, + TemplateDeductionInfo &Info) { + OverloadCandidate::DeductionFailureInfo Result; + Result.Result = static_cast<unsigned>(TDK); + Result.Data = 0; + switch (TDK) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + break; + + case Sema::TDK_Incomplete: + case Sema::TDK_InvalidExplicitArguments: + Result.Data = Info.Param.getOpaqueValue(); + break; + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: { + // FIXME: Should allocate from normal heap so that we can free this later. + DFIParamWithArguments *Saved = new (Context) DFIParamWithArguments; + Saved->Param = Info.Param; + Saved->FirstArg = Info.FirstArg; + Saved->SecondArg = Info.SecondArg; + Result.Data = Saved; + break; + } + + case Sema::TDK_SubstitutionFailure: + Result.Data = Info.take(); + break; + + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return Result; +} + +void OverloadCandidate::DeductionFailureInfo::Destroy() { + switch (static_cast<Sema::TemplateDeductionResult>(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_Incomplete: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_InvalidExplicitArguments: + break; + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + // FIXME: Destroy the data? + Data = 0; + break; + + case Sema::TDK_SubstitutionFailure: + // FIXME: Destroy the template arugment list? + Data = 0; + break; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } +} + +TemplateParameter +OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { + switch (static_cast<Sema::TemplateDeductionResult>(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_SubstitutionFailure: + return TemplateParameter(); + + case Sema::TDK_Incomplete: + case Sema::TDK_InvalidExplicitArguments: + return TemplateParameter::getFromOpaqueValue(Data); + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return static_cast<DFIParamWithArguments*>(Data)->Param; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return TemplateParameter(); +} + +TemplateArgumentList * +OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { + switch (static_cast<Sema::TemplateDeductionResult>(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_Incomplete: + case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return 0; + + case Sema::TDK_SubstitutionFailure: + return static_cast<TemplateArgumentList*>(Data); + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return 0; +} + +const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { + switch (static_cast<Sema::TemplateDeductionResult>(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_Incomplete: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_SubstitutionFailure: + return 0; + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return &static_cast<DFIParamWithArguments*>(Data)->FirstArg; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return 0; +} + +const TemplateArgument * +OverloadCandidate::DeductionFailureInfo::getSecondArg() { + switch (static_cast<Sema::TemplateDeductionResult>(Result)) { + case Sema::TDK_Success: + case Sema::TDK_InstantiationDepth: + case Sema::TDK_Incomplete: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_SubstitutionFailure: + return 0; + + case Sema::TDK_Inconsistent: + case Sema::TDK_Underqualified: + return &static_cast<DFIParamWithArguments*>(Data)->SecondArg; + + // Unhandled + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + break; + } + + return 0; +} + +void OverloadCandidateSet::clear() { + inherited::clear(); + Functions.clear(); +} + +// IsOverload - Determine whether the given New declaration is an +// overload of the declarations in Old. This routine returns false if +// New and Old cannot be overloaded, e.g., if New has the same +// signature as some function in Old (C++ 1.3.10) or if the Old +// declarations aren't functions (or function templates) at all. When +// it does return false, MatchedDecl will point to the decl that New +// cannot be overloaded with. This decl may be a UsingShadowDecl on +// top of the underlying declaration. +// +// Example: Given the following input: +// +// void f(int, float); // #1 +// void f(int, int); // #2 +// int f(int, int); // #3 +// +// When we process #1, there is no previous declaration of "f", +// so IsOverload will not be used. +// +// When we process #2, Old contains only the FunctionDecl for #1. By +// comparing the parameter types, we see that #1 and #2 are overloaded +// (since they have different signatures), so this routine returns +// false; MatchedDecl is unchanged. +// +// When we process #3, Old is an overload set containing #1 and #2. We +// compare the signatures of #3 to #1 (they're overloaded, so we do +// nothing) and then #3 to #2. Since the signatures of #3 and #2 are +// identical (return types of functions are not part of the +// signature), IsOverload returns false and MatchedDecl will be set to +// point to the FunctionDecl for #2. +// +// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced +// into a class by a using declaration. The rules for whether to hide +// shadow declarations ignore some properties which otherwise figure +// into a function template's signature. +Sema::OverloadKind +Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, + NamedDecl *&Match, bool NewIsUsingDecl) { + for (LookupResult::iterator I = Old.begin(), E = Old.end(); + I != E; ++I) { + NamedDecl *OldD = *I; + + bool OldIsUsingDecl = false; + if (isa<UsingShadowDecl>(OldD)) { + OldIsUsingDecl = true; + + // We can always introduce two using declarations into the same + // context, even if they have identical signatures. + if (NewIsUsingDecl) continue; + + OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl(); + } + + // If either declaration was introduced by a using declaration, + // we'll need to use slightly different rules for matching. + // Essentially, these rules are the normal rules, except that + // function templates hide function templates with different + // return types or template parameter lists. + bool UseMemberUsingDeclRules = + (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord(); + + if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) { + if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) { + if (UseMemberUsingDeclRules && OldIsUsingDecl) { + HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); + continue; + } + + Match = *I; + return Ovl_Match; + } + } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) { + if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) { + if (UseMemberUsingDeclRules && OldIsUsingDecl) { + HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); + continue; + } + + Match = *I; + return Ovl_Match; + } + } else if (isa<UsingDecl>(OldD)) { + // We can overload with these, which can show up when doing + // redeclaration checks for UsingDecls. + assert(Old.getLookupKind() == LookupUsingDeclName); + } else if (isa<TagDecl>(OldD)) { + // We can always overload with tags by hiding them. + } else if (isa<UnresolvedUsingValueDecl>(OldD)) { + // Optimistically assume that an unresolved using decl will + // overload; if it doesn't, we'll have to diagnose during + // template instantiation. + } else { + // (C++ 13p1): + // Only function declarations can be overloaded; object and type + // declarations cannot be overloaded. + Match = *I; + return Ovl_NonFunction; + } + } + + return Ovl_Overload; +} + +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, + bool UseUsingDeclRules) { + // If both of the functions are extern "C", then they are not + // overloads. + if (Old->isExternC() && New->isExternC()) + return false; + + FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); + FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); + + // C++ [temp.fct]p2: + // A function template can be overloaded with other function templates + // and with normal (non-template) functions. + if ((OldTemplate == 0) != (NewTemplate == 0)) + return true; + + // Is the function New an overload of the function Old? + QualType OldQType = Context.getCanonicalType(Old->getType()); + QualType NewQType = Context.getCanonicalType(New->getType()); + + // Compare the signatures (C++ 1.3.10) of the two functions to + // determine whether they are overloads. If we find any mismatch + // in the signature, they are overloads. + + // If either of these functions is a K&R-style function (no + // prototype), then we consider them to have matching signatures. + if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) || + isa<FunctionNoProtoType>(NewQType.getTypePtr())) + return false; + + const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType); + const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType); + + // The signature of a function includes the types of its + // parameters (C++ 1.3.10), which includes the presence or absence + // of the ellipsis; see C++ DR 357). + if (OldQType != NewQType && + (OldType->getNumArgs() != NewType->getNumArgs() || + OldType->isVariadic() != NewType->isVariadic() || + !FunctionArgTypesAreEqual(OldType, NewType))) + return true; + + // C++ [temp.over.link]p4: + // The signature of a function template consists of its function + // signature, its return type and its template parameter list. The names + // of the template parameters are significant only for establishing the + // relationship between the template parameters and the rest of the + // signature. + // + // We check the return type and template parameter lists for function + // templates first; the remaining checks follow. + // + // However, we don't consider either of these when deciding whether + // a member introduced by a shadow declaration is hidden. + if (!UseUsingDeclRules && NewTemplate && + (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), + false, TPL_TemplateMatch) || + OldType->getResultType() != NewType->getResultType())) + return true; + + // If the function is a class member, its signature includes the + // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself. + // + // As part of this, also check whether one of the member functions + // is static, in which case they are not overloads (C++ + // 13.1p2). While not part of the definition of the signature, + // this check is important to determine whether these functions + // can be overloaded. + CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old); + CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); + if (OldMethod && NewMethod && + !OldMethod->isStatic() && !NewMethod->isStatic() && + (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() || + OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) { + if (!UseUsingDeclRules && + OldMethod->getRefQualifier() != NewMethod->getRefQualifier() && + (OldMethod->getRefQualifier() == RQ_None || + NewMethod->getRefQualifier() == RQ_None)) { + // C++0x [over.load]p2: + // - Member function declarations with the same name and the same + // parameter-type-list as well as member function template + // declarations with the same name, the same parameter-type-list, and + // the same template parameter lists cannot be overloaded if any of + // them, but not all, have a ref-qualifier (8.3.5). + Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) + << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); + Diag(OldMethod->getLocation(), diag::note_previous_declaration); + } + + return true; + } + + // The signatures match; this is not an overload. + return false; +} + +/// TryImplicitConversion - Attempt to perform an implicit conversion +/// from the given expression (Expr) to the given type (ToType). This +/// function returns an implicit conversion sequence that can be used +/// to perform the initialization. Given +/// +/// void f(float f); +/// void g(int i) { f(i); } +/// +/// this routine would produce an implicit conversion sequence to +/// describe the initialization of f from i, which will be a standard +/// conversion sequence containing an lvalue-to-rvalue conversion (C++ +/// 4.1) followed by a floating-integral conversion (C++ 4.9). +// +/// Note that this routine only determines how the conversion can be +/// performed; it does not actually perform the conversion. As such, +/// it will not produce any diagnostics if no conversion is available, +/// but will instead return an implicit conversion sequence of kind +/// "BadConversion". +/// +/// If @p SuppressUserConversions, then user-defined conversions are +/// not permitted. +/// If @p AllowExplicit, then explicit user-defined conversions are +/// permitted. +static ImplicitConversionSequence +TryImplicitConversion(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution, + bool CStyle) { + ImplicitConversionSequence ICS; + if (IsStandardConversion(S, From, ToType, InOverloadResolution, + ICS.Standard, CStyle)) { + ICS.setStandard(); + return ICS; + } + + if (!S.getLangOptions().CPlusPlus) { + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + return ICS; + } + + // C++ [over.ics.user]p4: + // A conversion of an expression of class type to the same class + // type is given Exact Match rank, and a conversion of an + // expression of class type to a base class of that type is + // given Conversion rank, in spite of the fact that a copy/move + // constructor (i.e., a user-defined conversion function) is + // called for those cases. + QualType FromType = From->getType(); + if (ToType->getAs<RecordType>() && FromType->getAs<RecordType>() && + (S.Context.hasSameUnqualifiedType(FromType, ToType) || + S.IsDerivedFrom(FromType, ToType))) { + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + ICS.Standard.setFromType(FromType); + ICS.Standard.setAllToTypes(ToType); + + // We don't actually check at this point whether there is a valid + // copy/move constructor, since overloading just assumes that it + // exists. When we actually perform initialization, we'll find the + // appropriate constructor to copy the returned object, if needed. + ICS.Standard.CopyConstructor = 0; + + // Determine whether this is considered a derived-to-base conversion. + if (!S.Context.hasSameUnqualifiedType(FromType, ToType)) + ICS.Standard.Second = ICK_Derived_To_Base; + + return ICS; + } + + if (SuppressUserConversions) { + // We're not in the case above, so there is no conversion that + // we can perform. + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + return ICS; + } + + // Attempt user-defined conversion. + OverloadCandidateSet Conversions(From->getExprLoc()); + OverloadingResult UserDefResult + = IsUserDefinedConversion(S, From, ToType, ICS.UserDefined, Conversions, + AllowExplicit); + + if (UserDefResult == OR_Success) { + ICS.setUserDefined(); + // C++ [over.ics.user]p4: + // A conversion of an expression of class type to the same class + // type is given Exact Match rank, and a conversion of an + // expression of class type to a base class of that type is + // given Conversion rank, in spite of the fact that a copy + // constructor (i.e., a user-defined conversion function) is + // called for those cases. + if (CXXConstructorDecl *Constructor + = dyn_cast<CXXConstructorDecl>(ICS.UserDefined.ConversionFunction)) { + QualType FromCanon + = S.Context.getCanonicalType(From->getType().getUnqualifiedType()); + QualType ToCanon + = S.Context.getCanonicalType(ToType).getUnqualifiedType(); + if (Constructor->isCopyConstructor() && + (FromCanon == ToCanon || S.IsDerivedFrom(FromCanon, ToCanon))) { + // Turn this into a "standard" conversion sequence, so that it + // gets ranked with standard conversion sequences. + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + ICS.Standard.setFromType(From->getType()); + ICS.Standard.setAllToTypes(ToType); + ICS.Standard.CopyConstructor = Constructor; + if (ToCanon != FromCanon) + ICS.Standard.Second = ICK_Derived_To_Base; + } + } + + // C++ [over.best.ics]p4: + // However, when considering the argument of a user-defined + // conversion function that is a candidate by 13.3.1.3 when + // invoked for the copying of the temporary in the second step + // of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or + // 13.3.1.6 in all cases, only standard conversion sequences and + // ellipsis conversion sequences are allowed. + if (SuppressUserConversions && ICS.isUserDefined()) { + ICS.setBad(BadConversionSequence::suppressed_user, From, ToType); + } + } else if (UserDefResult == OR_Ambiguous && !SuppressUserConversions) { + ICS.setAmbiguous(); + ICS.Ambiguous.setFromType(From->getType()); + ICS.Ambiguous.setToType(ToType); + for (OverloadCandidateSet::iterator Cand = Conversions.begin(); + Cand != Conversions.end(); ++Cand) + if (Cand->Viable) + ICS.Ambiguous.addConversion(Cand->Function); + } else { + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + } + + return ICS; +} + +bool Sema::TryImplicitConversion(InitializationSequence &Sequence, + const InitializedEntity &Entity, + Expr *Initializer, + bool SuppressUserConversions, + bool AllowExplicitConversions, + bool InOverloadResolution, + bool CStyle) { + ImplicitConversionSequence ICS + = clang::TryImplicitConversion(*this, Initializer, Entity.getType(), + SuppressUserConversions, + AllowExplicitConversions, + InOverloadResolution, + CStyle); + if (ICS.isBad()) return true; + + // Perform the actual conversion. + Sequence.AddConversionSequenceStep(ICS, Entity.getType()); + return false; +} + +/// PerformImplicitConversion - Perform an implicit conversion of the +/// expression From to the type ToType. Returns the +/// converted expression. Flavor is the kind of conversion we're +/// performing, used in the error message. If @p AllowExplicit, +/// explicit user-defined conversions are permitted. +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, bool AllowExplicit) { + ImplicitConversionSequence ICS; + return PerformImplicitConversion(From, ToType, Action, AllowExplicit, ICS); +} + +ExprResult +Sema::PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, bool AllowExplicit, + ImplicitConversionSequence& ICS) { + ICS = clang::TryImplicitConversion(*this, From, ToType, + /*SuppressUserConversions=*/false, + AllowExplicit, + /*InOverloadResolution=*/false, + /*CStyle=*/false); + return PerformImplicitConversion(From, ToType, ICS, Action); +} + +/// \brief Determine whether the conversion from FromType to ToType is a valid +/// conversion that strips "noreturn" off the nested function type. +static bool IsNoReturnConversion(ASTContext &Context, QualType FromType, + QualType ToType, QualType &ResultTy) { + if (Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + // Permit the conversion F(t __attribute__((noreturn))) -> F(t) + // where F adds one of the following at most once: + // - a pointer + // - a member pointer + // - a block pointer + CanQualType CanTo = Context.getCanonicalType(ToType); + CanQualType CanFrom = Context.getCanonicalType(FromType); + Type::TypeClass TyClass = CanTo->getTypeClass(); + if (TyClass != CanFrom->getTypeClass()) return false; + if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) { + if (TyClass == Type::Pointer) { + CanTo = CanTo.getAs<PointerType>()->getPointeeType(); + CanFrom = CanFrom.getAs<PointerType>()->getPointeeType(); + } else if (TyClass == Type::BlockPointer) { + CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType(); + CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType(); + } else if (TyClass == Type::MemberPointer) { + CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType(); + CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType(); + } else { + return false; + } + + TyClass = CanTo->getTypeClass(); + if (TyClass != CanFrom->getTypeClass()) return false; + if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) + return false; + } + + const FunctionType *FromFn = cast<FunctionType>(CanFrom); + FunctionType::ExtInfo EInfo = FromFn->getExtInfo(); + if (!EInfo.getNoReturn()) return false; + + FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false)); + assert(QualType(FromFn, 0).isCanonical()); + if (QualType(FromFn, 0) != CanTo) return false; + + ResultTy = ToType; + return true; +} + +/// \brief Determine whether the conversion from FromType to ToType is a valid +/// vector conversion. +/// +/// \param ICK Will be set to the vector conversion kind, if this is a vector +/// conversion. +static bool IsVectorConversion(ASTContext &Context, QualType FromType, + QualType ToType, ImplicitConversionKind &ICK) { + // We need at least one of these types to be a vector type to have a vector + // conversion. + if (!ToType->isVectorType() && !FromType->isVectorType()) + return false; + + // Identical types require no conversions. + if (Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + // There are no conversions between extended vector types, only identity. + if (ToType->isExtVectorType()) { + // There are no conversions between extended vector types other than the + // identity conversion. + if (FromType->isExtVectorType()) + return false; + + // Vector splat from any arithmetic type to a vector. + if (FromType->isArithmeticType()) { + ICK = ICK_Vector_Splat; + return true; + } + } + + // We can perform the conversion between vector types in the following cases: + // 1)vector types are equivalent AltiVec and GCC vector types + // 2)lax vector conversions are permitted and the vector types are of the + // same size + if (ToType->isVectorType() && FromType->isVectorType()) { + if (Context.areCompatibleVectorTypes(FromType, ToType) || + (Context.getLangOptions().LaxVectorConversions && + (Context.getTypeSize(FromType) == Context.getTypeSize(ToType)))) { + ICK = ICK_Vector_Conversion; + return true; + } + } + + return false; +} + +/// IsStandardConversion - Determines whether there is a standard +/// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the +/// expression From to the type ToType. Standard conversion sequences +/// only consider non-class types; for conversions that involve class +/// types, use TryImplicitConversion. If a conversion exists, SCS will +/// contain the standard conversion sequence required to perform this +/// conversion and this routine will return true. Otherwise, this +/// routine will return false and the value of SCS is unspecified. +static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle) { + QualType FromType = From->getType(); + + // Standard conversions (C++ [conv]) + SCS.setAsIdentityConversion(); + SCS.DeprecatedStringLiteralToCharPtr = false; + SCS.IncompatibleObjC = false; + SCS.setFromType(FromType); + SCS.CopyConstructor = 0; + + // There are no standard conversions for class types in C++, so + // abort early. When overloading in C, however, we do permit + if (FromType->isRecordType() || ToType->isRecordType()) { + if (S.getLangOptions().CPlusPlus) + return false; + + // When we're overloading in C, we allow, as standard conversions, + } + + // The first conversion can be an lvalue-to-rvalue conversion, + // array-to-pointer conversion, or function-to-pointer conversion + // (C++ 4p1). + + if (FromType == S.Context.OverloadTy) { + DeclAccessPair AccessPair; + if (FunctionDecl *Fn + = S.ResolveAddressOfOverloadedFunction(From, ToType, false, + AccessPair)) { + // We were able to resolve the address of the overloaded function, + // so we can convert to the type of that function. + FromType = Fn->getType(); + + // we can sometimes resolve &foo<int> regardless of ToType, so check + // if the type matches (identity) or we are converting to bool + if (!S.Context.hasSameUnqualifiedType( + S.ExtractUnqualifiedFunctionType(ToType), FromType)) { + QualType resultTy; + // if the function type matches except for [[noreturn]], it's ok + if (!IsNoReturnConversion(S.Context, FromType, + S.ExtractUnqualifiedFunctionType(ToType), resultTy)) + // otherwise, only a boolean conversion is standard + if (!ToType->isBooleanType()) + return false; + } + + // Check if the "from" expression is taking the address of an overloaded + // function and recompute the FromType accordingly. Take advantage of the + // fact that non-static member functions *must* have such an address-of + // expression. + CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn); + if (Method && !Method->isStatic()) { + assert(isa<UnaryOperator>(From->IgnoreParens()) && + "Non-unary operator on non-static member address"); + assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() + == UO_AddrOf && + "Non-address-of operator on non-static member address"); + const Type *ClassType + = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); + FromType = S.Context.getMemberPointerType(FromType, ClassType); + } else if (isa<UnaryOperator>(From->IgnoreParens())) { + assert(cast<UnaryOperator>(From->IgnoreParens())->getOpcode() == + UO_AddrOf && + "Non-address-of operator for overloaded function expression"); + FromType = S.Context.getPointerType(FromType); + } + + // Check that we've computed the proper type after overload resolution. + assert(S.Context.hasSameType( + FromType, + S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); + } else { + return false; + } + } + // Lvalue-to-rvalue conversion (C++ 4.1): + // An lvalue (3.10) of a non-function, non-array type T can be + // converted to an rvalue. + bool argIsLValue = From->isLValue(); + if (argIsLValue && + !FromType->isFunctionType() && !FromType->isArrayType() && + S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { + SCS.First = ICK_Lvalue_To_Rvalue; + + // If T is a non-class type, the type of the rvalue is the + // cv-unqualified version of T. Otherwise, the type of the rvalue + // is T (C++ 4.1p1). C++ can't get here with class types; in C, we + // just strip the qualifiers because they don't matter. + FromType = FromType.getUnqualifiedType(); + } else if (FromType->isArrayType()) { + // Array-to-pointer conversion (C++ 4.2) + SCS.First = ICK_Array_To_Pointer; + + // An lvalue or rvalue of type "array of N T" or "array of unknown + // bound of T" can be converted to an rvalue of type "pointer to + // T" (C++ 4.2p1). + FromType = S.Context.getArrayDecayedType(FromType); + + if (S.IsStringLiteralToNonConstPointerConversion(From, ToType)) { + // This conversion is deprecated. (C++ D.4). + SCS.DeprecatedStringLiteralToCharPtr = true; + + // For the purpose of ranking in overload resolution + // (13.3.3.1.1), this conversion is considered an + // array-to-pointer conversion followed by a qualification + // conversion (4.4). (C++ 4.2p2) + SCS.Second = ICK_Identity; + SCS.Third = ICK_Qualification; + SCS.setAllToTypes(FromType); + return true; + } + } else if (FromType->isFunctionType() && argIsLValue) { + // Function-to-pointer conversion (C++ 4.3). + SCS.First = ICK_Function_To_Pointer; + + // An lvalue of function type T can be converted to an rvalue of + // type "pointer to T." The result is a pointer to the + // function. (C++ 4.3p1). + FromType = S.Context.getPointerType(FromType); + } else { + // We don't require any conversions for the first step. + SCS.First = ICK_Identity; + } + SCS.setToType(0, FromType); + + // The second conversion can be an integral promotion, floating + // point promotion, integral conversion, floating point conversion, + // floating-integral conversion, pointer conversion, + // pointer-to-member conversion, or boolean conversion (C++ 4p1). + // For overloading in C, this can also be a "compatible-type" + // conversion. + bool IncompatibleObjC = false; + ImplicitConversionKind SecondICK = ICK_Identity; + if (S.Context.hasSameUnqualifiedType(FromType, ToType)) { + // The unqualified versions of the types are the same: there's no + // conversion to do. + SCS.Second = ICK_Identity; + } else if (S.IsIntegralPromotion(From, FromType, ToType)) { + // Integral promotion (C++ 4.5). + SCS.Second = ICK_Integral_Promotion; + FromType = ToType.getUnqualifiedType(); + } else if (S.IsFloatingPointPromotion(FromType, ToType)) { + // Floating point promotion (C++ 4.6). + SCS.Second = ICK_Floating_Promotion; + FromType = ToType.getUnqualifiedType(); + } else if (S.IsComplexPromotion(FromType, ToType)) { + // Complex promotion (Clang extension) + SCS.Second = ICK_Complex_Promotion; + FromType = ToType.getUnqualifiedType(); + } else if (ToType->isBooleanType() && + (FromType->isArithmeticType() || + FromType->isAnyPointerType() || + FromType->isBlockPointerType() || + FromType->isMemberPointerType() || + FromType->isNullPtrType())) { + // Boolean conversions (C++ 4.12). + SCS.Second = ICK_Boolean_Conversion; + FromType = S.Context.BoolTy; + } else if (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isIntegralType(S.Context)) { + // Integral conversions (C++ 4.7). + SCS.Second = ICK_Integral_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if (FromType->isAnyComplexType() && ToType->isComplexType()) { + // Complex conversions (C99 6.3.1.6) + SCS.Second = ICK_Complex_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) || + (ToType->isAnyComplexType() && FromType->isArithmeticType())) { + // Complex-real conversions (C99 6.3.1.7) + SCS.Second = ICK_Complex_Real; + FromType = ToType.getUnqualifiedType(); + } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) { + // Floating point conversions (C++ 4.8). + SCS.Second = ICK_Floating_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if ((FromType->isRealFloatingType() && + ToType->isIntegralType(S.Context)) || + (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isRealFloatingType())) { + // Floating-integral conversions (C++ 4.9). + SCS.Second = ICK_Floating_Integral; + FromType = ToType.getUnqualifiedType(); + } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) { + SCS.Second = ICK_Block_Pointer_Conversion; + } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution, + FromType, IncompatibleObjC)) { + // Pointer conversions (C++ 4.10). + SCS.Second = ICK_Pointer_Conversion; + SCS.IncompatibleObjC = IncompatibleObjC; + FromType = FromType.getUnqualifiedType(); + } else if (S.IsMemberPointerConversion(From, FromType, ToType, + InOverloadResolution, FromType)) { + // Pointer to member conversions (4.11). + SCS.Second = ICK_Pointer_Member; + } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) { + SCS.Second = SecondICK; + FromType = ToType.getUnqualifiedType(); + } else if (!S.getLangOptions().CPlusPlus && + S.Context.typesAreCompatible(ToType, FromType)) { + // Compatible conversions (Clang extension for C function overloading) + SCS.Second = ICK_Compatible_Conversion; + FromType = ToType.getUnqualifiedType(); + } else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) { + // Treat a conversion that strips "noreturn" as an identity conversion. + SCS.Second = ICK_NoReturn_Adjustment; + } else if (IsTransparentUnionStandardConversion(S, From, ToType, + InOverloadResolution, + SCS, CStyle)) { + SCS.Second = ICK_TransparentUnionConversion; + FromType = ToType; + } else { + // No second conversion required. + SCS.Second = ICK_Identity; + } + SCS.setToType(1, FromType); + + QualType CanonFrom; + QualType CanonTo; + // The third conversion can be a qualification conversion (C++ 4p1). + if (S.IsQualificationConversion(FromType, ToType, CStyle)) { + SCS.Third = ICK_Qualification; + FromType = ToType; + CanonFrom = S.Context.getCanonicalType(FromType); + CanonTo = S.Context.getCanonicalType(ToType); + } else { + // No conversion required + SCS.Third = ICK_Identity; + + // C++ [over.best.ics]p6: + // [...] Any difference in top-level cv-qualification is + // subsumed by the initialization itself and does not constitute + // a conversion. [...] + CanonFrom = S.Context.getCanonicalType(FromType); + CanonTo = S.Context.getCanonicalType(ToType); + if (CanonFrom.getLocalUnqualifiedType() + == CanonTo.getLocalUnqualifiedType() && + (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers() + || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr())) { + FromType = ToType; + CanonFrom = CanonTo; + } + } + SCS.setToType(2, FromType); + + // If we have not converted the argument type to the parameter type, + // this is a bad conversion sequence. + if (CanonFrom != CanonTo) + return false; + + return true; +} + +static bool +IsTransparentUnionStandardConversion(Sema &S, Expr* From, + QualType &ToType, + bool InOverloadResolution, + StandardConversionSequence &SCS, + bool CStyle) { + + const RecordType *UT = ToType->getAsUnionType(); + if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) + return false; + // The field to initialize within the transparent union. + RecordDecl *UD = UT->getDecl(); + // It's compatible if the expression matches any of the fields. + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); + it != itend; ++it) { + if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, CStyle)) { + ToType = it->getType(); + return true; + } + } + return false; +} + +/// IsIntegralPromotion - Determines whether the conversion from the +/// expression From (whose potentially-adjusted type is FromType) to +/// ToType is an integral promotion (C++ 4.5). If so, returns true and +/// sets PromotedType to the promoted type. +bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { + const BuiltinType *To = ToType->getAs<BuiltinType>(); + // All integers are built-in. + if (!To) { + return false; + } + + // An rvalue of type char, signed char, unsigned char, short int, or + // unsigned short int can be converted to an rvalue of type int if + // int can represent all the values of the source type; otherwise, + // the source rvalue can be converted to an rvalue of type unsigned + // int (C++ 4.5p1). + if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() && + !FromType->isEnumeralType()) { + if (// We can promote any signed, promotable integer type to an int + (FromType->isSignedIntegerType() || + // We can promote any unsigned integer type whose size is + // less than int to an int. + (!FromType->isSignedIntegerType() && + Context.getTypeSize(FromType) < Context.getTypeSize(ToType)))) { + return To->getKind() == BuiltinType::Int; + } + + return To->getKind() == BuiltinType::UInt; + } + + // C++0x [conv.prom]p3: + // A prvalue of an unscoped enumeration type whose underlying type is not + // fixed (7.2) can be converted to an rvalue a prvalue of the first of the + // following types that can represent all the values of the enumeration + // (i.e., the values in the range bmin to bmax as described in 7.2): int, + // unsigned int, long int, unsigned long int, long long int, or unsigned + // long long int. If none of the types in that list can represent all the + // values of the enumeration, an rvalue a prvalue of an unscoped enumeration + // type can be converted to an rvalue a prvalue of the extended integer type + // with lowest integer conversion rank (4.13) greater than the rank of long + // long in which all the values of the enumeration can be represented. If + // there are two such extended types, the signed one is chosen. + if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) { + // C++0x 7.2p9: Note that this implicit enum to int conversion is not + // provided for a scoped enumeration. + if (FromEnumType->getDecl()->isScoped()) + return false; + + // We have already pre-calculated the promotion type, so this is trivial. + if (ToType->isIntegerType() && + !RequireCompleteType(From->getLocStart(), FromType, PDiag())) + return Context.hasSameUnqualifiedType(ToType, + FromEnumType->getDecl()->getPromotionType()); + } + + // C++0x [conv.prom]p2: + // A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) can be converted + // to an rvalue a prvalue of the first of the following types that can + // represent all the values of its underlying type: int, unsigned int, + // long int, unsigned long int, long long int, or unsigned long long int. + // If none of the types in that list can represent all the values of its + // underlying type, an rvalue a prvalue of type char16_t, char32_t, + // or wchar_t can be converted to an rvalue a prvalue of its underlying + // type. + if (FromType->isAnyCharacterType() && !FromType->isCharType() && + ToType->isIntegerType()) { + // Determine whether the type we're converting from is signed or + // unsigned. + bool FromIsSigned; + uint64_t FromSize = Context.getTypeSize(FromType); + + // FIXME: Is wchar_t signed or unsigned? We assume it's signed for now. + FromIsSigned = true; + + // The types we'll try to promote to, in the appropriate + // order. Try each of these types. + QualType PromoteTypes[6] = { + Context.IntTy, Context.UnsignedIntTy, + Context.LongTy, Context.UnsignedLongTy , + Context.LongLongTy, Context.UnsignedLongLongTy + }; + for (int Idx = 0; Idx < 6; ++Idx) { + uint64_t ToSize = Context.getTypeSize(PromoteTypes[Idx]); + if (FromSize < ToSize || + (FromSize == ToSize && + FromIsSigned == PromoteTypes[Idx]->isSignedIntegerType())) { + // We found the type that we can promote to. If this is the + // type we wanted, we have a promotion. Otherwise, no + // promotion. + return Context.hasSameUnqualifiedType(ToType, PromoteTypes[Idx]); + } + } + } + + // An rvalue for an integral bit-field (9.6) can be converted to an + // rvalue of type int if int can represent all the values of the + // bit-field; otherwise, it can be converted to unsigned int if + // unsigned int can represent all the values of the bit-field. If + // the bit-field is larger yet, no integral promotion applies to + // it. If the bit-field has an enumerated type, it is treated as any + // other value of that type for promotion purposes (C++ 4.5p3). + // FIXME: We should delay checking of bit-fields until we actually perform the + // conversion. + using llvm::APSInt; + if (From) + if (FieldDecl *MemberDecl = From->getBitField()) { + APSInt BitWidth; + if (FromType->isIntegralType(Context) && + MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { + APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); + ToSize = Context.getTypeSize(ToType); + + // Are we promoting to an int from a bitfield that fits in an int? + if (BitWidth < ToSize || + (FromType->isSignedIntegerType() && BitWidth <= ToSize)) { + return To->getKind() == BuiltinType::Int; + } + + // Are we promoting to an unsigned int from an unsigned bitfield + // that fits into an unsigned int? + if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) { + return To->getKind() == BuiltinType::UInt; + } + + return false; + } + } + + // An rvalue of type bool can be converted to an rvalue of type int, + // with false becoming zero and true becoming one (C++ 4.5p4). + if (FromType->isBooleanType() && To->getKind() == BuiltinType::Int) { + return true; + } + + return false; +} + +/// IsFloatingPointPromotion - Determines whether the conversion from +/// FromType to ToType is a floating point promotion (C++ 4.6). If so, +/// returns true and sets PromotedType to the promoted type. +bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { + /// An rvalue of type float can be converted to an rvalue of type + /// double. (C++ 4.6p1). + if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>()) + if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) { + if (FromBuiltin->getKind() == BuiltinType::Float && + ToBuiltin->getKind() == BuiltinType::Double) + return true; + + // C99 6.3.1.5p1: + // When a float is promoted to double or long double, or a + // double is promoted to long double [...]. + if (!getLangOptions().CPlusPlus && + (FromBuiltin->getKind() == BuiltinType::Float || + FromBuiltin->getKind() == BuiltinType::Double) && + (ToBuiltin->getKind() == BuiltinType::LongDouble)) + return true; + } + + return false; +} + +/// \brief Determine if a conversion is a complex promotion. +/// +/// A complex promotion is defined as a complex -> complex conversion +/// where the conversion between the underlying real types is a +/// floating-point or integral promotion. +bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) { + const ComplexType *FromComplex = FromType->getAs<ComplexType>(); + if (!FromComplex) + return false; + + const ComplexType *ToComplex = ToType->getAs<ComplexType>(); + if (!ToComplex) + return false; + + return IsFloatingPointPromotion(FromComplex->getElementType(), + ToComplex->getElementType()) || + IsIntegralPromotion(0, FromComplex->getElementType(), + ToComplex->getElementType()); +} + +/// BuildSimilarlyQualifiedPointerType - In a pointer conversion from +/// the pointer type FromPtr to a pointer to type ToPointee, with the +/// same type qualifiers as FromPtr has on its pointee type. ToType, +/// if non-empty, will be a pointer to ToType that may or may not have +/// the right set of qualifiers on its pointee. +static QualType +BuildSimilarlyQualifiedPointerType(const Type *FromPtr, + QualType ToPointee, QualType ToType, + ASTContext &Context) { + assert((FromPtr->getTypeClass() == Type::Pointer || + FromPtr->getTypeClass() == Type::ObjCObjectPointer) && + "Invalid similarly-qualified pointer type"); + + /// \brief Conversions to 'id' subsume cv-qualifier conversions. + if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType()) + return ToType.getUnqualifiedType(); + + QualType CanonFromPointee + = Context.getCanonicalType(FromPtr->getPointeeType()); + QualType CanonToPointee = Context.getCanonicalType(ToPointee); + Qualifiers Quals = CanonFromPointee.getQualifiers(); + + // Exact qualifier match -> return the pointer type we're converting to. + if (CanonToPointee.getLocalQualifiers() == Quals) { + // ToType is exactly what we need. Return it. + if (!ToType.isNull()) + return ToType.getUnqualifiedType(); + + // Build a pointer to ToPointee. It has the right qualifiers + // already. + if (isa<ObjCObjectPointerType>(ToType)) + return Context.getObjCObjectPointerType(ToPointee); + return Context.getPointerType(ToPointee); + } + + // Just build a canonical type that has the right qualifiers. + QualType QualifiedCanonToPointee + = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals); + + if (isa<ObjCObjectPointerType>(ToType)) + return Context.getObjCObjectPointerType(QualifiedCanonToPointee); + return Context.getPointerType(QualifiedCanonToPointee); +} + +static bool isNullPointerConstantForConversion(Expr *Expr, + bool InOverloadResolution, + ASTContext &Context) { + // Handle value-dependent integral null pointer constants correctly. + // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 + if (Expr->isValueDependent() && !Expr->isTypeDependent() && + Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType()) + return !InOverloadResolution; + + return Expr->isNullPointerConstant(Context, + InOverloadResolution? Expr::NPC_ValueDependentIsNotNull + : Expr::NPC_ValueDependentIsNull); +} + +/// IsPointerConversion - Determines whether the conversion of the +/// expression From, which has the (possibly adjusted) type FromType, +/// can be converted to the type ToType via a pointer conversion (C++ +/// 4.10). If so, returns true and places the converted type (that +/// might differ from ToType in its cv-qualifiers at some level) into +/// ConvertedType. +/// +/// This routine also supports conversions to and from block pointers +/// and conversions with Objective-C's 'id', 'id<protocols...>', and +/// pointers to interfaces. FIXME: Once we've determined the +/// appropriate overloading rules for Objective-C, we may want to +/// split the Objective-C checks into a different routine; however, +/// GCC seems to consider all of these conversions to be pointer +/// conversions, so for now they live here. IncompatibleObjC will be +/// set if the conversion is an allowed Objective-C conversion that +/// should result in a warning. +bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, + bool InOverloadResolution, + QualType& ConvertedType, + bool &IncompatibleObjC) { + IncompatibleObjC = false; + if (isObjCPointerConversion(FromType, ToType, ConvertedType, + IncompatibleObjC)) + return true; + + // Conversion from a null pointer constant to any Objective-C pointer type. + if (ToType->isObjCObjectPointerType() && + isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + // Blocks: Block pointers can be converted to void*. + if (FromType->isBlockPointerType() && ToType->isPointerType() && + ToType->getAs<PointerType>()->getPointeeType()->isVoidType()) { + ConvertedType = ToType; + return true; + } + // Blocks: A null pointer constant can be converted to a block + // pointer type. + if (ToType->isBlockPointerType() && + isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + // If the left-hand-side is nullptr_t, the right side can be a null + // pointer constant. + if (ToType->isNullPtrType() && + isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + const PointerType* ToTypePtr = ToType->getAs<PointerType>(); + if (!ToTypePtr) + return false; + + // A null pointer constant can be converted to a pointer type (C++ 4.10p1). + if (isNullPointerConstantForConversion(From, InOverloadResolution, Context)) { + ConvertedType = ToType; + return true; + } + + // Beyond this point, both types need to be pointers + // , including objective-c pointers. + QualType ToPointeeType = ToTypePtr->getPointeeType(); + if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) { + ConvertedType = BuildSimilarlyQualifiedPointerType( + FromType->getAs<ObjCObjectPointerType>(), + ToPointeeType, + ToType, Context); + return true; + } + const PointerType *FromTypePtr = FromType->getAs<PointerType>(); + if (!FromTypePtr) + return false; + + QualType FromPointeeType = FromTypePtr->getPointeeType(); + + // If the unqualified pointee types are the same, this can't be a + // pointer conversion, so don't do all of the work below. + if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) + return false; + + // An rvalue of type "pointer to cv T," where T is an object type, + // can be converted to an rvalue of type "pointer to cv void" (C++ + // 4.10p2). + if (FromPointeeType->isIncompleteOrObjectType() && + ToPointeeType->isVoidType()) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + // MSVC allows implicit function to void* type conversion. + if (getLangOptions().Microsoft && FromPointeeType->isFunctionType() && + ToPointeeType->isVoidType()) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + // When we're overloading in C, we allow a special kind of pointer + // conversion for compatible-but-not-identical pointee types. + if (!getLangOptions().CPlusPlus && + Context.typesAreCompatible(FromPointeeType, ToPointeeType)) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + // C++ [conv.ptr]p3: + // + // An rvalue of type "pointer to cv D," where D is a class type, + // can be converted to an rvalue of type "pointer to cv B," where + // B is a base class (clause 10) of D. If B is an inaccessible + // (clause 11) or ambiguous (10.2) base class of D, a program that + // necessitates this conversion is ill-formed. The result of the + // conversion is a pointer to the base class sub-object of the + // derived class object. The null pointer value is converted to + // the null pointer value of the destination type. + // + // Note that we do not check for ambiguity or inaccessibility + // here. That is handled by CheckPointerConversion. + if (getLangOptions().CPlusPlus && + FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType) && + !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) && + IsDerivedFrom(FromPointeeType, ToPointeeType)) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + if (FromPointeeType->isVectorType() && ToPointeeType->isVectorType() && + Context.areCompatibleVectorTypes(FromPointeeType, ToPointeeType)) { + ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, + ToPointeeType, + ToType, Context); + return true; + } + + return false; +} + +/// \brief Adopt the given qualifiers for the given type. +static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ + Qualifiers TQs = T.getQualifiers(); + + // Check whether qualifiers already match. + if (TQs == Qs) + return T; + + if (Qs.compatiblyIncludes(TQs)) + return Context.getQualifiedType(T, Qs); + + return Context.getQualifiedType(T.getUnqualifiedType(), Qs); +} + +/// isObjCPointerConversion - Determines whether this is an +/// Objective-C pointer conversion. Subroutine of IsPointerConversion, +/// with the same arguments and return values. +bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, + QualType& ConvertedType, + bool &IncompatibleObjC) { + if (!getLangOptions().ObjC1) + return false; + + // The set of qualifiers on the type we're converting from. + Qualifiers FromQualifiers = FromType.getQualifiers(); + + // First, we handle all conversions on ObjC object pointer types. + const ObjCObjectPointerType* ToObjCPtr = + ToType->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *FromObjCPtr = + FromType->getAs<ObjCObjectPointerType>(); + + if (ToObjCPtr && FromObjCPtr) { + // If the pointee types are the same (ignoring qualifications), + // then this is not a pointer conversion. + if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(), + FromObjCPtr->getPointeeType())) + return false; + + // Check for compatible + // Objective C++: We're able to convert between "id" or "Class" and a + // pointer to any interface (in both directions). + if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) { + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + // Conversions with Objective-C's id<...>. + if ((FromObjCPtr->isObjCQualifiedIdType() || + ToObjCPtr->isObjCQualifiedIdType()) && + Context.ObjCQualifiedIdTypesAreCompatible(ToType, FromType, + /*compare=*/false)) { + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + // Objective C++: We're able to convert from a pointer to an + // interface to a pointer to a different interface. + if (Context.canAssignObjCInterfaces(ToObjCPtr, FromObjCPtr)) { + const ObjCInterfaceType* LHS = ToObjCPtr->getInterfaceType(); + const ObjCInterfaceType* RHS = FromObjCPtr->getInterfaceType(); + if (getLangOptions().CPlusPlus && LHS && RHS && + !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs( + FromObjCPtr->getPointeeType())) + return false; + ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, + ToObjCPtr->getPointeeType(), + ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + + if (Context.canAssignObjCInterfaces(FromObjCPtr, ToObjCPtr)) { + // Okay: this is some kind of implicit downcast of Objective-C + // interfaces, which is permitted. However, we're going to + // complain about it. + IncompatibleObjC = true; + ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, + ToObjCPtr->getPointeeType(), + ToType, Context); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + } + // Beyond this point, both types need to be C pointers or block pointers. + QualType ToPointeeType; + if (const PointerType *ToCPtr = ToType->getAs<PointerType>()) + ToPointeeType = ToCPtr->getPointeeType(); + else if (const BlockPointerType *ToBlockPtr = + ToType->getAs<BlockPointerType>()) { + // Objective C++: We're able to convert from a pointer to any object + // to a block pointer type. + if (FromObjCPtr && FromObjCPtr->isObjCBuiltinType()) { + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + ToPointeeType = ToBlockPtr->getPointeeType(); + } + else if (FromType->getAs<BlockPointerType>() && + ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) { + // Objective C++: We're able to convert from a block pointer type to a + // pointer to any object. + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + return true; + } + else + return false; + + QualType FromPointeeType; + if (const PointerType *FromCPtr = FromType->getAs<PointerType>()) + FromPointeeType = FromCPtr->getPointeeType(); + else if (const BlockPointerType *FromBlockPtr = + FromType->getAs<BlockPointerType>()) + FromPointeeType = FromBlockPtr->getPointeeType(); + else + return false; + + // If we have pointers to pointers, recursively check whether this + // is an Objective-C conversion. + if (FromPointeeType->isPointerType() && ToPointeeType->isPointerType() && + isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, + IncompatibleObjC)) { + // We always complain about this conversion. + IncompatibleObjC = true; + ConvertedType = Context.getPointerType(ConvertedType); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + // Allow conversion of pointee being objective-c pointer to another one; + // as in I* to id. + if (FromPointeeType->getAs<ObjCObjectPointerType>() && + ToPointeeType->getAs<ObjCObjectPointerType>() && + isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, + IncompatibleObjC)) { + ConvertedType = Context.getPointerType(ConvertedType); + ConvertedType = AdoptQualifiers(Context, ConvertedType, FromQualifiers); + return true; + } + + // If we have pointers to functions or blocks, check whether the only + // differences in the argument and result types are in Objective-C + // pointer conversions. If so, we permit the conversion (but + // complain about it). + const FunctionProtoType *FromFunctionType + = FromPointeeType->getAs<FunctionProtoType>(); + const FunctionProtoType *ToFunctionType + = ToPointeeType->getAs<FunctionProtoType>(); + if (FromFunctionType && ToFunctionType) { + // If the function types are exactly the same, this isn't an + // Objective-C pointer conversion. + if (Context.getCanonicalType(FromPointeeType) + == Context.getCanonicalType(ToPointeeType)) + return false; + + // Perform the quick checks that will tell us whether these + // function types are obviously different. + if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() || + FromFunctionType->isVariadic() != ToFunctionType->isVariadic() || + FromFunctionType->getTypeQuals() != ToFunctionType->getTypeQuals()) + return false; + + bool HasObjCConversion = false; + if (Context.getCanonicalType(FromFunctionType->getResultType()) + == Context.getCanonicalType(ToFunctionType->getResultType())) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(FromFunctionType->getResultType(), + ToFunctionType->getResultType(), + ConvertedType, IncompatibleObjC)) { + // Okay, we have an Objective-C pointer conversion. + HasObjCConversion = true; + } else { + // Function types are too different. Abort. + return false; + } + + // Check argument types. + for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); + ArgIdx != NumArgs; ++ArgIdx) { + QualType FromArgType = FromFunctionType->getArgType(ArgIdx); + QualType ToArgType = ToFunctionType->getArgType(ArgIdx); + if (Context.getCanonicalType(FromArgType) + == Context.getCanonicalType(ToArgType)) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(FromArgType, ToArgType, + ConvertedType, IncompatibleObjC)) { + // Okay, we have an Objective-C pointer conversion. + HasObjCConversion = true; + } else { + // Argument types are too different. Abort. + return false; + } + } + + if (HasObjCConversion) { + // We had an Objective-C conversion. Allow this pointer + // conversion, but complain about it. + ConvertedType = AdoptQualifiers(Context, ToType, FromQualifiers); + IncompatibleObjC = true; + return true; + } + } + + return false; +} + +bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, + QualType& ConvertedType) { + QualType ToPointeeType; + if (const BlockPointerType *ToBlockPtr = + ToType->getAs<BlockPointerType>()) + ToPointeeType = ToBlockPtr->getPointeeType(); + else + return false; + + QualType FromPointeeType; + if (const BlockPointerType *FromBlockPtr = + FromType->getAs<BlockPointerType>()) + FromPointeeType = FromBlockPtr->getPointeeType(); + else + return false; + // We have pointer to blocks, check whether the only + // differences in the argument and result types are in Objective-C + // pointer conversions. If so, we permit the conversion. + + const FunctionProtoType *FromFunctionType + = FromPointeeType->getAs<FunctionProtoType>(); + const FunctionProtoType *ToFunctionType + = ToPointeeType->getAs<FunctionProtoType>(); + + if (!FromFunctionType || !ToFunctionType) + return false; + + if (Context.hasSameType(FromPointeeType, ToPointeeType)) + return true; + + // Perform the quick checks that will tell us whether these + // function types are obviously different. + if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() || + FromFunctionType->isVariadic() != ToFunctionType->isVariadic()) + return false; + + FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo(); + FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo(); + if (FromEInfo != ToEInfo) + return false; + + bool IncompatibleObjC = false; + if (Context.hasSameType(FromFunctionType->getResultType(), + ToFunctionType->getResultType())) { + // Okay, the types match exactly. Nothing to do. + } else { + QualType RHS = FromFunctionType->getResultType(); + QualType LHS = ToFunctionType->getResultType(); + if ((!getLangOptions().CPlusPlus || !RHS->isRecordType()) && + !RHS.hasQualifiers() && LHS.hasQualifiers()) + LHS = LHS.getUnqualifiedType(); + + if (Context.hasSameType(RHS,LHS)) { + // OK exact match. + } else if (isObjCPointerConversion(RHS, LHS, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } + else + return false; + } + + // Check argument types. + for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); + ArgIdx != NumArgs; ++ArgIdx) { + IncompatibleObjC = false; + QualType FromArgType = FromFunctionType->getArgType(ArgIdx); + QualType ToArgType = ToFunctionType->getArgType(ArgIdx); + if (Context.hasSameType(FromArgType, ToArgType)) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(ToArgType, FromArgType, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } else + // Argument types are too different. Abort. + return false; + } + ConvertedType = ToType; + return true; +} + +/// FunctionArgTypesAreEqual - This routine checks two function proto types +/// for equlity of their argument types. Caller has already checked that +/// they have same number of arguments. This routine assumes that Objective-C +/// pointer types which only differ in their protocol qualifiers are equal. +bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType, + const FunctionProtoType *NewType) { + if (!getLangOptions().ObjC1) + return std::equal(OldType->arg_type_begin(), OldType->arg_type_end(), + NewType->arg_type_begin()); + + for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(), + N = NewType->arg_type_begin(), + E = OldType->arg_type_end(); O && (O != E); ++O, ++N) { + QualType ToType = (*O); + QualType FromType = (*N); + if (ToType != FromType) { + if (const PointerType *PTTo = ToType->getAs<PointerType>()) { + if (const PointerType *PTFr = FromType->getAs<PointerType>()) + if ((PTTo->getPointeeType()->isObjCQualifiedIdType() && + PTFr->getPointeeType()->isObjCQualifiedIdType()) || + (PTTo->getPointeeType()->isObjCQualifiedClassType() && + PTFr->getPointeeType()->isObjCQualifiedClassType())) + continue; + } + else if (const ObjCObjectPointerType *PTTo = + ToType->getAs<ObjCObjectPointerType>()) { + if (const ObjCObjectPointerType *PTFr = + FromType->getAs<ObjCObjectPointerType>()) + if (PTTo->getInterfaceDecl() == PTFr->getInterfaceDecl()) + continue; + } + return false; + } + } + return true; +} + +/// CheckPointerConversion - Check the pointer conversion from the +/// expression From to the type ToType. This routine checks for +/// ambiguous or inaccessible derived-to-base pointer +/// conversions for which IsPointerConversion has already returned +/// true. It returns true and produces a diagnostic if there was an +/// error, or returns false otherwise. +bool Sema::CheckPointerConversion(Expr *From, QualType ToType, + CastKind &Kind, + CXXCastPath& BasePath, + bool IgnoreBaseAccess) { + QualType FromType = From->getType(); + bool IsCStyleOrFunctionalCast = IgnoreBaseAccess; + + Kind = CK_BitCast; + + if (!IsCStyleOrFunctionalCast && + Context.hasSameUnqualifiedType(From->getType(), Context.BoolTy) && + From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) + DiagRuntimeBehavior(From->getExprLoc(), From, + PDiag(diag::warn_impcast_bool_to_null_pointer) + << ToType << From->getSourceRange()); + + if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) + if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) { + QualType FromPointeeType = FromPtrType->getPointeeType(), + ToPointeeType = ToPtrType->getPointeeType(); + + if (FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + !Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) { + // We must have a derived-to-base conversion. Check an + // ambiguous or inaccessible conversion. + if (CheckDerivedToBaseConversion(FromPointeeType, ToPointeeType, + From->getExprLoc(), + From->getSourceRange(), &BasePath, + IgnoreBaseAccess)) + return true; + + // The conversion was successful. + Kind = CK_DerivedToBase; + } + } + if (const ObjCObjectPointerType *FromPtrType = + FromType->getAs<ObjCObjectPointerType>()) { + if (const ObjCObjectPointerType *ToPtrType = + ToType->getAs<ObjCObjectPointerType>()) { + // Objective-C++ conversions are always okay. + // FIXME: We should have a different class of conversions for the + // Objective-C++ implicit conversions. + if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType()) + return false; + } + } + + // We shouldn't fall into this case unless it's valid for other + // reasons. + if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + Kind = CK_NullToPointer; + + return false; +} + +/// IsMemberPointerConversion - Determines whether the conversion of the +/// expression From, which has the (possibly adjusted) type FromType, can be +/// converted to the type ToType via a member pointer conversion (C++ 4.11). +/// If so, returns true and places the converted type (that might differ from +/// ToType in its cv-qualifiers at some level) into ConvertedType. +bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, + QualType ToType, + bool InOverloadResolution, + QualType &ConvertedType) { + const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>(); + if (!ToTypePtr) + return false; + + // A null pointer constant can be converted to a member pointer (C++ 4.11p1) + if (From->isNullPointerConstant(Context, + InOverloadResolution? Expr::NPC_ValueDependentIsNotNull + : Expr::NPC_ValueDependentIsNull)) { + ConvertedType = ToType; + return true; + } + + // Otherwise, both types have to be member pointers. + const MemberPointerType *FromTypePtr = FromType->getAs<MemberPointerType>(); + if (!FromTypePtr) + return false; + + // A pointer to member of B can be converted to a pointer to member of D, + // where D is derived from B (C++ 4.11p2). + QualType FromClass(FromTypePtr->getClass(), 0); + QualType ToClass(ToTypePtr->getClass(), 0); + + if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && + !RequireCompleteType(From->getLocStart(), ToClass, PDiag()) && + IsDerivedFrom(ToClass, FromClass)) { + ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), + ToClass.getTypePtr()); + return true; + } + + return false; +} + +/// CheckMemberPointerConversion - Check the member pointer conversion from the +/// expression From to the type ToType. This routine checks for ambiguous or +/// virtual or inaccessible base-to-derived member pointer conversions +/// for which IsMemberPointerConversion has already returned true. It returns +/// true and produces a diagnostic if there was an error, or returns false +/// otherwise. +bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, + CastKind &Kind, + CXXCastPath &BasePath, + bool IgnoreBaseAccess) { + QualType FromType = From->getType(); + const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>(); + if (!FromPtrType) { + // This must be a null pointer to member pointer conversion + assert(From->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull) && + "Expr must be null pointer constant!"); + Kind = CK_NullToMemberPointer; + return false; + } + + const MemberPointerType *ToPtrType = ToType->getAs<MemberPointerType>(); + assert(ToPtrType && "No member pointer cast has a target type " + "that is not a member pointer."); + + QualType FromClass = QualType(FromPtrType->getClass(), 0); + QualType ToClass = QualType(ToPtrType->getClass(), 0); + + // FIXME: What about dependent types? + assert(FromClass->isRecordType() && "Pointer into non-class."); + assert(ToClass->isRecordType() && "Pointer into non-class."); + + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, + /*DetectVirtual=*/true); + bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths); + assert(DerivationOkay && + "Should not have been called if derivation isn't OK."); + (void)DerivationOkay; + + if (Paths.isAmbiguous(Context.getCanonicalType(FromClass). + getUnqualifiedType())) { + std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); + Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv) + << 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange(); + return true; + } + + if (const RecordType *VBase = Paths.getDetectedVirtual()) { + Diag(From->getExprLoc(), diag::err_memptr_conv_via_virtual) + << FromClass << ToClass << QualType(VBase, 0) + << From->getSourceRange(); + return true; + } + + if (!IgnoreBaseAccess) + CheckBaseClassAccess(From->getExprLoc(), FromClass, ToClass, + Paths.front(), + diag::err_downcast_from_inaccessible_base); + + // Must be a base to derived member conversion. + BuildBasePathArray(Paths, BasePath); + Kind = CK_BaseToDerivedMemberPointer; + return false; +} + +/// IsQualificationConversion - Determines whether the conversion from +/// an rvalue of type FromType to ToType is a qualification conversion +/// (C++ 4.4). +bool +Sema::IsQualificationConversion(QualType FromType, QualType ToType, + bool CStyle) { + FromType = Context.getCanonicalType(FromType); + ToType = Context.getCanonicalType(ToType); + + // If FromType and ToType are the same type, this is not a + // qualification conversion. + if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType()) + return false; + + // (C++ 4.4p4): + // A conversion can add cv-qualifiers at levels other than the first + // in multi-level pointers, subject to the following rules: [...] + bool PreviousToQualsIncludeConst = true; + bool UnwrappedAnyPointer = false; + while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) { + // Within each iteration of the loop, we check the qualifiers to + // determine if this still looks like a qualification + // conversion. Then, if all is well, we unwrap one more level of + // pointers or pointers-to-members and do it all again + // until there are no more pointers or pointers-to-members left to + // unwrap. + UnwrappedAnyPointer = true; + + Qualifiers FromQuals = FromType.getQualifiers(); + Qualifiers ToQuals = ToType.getQualifiers(); + + // Allow addition/removal of GC attributes but not changing GC attributes. + if (FromQuals.getObjCGCAttr() != ToQuals.getObjCGCAttr() && + (!FromQuals.hasObjCGCAttr() || !ToQuals.hasObjCGCAttr())) { + FromQuals.removeObjCGCAttr(); + ToQuals.removeObjCGCAttr(); + } + + // -- for every j > 0, if const is in cv 1,j then const is in cv + // 2,j, and similarly for volatile. + if (!CStyle && !ToQuals.compatiblyIncludes(FromQuals)) + return false; + + // -- if the cv 1,j and cv 2,j are different, then const is in + // every cv for 0 < k < j. + if (!CStyle && FromQuals.getCVRQualifiers() != ToQuals.getCVRQualifiers() + && !PreviousToQualsIncludeConst) + return false; + + // Keep track of whether all prior cv-qualifiers in the "to" type + // include const. + PreviousToQualsIncludeConst + = PreviousToQualsIncludeConst && ToQuals.hasConst(); + } + + // We are left with FromType and ToType being the pointee types + // after unwrapping the original FromType and ToType the same number + // of types. If we unwrapped any pointers, and if FromType and + // ToType have the same unqualified type (since we checked + // qualifiers above), then this is a qualification conversion. + return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType); +} + +/// Determines whether there is a user-defined conversion sequence +/// (C++ [over.ics.user]) that converts expression From to the type +/// ToType. If such a conversion exists, User will contain the +/// user-defined conversion sequence that performs such a conversion +/// and this routine will return true. Otherwise, this routine returns +/// false and User is unspecified. +/// +/// \param AllowExplicit true if the conversion should consider C++0x +/// "explicit" conversion functions as well as non-explicit conversion +/// functions (C++0x [class.conv.fct]p2). +static OverloadingResult +IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, + UserDefinedConversionSequence& User, + OverloadCandidateSet& CandidateSet, + bool AllowExplicit) { + // Whether we will only visit constructors. + bool ConstructorsOnly = false; + + // If the type we are conversion to is a class type, enumerate its + // constructors. + if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) { + // C++ [over.match.ctor]p1: + // When objects of class type are direct-initialized (8.5), or + // copy-initialized from an expression of the same or a + // derived class type (8.5), overload resolution selects the + // constructor. [...] For copy-initialization, the candidate + // functions are all the converting constructors (12.3.1) of + // that class. The argument list is the expression-list within + // the parentheses of the initializer. + if (S.Context.hasSameUnqualifiedType(ToType, From->getType()) || + (From->getType()->getAs<RecordType>() && + S.IsDerivedFrom(From->getType(), ToType))) + ConstructorsOnly = true; + + S.RequireCompleteType(From->getLocStart(), ToType, S.PDiag()); + // RequireCompleteType may have returned true due to some invalid decl + // during template instantiation, but ToType may be complete enough now + // to try to recover. + if (ToType->isIncompleteType()) { + // We're not going to find any constructors. + } else if (CXXRecordDecl *ToRecordDecl + = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) { + DeclContext::lookup_iterator Con, ConEnd; + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl); + Con != ConEnd; ++Con) { + NamedDecl *D = *Con; + DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); + + // Find the constructor (which may be a template). + CXXConstructorDecl *Constructor = 0; + FunctionTemplateDecl *ConstructorTmpl + = dyn_cast<FunctionTemplateDecl>(D); + if (ConstructorTmpl) + Constructor + = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); + else + Constructor = cast<CXXConstructorDecl>(D); + + if (!Constructor->isInvalidDecl() && + Constructor->isConvertingConstructor(AllowExplicit)) { + if (ConstructorTmpl) + S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, + /*ExplicitArgs*/ 0, + &From, 1, CandidateSet, + /*SuppressUserConversions=*/ + !ConstructorsOnly); + else + // Allow one user-defined conversion when user specifies a + // From->ToType conversion via an static cast (c-style, etc). + S.AddOverloadCandidate(Constructor, FoundDecl, + &From, 1, CandidateSet, + /*SuppressUserConversions=*/ + !ConstructorsOnly); + } + } + } + } + + // Enumerate conversion functions, if we're allowed to. + if (ConstructorsOnly) { + } else if (S.RequireCompleteType(From->getLocStart(), From->getType(), + S.PDiag(0) << From->getSourceRange())) { + // No conversion functions from incomplete types. + } else if (const RecordType *FromRecordType + = From->getType()->getAs<RecordType>()) { + if (CXXRecordDecl *FromRecordDecl + = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) { + // Add all of the conversion functions as candidates. + const UnresolvedSetImpl *Conversions + = FromRecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + DeclAccessPair FoundDecl = I.getPair(); + NamedDecl *D = FoundDecl.getDecl(); + CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + CXXConversionDecl *Conv; + FunctionTemplateDecl *ConvTemplate; + if ((ConvTemplate = dyn_cast<FunctionTemplateDecl>(D))) + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + Conv = cast<CXXConversionDecl>(D); + + if (AllowExplicit || !Conv->isExplicit()) { + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, FoundDecl, + ActingContext, From, ToType, + CandidateSet); + else + S.AddConversionCandidate(Conv, FoundDecl, ActingContext, + From, ToType, CandidateSet); + } + } + } + } + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { + case OR_Success: + // Record the standard conversion we used and the conversion function. + if (CXXConstructorDecl *Constructor + = dyn_cast<CXXConstructorDecl>(Best->Function)) { + S.MarkDeclarationReferenced(From->getLocStart(), Constructor); + + // C++ [over.ics.user]p1: + // If the user-defined conversion is specified by a + // constructor (12.3.1), the initial standard conversion + // sequence converts the source type to the type required by + // the argument of the constructor. + // + QualType ThisType = Constructor->getThisType(S.Context); + if (Best->Conversions[0].isEllipsis()) + User.EllipsisConversion = true; + else { + User.Before = Best->Conversions[0].Standard; + User.EllipsisConversion = false; + } + User.ConversionFunction = Constructor; + User.FoundConversionFunction = Best->FoundDecl.getDecl(); + User.After.setAsIdentityConversion(); + User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); + User.After.setAllToTypes(ToType); + return OR_Success; + } else if (CXXConversionDecl *Conversion + = dyn_cast<CXXConversionDecl>(Best->Function)) { + S.MarkDeclarationReferenced(From->getLocStart(), Conversion); + + // C++ [over.ics.user]p1: + // + // [...] If the user-defined conversion is specified by a + // conversion function (12.3.2), the initial standard + // conversion sequence converts the source type to the + // implicit object parameter of the conversion function. + User.Before = Best->Conversions[0].Standard; + User.ConversionFunction = Conversion; + User.FoundConversionFunction = Best->FoundDecl.getDecl(); + User.EllipsisConversion = false; + + // C++ [over.ics.user]p2: + // The second standard conversion sequence converts the + // result of the user-defined conversion to the target type + // for the sequence. Since an implicit conversion sequence + // is an initialization, the special rules for + // initialization by user-defined conversion apply when + // selecting the best user-defined conversion for a + // user-defined conversion sequence (see 13.3.3 and + // 13.3.3.1). + User.After = Best->FinalConversion; + return OR_Success; + } else { + llvm_unreachable("Not a constructor or conversion function?"); + return OR_No_Viable_Function; + } + + case OR_No_Viable_Function: + return OR_No_Viable_Function; + case OR_Deleted: + // No conversion here! We're done. + return OR_Deleted; + + case OR_Ambiguous: + return OR_Ambiguous; + } + + return OR_No_Viable_Function; +} + +bool +Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { + ImplicitConversionSequence ICS; + OverloadCandidateSet CandidateSet(From->getExprLoc()); + OverloadingResult OvResult = + IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, + CandidateSet, false); + if (OvResult == OR_Ambiguous) + Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_ambiguous_condition) + << From->getType() << ToType << From->getSourceRange(); + else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) + Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_nonviable_condition) + << From->getType() << ToType << From->getSourceRange(); + else + return false; + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &From, 1); + return true; +} + +/// CompareImplicitConversionSequences - Compare two implicit +/// conversion sequences to determine whether one is better than the +/// other or if they are indistinguishable (C++ 13.3.3.2). +static ImplicitConversionSequence::CompareKind +CompareImplicitConversionSequences(Sema &S, + const ImplicitConversionSequence& ICS1, + const ImplicitConversionSequence& ICS2) +{ + // (C++ 13.3.3.2p2): When comparing the basic forms of implicit + // conversion sequences (as defined in 13.3.3.1) + // -- a standard conversion sequence (13.3.3.1.1) is a better + // conversion sequence than a user-defined conversion sequence or + // an ellipsis conversion sequence, and + // -- a user-defined conversion sequence (13.3.3.1.2) is a better + // conversion sequence than an ellipsis conversion sequence + // (13.3.3.1.3). + // + // C++0x [over.best.ics]p10: + // For the purpose of ranking implicit conversion sequences as + // described in 13.3.3.2, the ambiguous conversion sequence is + // treated as a user-defined sequence that is indistinguishable + // from any other user-defined conversion sequence. + if (ICS1.getKindRank() < ICS2.getKindRank()) + return ImplicitConversionSequence::Better; + else if (ICS2.getKindRank() < ICS1.getKindRank()) + return ImplicitConversionSequence::Worse; + + // The following checks require both conversion sequences to be of + // the same kind. + if (ICS1.getKind() != ICS2.getKind()) + return ImplicitConversionSequence::Indistinguishable; + + // Two implicit conversion sequences of the same form are + // indistinguishable conversion sequences unless one of the + // following rules apply: (C++ 13.3.3.2p3): + if (ICS1.isStandard()) + return CompareStandardConversionSequences(S, ICS1.Standard, ICS2.Standard); + else if (ICS1.isUserDefined()) { + // User-defined conversion sequence U1 is a better conversion + // sequence than another user-defined conversion sequence U2 if + // they contain the same user-defined conversion function or + // constructor and if the second standard conversion sequence of + // U1 is better than the second standard conversion sequence of + // U2 (C++ 13.3.3.2p3). + if (ICS1.UserDefined.ConversionFunction == + ICS2.UserDefined.ConversionFunction) + return CompareStandardConversionSequences(S, + ICS1.UserDefined.After, + ICS2.UserDefined.After); + } + + return ImplicitConversionSequence::Indistinguishable; +} + +static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) { + while (Context.UnwrapSimilarPointerTypes(T1, T2)) { + Qualifiers Quals; + T1 = Context.getUnqualifiedArrayType(T1, Quals); + T2 = Context.getUnqualifiedArrayType(T2, Quals); + } + + return Context.hasSameUnqualifiedType(T1, T2); +} + +// Per 13.3.3.2p3, compare the given standard conversion sequences to +// determine if one is a proper subset of the other. +static ImplicitConversionSequence::CompareKind +compareStandardConversionSubsets(ASTContext &Context, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { + ImplicitConversionSequence::CompareKind Result + = ImplicitConversionSequence::Indistinguishable; + + // the identity conversion sequence is considered to be a subsequence of + // any non-identity conversion sequence + if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion()) + return ImplicitConversionSequence::Better; + else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion()) + return ImplicitConversionSequence::Worse; + + if (SCS1.Second != SCS2.Second) { + if (SCS1.Second == ICK_Identity) + Result = ImplicitConversionSequence::Better; + else if (SCS2.Second == ICK_Identity) + Result = ImplicitConversionSequence::Worse; + else + return ImplicitConversionSequence::Indistinguishable; + } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1))) + return ImplicitConversionSequence::Indistinguishable; + + if (SCS1.Third == SCS2.Third) { + return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result + : ImplicitConversionSequence::Indistinguishable; + } + + if (SCS1.Third == ICK_Identity) + return Result == ImplicitConversionSequence::Worse + ? ImplicitConversionSequence::Indistinguishable + : ImplicitConversionSequence::Better; + + if (SCS2.Third == ICK_Identity) + return Result == ImplicitConversionSequence::Better + ? ImplicitConversionSequence::Indistinguishable + : ImplicitConversionSequence::Worse; + + return ImplicitConversionSequence::Indistinguishable; +} + +/// \brief Determine whether one of the given reference bindings is better +/// than the other based on what kind of bindings they are. +static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1, + const StandardConversionSequence &SCS2) { + // C++0x [over.ics.rank]p3b4: + // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an + // implicit object parameter of a non-static member function declared + // without a ref-qualifier, and *either* S1 binds an rvalue reference + // to an rvalue and S2 binds an lvalue reference *or S1 binds an + // lvalue reference to a function lvalue and S2 binds an rvalue + // reference*. + // + // FIXME: Rvalue references. We're going rogue with the above edits, + // because the semantics in the current C++0x working paper (N3225 at the + // time of this writing) break the standard definition of std::forward + // and std::reference_wrapper when dealing with references to functions. + // Proposed wording changes submitted to CWG for consideration. + if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier || + SCS2.BindsImplicitObjectArgumentWithoutRefQualifier) + return false; + + return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue && + SCS2.IsLvalueReference) || + (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue && + !SCS2.IsLvalueReference); +} + +/// CompareStandardConversionSequences - Compare two standard +/// conversion sequences to determine whether one is better than the +/// other or if they are indistinguishable (C++ 13.3.3.2p3). +static ImplicitConversionSequence::CompareKind +CompareStandardConversionSequences(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) +{ + // Standard conversion sequence S1 is a better conversion sequence + // than standard conversion sequence S2 if (C++ 13.3.3.2p3): + + // -- S1 is a proper subsequence of S2 (comparing the conversion + // sequences in the canonical form defined by 13.3.3.1.1, + // excluding any Lvalue Transformation; the identity conversion + // sequence is considered to be a subsequence of any + // non-identity conversion sequence) or, if not that, + if (ImplicitConversionSequence::CompareKind CK + = compareStandardConversionSubsets(S.Context, SCS1, SCS2)) + return CK; + + // -- the rank of S1 is better than the rank of S2 (by the rules + // defined below), or, if not that, + ImplicitConversionRank Rank1 = SCS1.getRank(); + ImplicitConversionRank Rank2 = SCS2.getRank(); + if (Rank1 < Rank2) + return ImplicitConversionSequence::Better; + else if (Rank2 < Rank1) + return ImplicitConversionSequence::Worse; + + // (C++ 13.3.3.2p4): Two conversion sequences with the same rank + // are indistinguishable unless one of the following rules + // applies: + + // A conversion that is not a conversion of a pointer, or + // pointer to member, to bool is better than another conversion + // that is such a conversion. + if (SCS1.isPointerConversionToBool() != SCS2.isPointerConversionToBool()) + return SCS2.isPointerConversionToBool() + ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + + // C++ [over.ics.rank]p4b2: + // + // If class B is derived directly or indirectly from class A, + // conversion of B* to A* is better than conversion of B* to + // void*, and conversion of A* to void* is better than conversion + // of B* to void*. + bool SCS1ConvertsToVoid + = SCS1.isPointerConversionToVoidPointer(S.Context); + bool SCS2ConvertsToVoid + = SCS2.isPointerConversionToVoidPointer(S.Context); + if (SCS1ConvertsToVoid != SCS2ConvertsToVoid) { + // Exactly one of the conversion sequences is a conversion to + // a void pointer; it's the worse conversion. + return SCS2ConvertsToVoid ? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } else if (!SCS1ConvertsToVoid && !SCS2ConvertsToVoid) { + // Neither conversion sequence converts to a void pointer; compare + // their derived-to-base conversions. + if (ImplicitConversionSequence::CompareKind DerivedCK + = CompareDerivedToBaseConversions(S, SCS1, SCS2)) + return DerivedCK; + } else if (SCS1ConvertsToVoid && SCS2ConvertsToVoid && + !S.Context.hasSameType(SCS1.getFromType(), SCS2.getFromType())) { + // Both conversion sequences are conversions to void + // pointers. Compare the source types to determine if there's an + // inheritance relationship in their sources. + QualType FromType1 = SCS1.getFromType(); + QualType FromType2 = SCS2.getFromType(); + + // Adjust the types we're converting from via the array-to-pointer + // conversion, if we need to. + if (SCS1.First == ICK_Array_To_Pointer) + FromType1 = S.Context.getArrayDecayedType(FromType1); + if (SCS2.First == ICK_Array_To_Pointer) + FromType2 = S.Context.getArrayDecayedType(FromType2); + + QualType FromPointee1 = FromType1->getPointeeType().getUnqualifiedType(); + QualType FromPointee2 = FromType2->getPointeeType().getUnqualifiedType(); + + if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + return ImplicitConversionSequence::Worse; + + // Objective-C++: If one interface is more specific than the + // other, it is the better one. + const ObjCObjectPointerType* FromObjCPtr1 + = FromType1->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType* FromObjCPtr2 + = FromType2->getAs<ObjCObjectPointerType>(); + if (FromObjCPtr1 && FromObjCPtr2) { + bool AssignLeft = S.Context.canAssignObjCInterfaces(FromObjCPtr1, + FromObjCPtr2); + bool AssignRight = S.Context.canAssignObjCInterfaces(FromObjCPtr2, + FromObjCPtr1); + if (AssignLeft != AssignRight) { + return AssignLeft? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } + } + } + + // Compare based on qualification conversions (C++ 13.3.3.2p3, + // bullet 3). + if (ImplicitConversionSequence::CompareKind QualCK + = CompareQualificationConversions(S, SCS1, SCS2)) + return QualCK; + + if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) { + // Check for a better reference binding based on the kind of bindings. + if (isBetterReferenceBindingKind(SCS1, SCS2)) + return ImplicitConversionSequence::Better; + else if (isBetterReferenceBindingKind(SCS2, SCS1)) + return ImplicitConversionSequence::Worse; + + // C++ [over.ics.rank]p3b4: + // -- S1 and S2 are reference bindings (8.5.3), and the types to + // which the references refer are the same type except for + // top-level cv-qualifiers, and the type to which the reference + // initialized by S2 refers is more cv-qualified than the type + // to which the reference initialized by S1 refers. + QualType T1 = SCS1.getToType(2); + QualType T2 = SCS2.getToType(2); + T1 = S.Context.getCanonicalType(T1); + T2 = S.Context.getCanonicalType(T2); + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals); + if (UnqualT1 == UnqualT2) { + // If the type is an array type, promote the element qualifiers to the + // type for comparison. + if (isa<ArrayType>(T1) && T1Quals) + T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); + if (isa<ArrayType>(T2) && T2Quals) + T2 = S.Context.getQualifiedType(UnqualT2, T2Quals); + if (T2.isMoreQualifiedThan(T1)) + return ImplicitConversionSequence::Better; + else if (T1.isMoreQualifiedThan(T2)) + return ImplicitConversionSequence::Worse; + } + } + + return ImplicitConversionSequence::Indistinguishable; +} + +/// CompareQualificationConversions - Compares two standard conversion +/// sequences to determine whether they can be ranked based on their +/// qualification conversions (C++ 13.3.3.2p3 bullet 3). +ImplicitConversionSequence::CompareKind +CompareQualificationConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { + // C++ 13.3.3.2p3: + // -- S1 and S2 differ only in their qualification conversion and + // yield similar types T1 and T2 (C++ 4.4), respectively, and the + // cv-qualification signature of type T1 is a proper subset of + // the cv-qualification signature of type T2, and S1 is not the + // deprecated string literal array-to-pointer conversion (4.2). + if (SCS1.First != SCS2.First || SCS1.Second != SCS2.Second || + SCS1.Third != SCS2.Third || SCS1.Third != ICK_Qualification) + return ImplicitConversionSequence::Indistinguishable; + + // FIXME: the example in the standard doesn't use a qualification + // conversion (!) + QualType T1 = SCS1.getToType(2); + QualType T2 = SCS2.getToType(2); + T1 = S.Context.getCanonicalType(T1); + T2 = S.Context.getCanonicalType(T2); + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals); + + // If the types are the same, we won't learn anything by unwrapped + // them. + if (UnqualT1 == UnqualT2) + return ImplicitConversionSequence::Indistinguishable; + + // If the type is an array type, promote the element qualifiers to the type + // for comparison. + if (isa<ArrayType>(T1) && T1Quals) + T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); + if (isa<ArrayType>(T2) && T2Quals) + T2 = S.Context.getQualifiedType(UnqualT2, T2Quals); + + ImplicitConversionSequence::CompareKind Result + = ImplicitConversionSequence::Indistinguishable; + while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) { + // Within each iteration of the loop, we check the qualifiers to + // determine if this still looks like a qualification + // conversion. Then, if all is well, we unwrap one more level of + // pointers or pointers-to-members and do it all again + // until there are no more pointers or pointers-to-members left + // to unwrap. This essentially mimics what + // IsQualificationConversion does, but here we're checking for a + // strict subset of qualifiers. + if (T1.getCVRQualifiers() == T2.getCVRQualifiers()) + // The qualifiers are the same, so this doesn't tell us anything + // about how the sequences rank. + ; + else if (T2.isMoreQualifiedThan(T1)) { + // T1 has fewer qualifiers, so it could be the better sequence. + if (Result == ImplicitConversionSequence::Worse) + // Neither has qualifiers that are a subset of the other's + // qualifiers. + return ImplicitConversionSequence::Indistinguishable; + + Result = ImplicitConversionSequence::Better; + } else if (T1.isMoreQualifiedThan(T2)) { + // T2 has fewer qualifiers, so it could be the better sequence. + if (Result == ImplicitConversionSequence::Better) + // Neither has qualifiers that are a subset of the other's + // qualifiers. + return ImplicitConversionSequence::Indistinguishable; + + Result = ImplicitConversionSequence::Worse; + } else { + // Qualifiers are disjoint. + return ImplicitConversionSequence::Indistinguishable; + } + + // If the types after this point are equivalent, we're done. + if (S.Context.hasSameUnqualifiedType(T1, T2)) + break; + } + + // Check that the winning standard conversion sequence isn't using + // the deprecated string literal array to pointer conversion. + switch (Result) { + case ImplicitConversionSequence::Better: + if (SCS1.DeprecatedStringLiteralToCharPtr) + Result = ImplicitConversionSequence::Indistinguishable; + break; + + case ImplicitConversionSequence::Indistinguishable: + break; + + case ImplicitConversionSequence::Worse: + if (SCS2.DeprecatedStringLiteralToCharPtr) + Result = ImplicitConversionSequence::Indistinguishable; + break; + } + + return Result; +} + +/// CompareDerivedToBaseConversions - Compares two standard conversion +/// sequences to determine whether they can be ranked based on their +/// various kinds of derived-to-base conversions (C++ +/// [over.ics.rank]p4b3). As part of these checks, we also look at +/// conversions between Objective-C interface types. +ImplicitConversionSequence::CompareKind +CompareDerivedToBaseConversions(Sema &S, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { + QualType FromType1 = SCS1.getFromType(); + QualType ToType1 = SCS1.getToType(1); + QualType FromType2 = SCS2.getFromType(); + QualType ToType2 = SCS2.getToType(1); + + // Adjust the types we're converting from via the array-to-pointer + // conversion, if we need to. + if (SCS1.First == ICK_Array_To_Pointer) + FromType1 = S.Context.getArrayDecayedType(FromType1); + if (SCS2.First == ICK_Array_To_Pointer) + FromType2 = S.Context.getArrayDecayedType(FromType2); + + // Canonicalize all of the types. + FromType1 = S.Context.getCanonicalType(FromType1); + ToType1 = S.Context.getCanonicalType(ToType1); + FromType2 = S.Context.getCanonicalType(FromType2); + ToType2 = S.Context.getCanonicalType(ToType2); + + // C++ [over.ics.rank]p4b3: + // + // If class B is derived directly or indirectly from class A and + // class C is derived directly or indirectly from B, + // + // Compare based on pointer conversions. + if (SCS1.Second == ICK_Pointer_Conversion && + SCS2.Second == ICK_Pointer_Conversion && + /*FIXME: Remove if Objective-C id conversions get their own rank*/ + FromType1->isPointerType() && FromType2->isPointerType() && + ToType1->isPointerType() && ToType2->isPointerType()) { + QualType FromPointee1 + = FromType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType ToPointee1 + = ToType1->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType FromPointee2 + = FromType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); + QualType ToPointee2 + = ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); + + // -- conversion of C* to B* is better than conversion of C* to A*, + if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { + if (S.IsDerivedFrom(ToPointee1, ToPointee2)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) + return ImplicitConversionSequence::Worse; + } + + // -- conversion of B* to A* is better than conversion of C* to A*, + if (FromPointee1 != FromPointee2 && ToPointee1 == ToPointee2) { + if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + return ImplicitConversionSequence::Worse; + } + } else if (SCS1.Second == ICK_Pointer_Conversion && + SCS2.Second == ICK_Pointer_Conversion) { + const ObjCObjectPointerType *FromPtr1 + = FromType1->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *FromPtr2 + = FromType2->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *ToPtr1 + = ToType1->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *ToPtr2 + = ToType2->getAs<ObjCObjectPointerType>(); + + if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) { + // Apply the same conversion ranking rules for Objective-C pointer types + // that we do for C++ pointers to class types. However, we employ the + // Objective-C pseudo-subtyping relationship used for assignment of + // Objective-C pointer types. + bool FromAssignLeft + = S.Context.canAssignObjCInterfaces(FromPtr1, FromPtr2); + bool FromAssignRight + = S.Context.canAssignObjCInterfaces(FromPtr2, FromPtr1); + bool ToAssignLeft + = S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2); + bool ToAssignRight + = S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1); + + // A conversion to an a non-id object pointer type or qualified 'id' + // type is better than a conversion to 'id'. + if (ToPtr1->isObjCIdType() && + (ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl())) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCIdType() && + (ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl())) + return ImplicitConversionSequence::Better; + + // A conversion to a non-id object pointer type is better than a + // conversion to a qualified 'id' type + if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl()) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl()) + return ImplicitConversionSequence::Better; + + // A conversion to an a non-Class object pointer type or qualified 'Class' + // type is better than a conversion to 'Class'. + if (ToPtr1->isObjCClassType() && + (ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl())) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCClassType() && + (ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl())) + return ImplicitConversionSequence::Better; + + // A conversion to a non-Class object pointer type is better than a + // conversion to a qualified 'Class' type. + if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl()) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCQualifiedClassType() && ToPtr1->getInterfaceDecl()) + return ImplicitConversionSequence::Better; + + // -- "conversion of C* to B* is better than conversion of C* to A*," + if (S.Context.hasSameType(FromType1, FromType2) && + !FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() && + (ToAssignLeft != ToAssignRight)) + return ToAssignLeft? ImplicitConversionSequence::Worse + : ImplicitConversionSequence::Better; + + // -- "conversion of B* to A* is better than conversion of C* to A*," + if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) && + (FromAssignLeft != FromAssignRight)) + return FromAssignLeft? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; + } + } + + // Ranking of member-pointer types. + if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member && + FromType1->isMemberPointerType() && FromType2->isMemberPointerType() && + ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) { + const MemberPointerType * FromMemPointer1 = + FromType1->getAs<MemberPointerType>(); + const MemberPointerType * ToMemPointer1 = + ToType1->getAs<MemberPointerType>(); + const MemberPointerType * FromMemPointer2 = + FromType2->getAs<MemberPointerType>(); + const MemberPointerType * ToMemPointer2 = + ToType2->getAs<MemberPointerType>(); + const Type *FromPointeeType1 = FromMemPointer1->getClass(); + const Type *ToPointeeType1 = ToMemPointer1->getClass(); + const Type *FromPointeeType2 = FromMemPointer2->getClass(); + const Type *ToPointeeType2 = ToMemPointer2->getClass(); + QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType(); + QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType(); + QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType(); + QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType(); + // conversion of A::* to B::* is better than conversion of A::* to C::*, + if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { + if (S.IsDerivedFrom(ToPointee1, ToPointee2)) + return ImplicitConversionSequence::Worse; + else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) + return ImplicitConversionSequence::Better; + } + // conversion of B::* to C::* is better than conversion of A::* to C::* + if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) { + if (S.IsDerivedFrom(FromPointee1, FromPointee2)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromPointee2, FromPointee1)) + return ImplicitConversionSequence::Worse; + } + } + + if (SCS1.Second == ICK_Derived_To_Base) { + // -- conversion of C to B is better than conversion of C to A, + // -- binding of an expression of type C to a reference of type + // B& is better than binding an expression of type C to a + // reference of type A&, + if (S.Context.hasSameUnqualifiedType(FromType1, FromType2) && + !S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { + if (S.IsDerivedFrom(ToType1, ToType2)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(ToType2, ToType1)) + return ImplicitConversionSequence::Worse; + } + + // -- conversion of B to A is better than conversion of C to A. + // -- binding of an expression of type B to a reference of type + // A& is better than binding an expression of type C to a + // reference of type A&, + if (!S.Context.hasSameUnqualifiedType(FromType1, FromType2) && + S.Context.hasSameUnqualifiedType(ToType1, ToType2)) { + if (S.IsDerivedFrom(FromType2, FromType1)) + return ImplicitConversionSequence::Better; + else if (S.IsDerivedFrom(FromType1, FromType2)) + return ImplicitConversionSequence::Worse; + } + } + + return ImplicitConversionSequence::Indistinguishable; +} + +/// CompareReferenceRelationship - Compare the two types T1 and T2 to +/// determine whether they are reference-related, +/// reference-compatible, reference-compatible with added +/// qualification, or incompatible, for use in C++ initialization by +/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference +/// type, and the first type (T1) is the pointee type of the reference +/// type being initialized. +Sema::ReferenceCompareResult +Sema::CompareReferenceRelationship(SourceLocation Loc, + QualType OrigT1, QualType OrigT2, + bool &DerivedToBase, + bool &ObjCConversion) { + assert(!OrigT1->isReferenceType() && + "T1 must be the pointee type of the reference type"); + assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type"); + + QualType T1 = Context.getCanonicalType(OrigT1); + QualType T2 = Context.getCanonicalType(OrigT2); + Qualifiers T1Quals, T2Quals; + QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals); + QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals); + + // C++ [dcl.init.ref]p4: + // Given types "cv1 T1" and "cv2 T2," "cv1 T1" is + // reference-related to "cv2 T2" if T1 is the same type as T2, or + // T1 is a base class of T2. + DerivedToBase = false; + ObjCConversion = false; + if (UnqualT1 == UnqualT2) { + // Nothing to do. + } else if (!RequireCompleteType(Loc, OrigT2, PDiag()) && + IsDerivedFrom(UnqualT2, UnqualT1)) + DerivedToBase = true; + else if (UnqualT1->isObjCObjectOrInterfaceType() && + UnqualT2->isObjCObjectOrInterfaceType() && + Context.canBindObjCObjectType(UnqualT1, UnqualT2)) + ObjCConversion = true; + else + return Ref_Incompatible; + + // At this point, we know that T1 and T2 are reference-related (at + // least). + + // If the type is an array type, promote the element qualifiers to the type + // for comparison. + if (isa<ArrayType>(T1) && T1Quals) + T1 = Context.getQualifiedType(UnqualT1, T1Quals); + if (isa<ArrayType>(T2) && T2Quals) + T2 = Context.getQualifiedType(UnqualT2, T2Quals); + + // C++ [dcl.init.ref]p4: + // "cv1 T1" is reference-compatible with "cv2 T2" if T1 is + // reference-related to T2 and cv1 is the same cv-qualification + // as, or greater cv-qualification than, cv2. For purposes of + // overload resolution, cases for which cv1 is greater + // cv-qualification than cv2 are identified as + // reference-compatible with added qualification (see 13.3.3.2). + // + // Note that we also require equivalence of Objective-C GC and address-space + // qualifiers when performing these computations, so that e.g., an int in + // address space 1 is not reference-compatible with an int in address + // space 2. + if (T1Quals == T2Quals) + return Ref_Compatible; + else if (T1.isMoreQualifiedThan(T2)) + return Ref_Compatible_With_Added_Qualification; + else + return Ref_Related; +} + +/// \brief Look for a user-defined conversion to an value reference-compatible +/// with DeclType. Return true if something definite is found. +static bool +FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, + QualType DeclType, SourceLocation DeclLoc, + Expr *Init, QualType T2, bool AllowRvalues, + bool AllowExplicit) { + assert(T2->isRecordType() && "Can only find conversions of record types."); + CXXRecordDecl *T2RecordDecl + = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); + + OverloadCandidateSet CandidateSet(DeclLoc); + const UnresolvedSetImpl *Conversions + = T2RecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate + = dyn_cast<FunctionTemplateDecl>(D); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + Conv = cast<CXXConversionDecl>(D); + + // If this is an explicit conversion, and we're not allowed to consider + // explicit conversions, skip it. + if (!AllowExplicit && Conv->isExplicit()) + continue; + + if (AllowRvalues) { + bool DerivedToBase = false; + bool ObjCConversion = false; + if (!ConvTemplate && + S.CompareReferenceRelationship( + DeclLoc, + Conv->getConversionType().getNonReferenceType() + .getUnqualifiedType(), + DeclType.getNonReferenceType().getUnqualifiedType(), + DerivedToBase, ObjCConversion) == + Sema::Ref_Incompatible) + continue; + } else { + // If the conversion function doesn't return a reference type, + // it can't be considered for this conversion. An rvalue reference + // is only acceptable if its referencee is a function type. + + const ReferenceType *RefType = + Conv->getConversionType()->getAs<ReferenceType>(); + if (!RefType || + (!RefType->isLValueReferenceType() && + !RefType->getPointeeType()->isFunctionType())) + continue; + } + + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, + Init, DeclType, CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, + DeclType, CandidateSet); + } + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) { + case OR_Success: + // C++ [over.ics.ref]p1: + // + // [...] If the parameter binds directly to the result of + // applying a conversion function to the argument + // expression, the implicit conversion sequence is a + // user-defined conversion sequence (13.3.3.1.2), with the + // second standard conversion sequence either an identity + // conversion or, if the conversion function returns an + // entity of a type that is a derived class of the parameter + // type, a derived-to-base Conversion. + if (!Best->FinalConversion.DirectBinding) + return false; + + if (Best->Function) + S.MarkDeclarationReferenced(DeclLoc, Best->Function); + ICS.setUserDefined(); + ICS.UserDefined.Before = Best->Conversions[0].Standard; + ICS.UserDefined.After = Best->FinalConversion; + ICS.UserDefined.ConversionFunction = Best->Function; + ICS.UserDefined.FoundConversionFunction = Best->FoundDecl.getDecl(); + ICS.UserDefined.EllipsisConversion = false; + assert(ICS.UserDefined.After.ReferenceBinding && + ICS.UserDefined.After.DirectBinding && + "Expected a direct reference binding!"); + return true; + + case OR_Ambiguous: + ICS.setAmbiguous(); + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); + Cand != CandidateSet.end(); ++Cand) + if (Cand->Viable) + ICS.Ambiguous.addConversion(Cand->Function); + return true; + + case OR_No_Viable_Function: + case OR_Deleted: + // There was no suitable conversion, or we found a deleted + // conversion; continue with other checks. + return false; + } + + return false; +} + +/// \brief Compute an implicit conversion sequence for reference +/// initialization. +static ImplicitConversionSequence +TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, + SourceLocation DeclLoc, + bool SuppressUserConversions, + bool AllowExplicit) { + assert(DeclType->isReferenceType() && "Reference init needs a reference"); + + // Most paths end in a failed conversion. + ImplicitConversionSequence ICS; + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); + + QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType(); + QualType T2 = Init->getType(); + + // If the initializer is the address of an overloaded function, try + // to resolve the overloaded function. If all goes well, T2 is the + // type of the resulting function. + if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) { + DeclAccessPair Found; + if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType, + false, Found)) + T2 = Fn->getType(); + } + + // Compute some basic properties of the types and the initializer. + bool isRValRef = DeclType->isRValueReferenceType(); + bool DerivedToBase = false; + bool ObjCConversion = false; + Expr::Classification InitCategory = Init->Classify(S.Context); + Sema::ReferenceCompareResult RefRelationship + = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase, + ObjCConversion); + + + // C++0x [dcl.init.ref]p5: + // A reference to type "cv1 T1" is initialized by an expression + // of type "cv2 T2" as follows: + + // -- If reference is an lvalue reference and the initializer expression + if (!isRValRef) { + // -- is an lvalue (but is not a bit-field), and "cv1 T1" is + // reference-compatible with "cv2 T2," or + // + // Per C++ [over.ics.ref]p4, we don't check the bit-field property here. + if (InitCategory.isLValue() && + RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { + // C++ [over.ics.ref]p1: + // When a parameter of reference type binds directly (8.5.3) + // to an argument expression, the implicit conversion sequence + // is the identity conversion, unless the argument expression + // has a type that is a derived class of the parameter type, + // in which case the implicit conversion sequence is a + // derived-to-base Conversion (13.3.3.1). + ICS.setStandard(); + ICS.Standard.First = ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base + : ObjCConversion? ICK_Compatible_Conversion + : ICK_Identity; + ICS.Standard.Third = ICK_Identity; + ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setToType(0, T2); + ICS.Standard.setToType(1, T1); + ICS.Standard.setToType(2, T1); + ICS.Standard.ReferenceBinding = true; + ICS.Standard.DirectBinding = true; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = false; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + ICS.Standard.CopyConstructor = 0; + + // Nothing more to do: the inaccessibility/ambiguity check for + // derived-to-base conversions is suppressed when we're + // computing the implicit conversion sequence (C++ + // [over.best.ics]p2). + return ICS; + } + + // -- has a class type (i.e., T2 is a class type), where T1 is + // not reference-related to T2, and can be implicitly + // converted to an lvalue of type "cv3 T3," where "cv1 T1" + // is reference-compatible with "cv3 T3" 92) (this + // conversion is selected by enumerating the applicable + // conversion functions (13.3.1.6) and choosing the best + // one through overload resolution (13.3)), + if (!SuppressUserConversions && T2->isRecordType() && + !S.RequireCompleteType(DeclLoc, T2, 0) && + RefRelationship == Sema::Ref_Incompatible) { + if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/false, + AllowExplicit)) + return ICS; + } + } + + // -- Otherwise, the reference shall be an lvalue reference to a + // non-volatile const type (i.e., cv1 shall be const), or the reference + // shall be an rvalue reference. + // + // We actually handle one oddity of C++ [over.ics.ref] at this + // point, which is that, due to p2 (which short-circuits reference + // binding by only attempting a simple conversion for non-direct + // bindings) and p3's strange wording, we allow a const volatile + // reference to bind to an rvalue. Hence the check for the presence + // of "const" rather than checking for "const" being the only + // qualifier. + // This is also the point where rvalue references and lvalue inits no longer + // go together. + if (!isRValRef && !T1.isConstQualified()) + return ICS; + + // -- If the initializer expression + // + // -- is an xvalue, class prvalue, array prvalue or function + // lvalue and "cv1T1" is reference-compatible with "cv2 T2", or + if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification && + (InitCategory.isXValue() || + (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) || + (InitCategory.isLValue() && T2->isFunctionType()))) { + ICS.setStandard(); + ICS.Standard.First = ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base + : ObjCConversion? ICK_Compatible_Conversion + : ICK_Identity; + ICS.Standard.Third = ICK_Identity; + ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setToType(0, T2); + ICS.Standard.setToType(1, T1); + ICS.Standard.setToType(2, T1); + ICS.Standard.ReferenceBinding = true; + // In C++0x, this is always a direct binding. In C++98/03, it's a direct + // binding unless we're binding to a class prvalue. + // Note: Although xvalues wouldn't normally show up in C++98/03 code, we + // allow the use of rvalue references in C++98/03 for the benefit of + // standard library implementors; therefore, we need the xvalue check here. + ICS.Standard.DirectBinding = + S.getLangOptions().CPlusPlus0x || + (InitCategory.isPRValue() && !T2->isRecordType()); + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = InitCategory.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + ICS.Standard.CopyConstructor = 0; + return ICS; + } + + // -- has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to + // an xvalue, class prvalue, or function lvalue of type + // "cv3 T3", where "cv1 T1" is reference-compatible with + // "cv3 T3", + // + // then the reference is bound to the value of the initializer + // expression in the first case and to the result of the conversion + // in the second case (or, in either case, to an appropriate base + // class subobject). + if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && + T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) && + FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/true, + AllowExplicit)) { + // In the second case, if the reference is an rvalue reference + // and the second standard conversion sequence of the + // user-defined conversion sequence includes an lvalue-to-rvalue + // conversion, the program is ill-formed. + if (ICS.isUserDefined() && isRValRef && + ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue) + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); + + return ICS; + } + + // -- Otherwise, a temporary of type "cv1 T1" is created and + // initialized from the initializer expression using the + // rules for a non-reference copy initialization (8.5). The + // reference is then bound to the temporary. If T1 is + // reference-related to T2, cv1 must be the same + // cv-qualification as, or greater cv-qualification than, + // cv2; otherwise, the program is ill-formed. + if (RefRelationship == Sema::Ref_Related) { + // If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then + // we would be reference-compatible or reference-compatible with + // added qualification. But that wasn't the case, so the reference + // initialization fails. + return ICS; + } + + // If at least one of the types is a class type, the types are not + // related, and we aren't allowed any user conversions, the + // reference binding fails. This case is important for breaking + // recursion, since TryImplicitConversion below will attempt to + // create a temporary through the use of a copy constructor. + if (SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && + (T1->isRecordType() || T2->isRecordType())) + return ICS; + + // If T1 is reference-related to T2 and the reference is an rvalue + // reference, the initializer expression shall not be an lvalue. + if (RefRelationship >= Sema::Ref_Related && + isRValRef && Init->Classify(S.Context).isLValue()) + return ICS; + + // C++ [over.ics.ref]p2: + // When a parameter of reference type is not bound directly to + // an argument expression, the conversion sequence is the one + // required to convert the argument expression to the + // underlying type of the reference according to + // 13.3.3.1. Conceptually, this conversion sequence corresponds + // to copy-initializing a temporary of the underlying type with + // the argument expression. Any difference in top-level + // cv-qualification is subsumed by the initialization itself + // and does not constitute a conversion. + ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions, + /*AllowExplicit=*/false, + /*InOverloadResolution=*/false, + /*CStyle=*/false); + + // Of course, that's still a reference binding. + if (ICS.isStandard()) { + ICS.Standard.ReferenceBinding = true; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = true; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + } else if (ICS.isUserDefined()) { + ICS.UserDefined.After.ReferenceBinding = true; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = true; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + } + + return ICS; +} + +/// TryCopyInitialization - Try to copy-initialize a value of type +/// ToType from the expression From. Return the implicit conversion +/// sequence required to pass this argument, which may be a bad +/// conversion sequence (meaning that the argument cannot be passed to +/// a parameter of this type). If @p SuppressUserConversions, then we +/// do not permit any user-defined conversion sequences. +static ImplicitConversionSequence +TryCopyInitialization(Sema &S, Expr *From, QualType ToType, + bool SuppressUserConversions, + bool InOverloadResolution) { + if (ToType->isReferenceType()) + return TryReferenceInit(S, From, ToType, + /*FIXME:*/From->getLocStart(), + SuppressUserConversions, + /*AllowExplicit=*/false); + + return TryImplicitConversion(S, From, ToType, + SuppressUserConversions, + /*AllowExplicit=*/false, + InOverloadResolution, + /*CStyle=*/false); +} + +/// TryObjectArgumentInitialization - Try to initialize the object +/// parameter of the given member function (@c Method) from the +/// expression @p From. +static ImplicitConversionSequence +TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, + Expr::Classification FromClassification, + CXXMethodDecl *Method, + CXXRecordDecl *ActingContext) { + QualType ClassType = S.Context.getTypeDeclType(ActingContext); + // [class.dtor]p2: A destructor can be invoked for a const, volatile or + // const volatile object. + unsigned Quals = isa<CXXDestructorDecl>(Method) ? + Qualifiers::Const | Qualifiers::Volatile : Method->getTypeQualifiers(); + QualType ImplicitParamType = S.Context.getCVRQualifiedType(ClassType, Quals); + + // Set up the conversion sequence as a "bad" conversion, to allow us + // to exit early. + ImplicitConversionSequence ICS; + + // We need to have an object of class type. + QualType FromType = OrigFromType; + if (const PointerType *PT = FromType->getAs<PointerType>()) { + FromType = PT->getPointeeType(); + + // When we had a pointer, it's implicitly dereferenced, so we + // better have an lvalue. + assert(FromClassification.isLValue()); + } + + assert(FromType->isRecordType()); + + // C++0x [over.match.funcs]p4: + // For non-static member functions, the type of the implicit object + // parameter is + // + // - "lvalue reference to cv X" for functions declared without a + // ref-qualifier or with the & ref-qualifier + // - "rvalue reference to cv X" for functions declared with the && + // ref-qualifier + // + // where X is the class of which the function is a member and cv is the + // cv-qualification on the member function declaration. + // + // However, when finding an implicit conversion sequence for the argument, we + // are not allowed to create temporaries or perform user-defined conversions + // (C++ [over.match.funcs]p5). We perform a simplified version of + // reference binding here, that allows class rvalues to bind to + // non-constant references. + + // First check the qualifiers. + QualType FromTypeCanon = S.Context.getCanonicalType(FromType); + if (ImplicitParamType.getCVRQualifiers() + != FromTypeCanon.getLocalCVRQualifiers() && + !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) { + ICS.setBad(BadConversionSequence::bad_qualifiers, + OrigFromType, ImplicitParamType); + return ICS; + } + + // Check that we have either the same type or a derived type. It + // affects the conversion rank. + QualType ClassTypeCanon = S.Context.getCanonicalType(ClassType); + ImplicitConversionKind SecondKind; + if (ClassTypeCanon == FromTypeCanon.getLocalUnqualifiedType()) { + SecondKind = ICK_Identity; + } else if (S.IsDerivedFrom(FromType, ClassType)) + SecondKind = ICK_Derived_To_Base; + else { + ICS.setBad(BadConversionSequence::unrelated_class, + FromType, ImplicitParamType); + return ICS; + } + + // Check the ref-qualifier. + switch (Method->getRefQualifier()) { + case RQ_None: + // Do nothing; we don't care about lvalueness or rvalueness. + break; + + case RQ_LValue: + if (!FromClassification.isLValue() && Quals != Qualifiers::Const) { + // non-const lvalue reference cannot bind to an rvalue + ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType, + ImplicitParamType); + return ICS; + } + break; + + case RQ_RValue: + if (!FromClassification.isRValue()) { + // rvalue reference cannot bind to an lvalue + ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType, + ImplicitParamType); + return ICS; + } + break; + } + + // Success. Mark this as a reference binding. + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + ICS.Standard.Second = SecondKind; + ICS.Standard.setFromType(FromType); + ICS.Standard.setAllToTypes(ImplicitParamType); + ICS.Standard.ReferenceBinding = true; + ICS.Standard.DirectBinding = true; + ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; + ICS.Standard.BindsToFunctionLvalue = false; + ICS.Standard.BindsToRvalue = FromClassification.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier + = (Method->getRefQualifier() == RQ_None); + return ICS; +} + +/// PerformObjectArgumentInitialization - Perform initialization of +/// the implicit object parameter for the given Method with the given +/// expression. +ExprResult +Sema::PerformObjectArgumentInitialization(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + CXXMethodDecl *Method) { + QualType FromRecordType, DestType; + QualType ImplicitParamRecordType = + Method->getThisType(Context)->getAs<PointerType>()->getPointeeType(); + + Expr::Classification FromClassification; + if (const PointerType *PT = From->getType()->getAs<PointerType>()) { + FromRecordType = PT->getPointeeType(); + DestType = Method->getThisType(Context); + FromClassification = Expr::Classification::makeSimpleLValue(); + } else { + FromRecordType = From->getType(); + DestType = ImplicitParamRecordType; + FromClassification = From->Classify(Context); + } + + // Note that we always use the true parent context when performing + // the actual argument initialization. + ImplicitConversionSequence ICS + = TryObjectArgumentInitialization(*this, From->getType(), FromClassification, + Method, Method->getParent()); + if (ICS.isBad()) { + if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) { + Qualifiers FromQs = FromRecordType.getQualifiers(); + Qualifiers ToQs = DestType.getQualifiers(); + unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); + if (CVR) { + Diag(From->getSourceRange().getBegin(), + diag::err_member_function_call_bad_cvr) + << Method->getDeclName() << FromRecordType << (CVR - 1) + << From->getSourceRange(); + Diag(Method->getLocation(), diag::note_previous_decl) + << Method->getDeclName(); + return ExprError(); + } + } + + return Diag(From->getSourceRange().getBegin(), + diag::err_implicit_object_parameter_init) + << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); + } + + if (ICS.Standard.Second == ICK_Derived_To_Base) { + ExprResult FromRes = + PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method); + if (FromRes.isInvalid()) + return ExprError(); + From = FromRes.take(); + } + + if (!Context.hasSameType(From->getType(), DestType)) + From = ImpCastExprToType(From, DestType, CK_NoOp, + From->getType()->isPointerType() ? VK_RValue : VK_LValue).take(); + return Owned(From); +} + +/// TryContextuallyConvertToBool - Attempt to contextually convert the +/// expression From to bool (C++0x [conv]p3). +static ImplicitConversionSequence +TryContextuallyConvertToBool(Sema &S, Expr *From) { + // FIXME: This is pretty broken. + return TryImplicitConversion(S, From, S.Context.BoolTy, + // FIXME: Are these flags correct? + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/true, + /*InOverloadResolution=*/false, + /*CStyle=*/false); +} + +/// PerformContextuallyConvertToBool - Perform a contextual conversion +/// of the expression From to bool (C++0x [conv]p3). +ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { + ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From); + if (!ICS.isBad()) + return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); + + if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) + return Diag(From->getSourceRange().getBegin(), + diag::err_typecheck_bool_condition) + << From->getType() << From->getSourceRange(); + return ExprError(); +} + +/// TryContextuallyConvertToObjCId - Attempt to contextually convert the +/// expression From to 'id'. +static ImplicitConversionSequence +TryContextuallyConvertToObjCId(Sema &S, Expr *From) { + QualType Ty = S.Context.getObjCIdType(); + return TryImplicitConversion(S, From, Ty, + // FIXME: Are these flags correct? + /*SuppressUserConversions=*/false, + /*AllowExplicit=*/true, + /*InOverloadResolution=*/false, + /*CStyle=*/false); +} + +/// PerformContextuallyConvertToObjCId - Perform a contextual conversion +/// of the expression From to 'id'. +ExprResult Sema::PerformContextuallyConvertToObjCId(Expr *From) { + QualType Ty = Context.getObjCIdType(); + ImplicitConversionSequence ICS = TryContextuallyConvertToObjCId(*this, From); + if (!ICS.isBad()) + return PerformImplicitConversion(From, Ty, ICS, AA_Converting); + return ExprError(); +} + +/// \brief Attempt to convert the given expression to an integral or +/// enumeration type. +/// +/// This routine will attempt to convert an expression of class type to an +/// integral or enumeration type, if that class type only has a single +/// conversion to an integral or enumeration type. +/// +/// \param Loc The source location of the construct that requires the +/// conversion. +/// +/// \param FromE The expression we're converting from. +/// +/// \param NotIntDiag The diagnostic to be emitted if the expression does not +/// have integral or enumeration type. +/// +/// \param IncompleteDiag The diagnostic to be emitted if the expression has +/// incomplete class type. +/// +/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an +/// explicit conversion function (because no implicit conversion functions +/// were available). This is a recovery mode. +/// +/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag, +/// showing which conversion was picked. +/// +/// \param AmbigDiag The diagnostic to be emitted if there is more than one +/// conversion function that could convert to integral or enumeration type. +/// +/// \param AmbigNote The note to be emitted with \p AmbigDiag for each +/// usable conversion function. +/// +/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion +/// function, which may be an extension in this case. +/// +/// \returns The expression, converted to an integral or enumeration type if +/// successful. +ExprResult +Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, + const PartialDiagnostic &NotIntDiag, + const PartialDiagnostic &IncompleteDiag, + const PartialDiagnostic &ExplicitConvDiag, + const PartialDiagnostic &ExplicitConvNote, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &AmbigNote, + const PartialDiagnostic &ConvDiag) { + // We can't perform any more checking for type-dependent expressions. + if (From->isTypeDependent()) + return Owned(From); + + // If the expression already has integral or enumeration type, we're golden. + QualType T = From->getType(); + if (T->isIntegralOrEnumerationType()) + return Owned(From); + + // FIXME: Check for missing '()' if T is a function type? + + // If we don't have a class type in C++, there's no way we can get an + // expression of integral or enumeration type. + const RecordType *RecordTy = T->getAs<RecordType>(); + if (!RecordTy || !getLangOptions().CPlusPlus) { + Diag(Loc, NotIntDiag) + << T << From->getSourceRange(); + return Owned(From); + } + + // We must have a complete class type. + if (RequireCompleteType(Loc, T, IncompleteDiag)) + return Owned(From); + + // Look for a conversion to an integral or enumeration type. + UnresolvedSet<4> ViableConversions; + UnresolvedSet<4> ExplicitConversions; + const UnresolvedSetImpl *Conversions + = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); + + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; + ++I) { + if (CXXConversionDecl *Conversion + = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) + if (Conversion->getConversionType().getNonReferenceType() + ->isIntegralOrEnumerationType()) { + if (Conversion->isExplicit()) + ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); + else + ViableConversions.addDecl(I.getDecl(), I.getAccess()); + } + } + + switch (ViableConversions.size()) { + case 0: + if (ExplicitConversions.size() == 1) { + DeclAccessPair Found = ExplicitConversions[0]; + CXXConversionDecl *Conversion + = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); + + // The user probably meant to invoke the given explicit + // conversion; use it. + QualType ConvTy + = Conversion->getConversionType().getNonReferenceType(); + std::string TypeStr; + ConvTy.getAsStringInternal(TypeStr, Context.PrintingPolicy); + + Diag(Loc, ExplicitConvDiag) + << T << ConvTy + << FixItHint::CreateInsertion(From->getLocStart(), + "static_cast<" + TypeStr + ">(") + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()), + ")"); + Diag(Conversion->getLocation(), ExplicitConvNote) + << ConvTy->isEnumeralType() << ConvTy; + + // If we aren't in a SFINAE context, build a call to the + // explicit conversion function. + if (isSFINAEContext()) + return ExprError(); + + CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion); + if (Result.isInvalid()) + return ExprError(); + + From = Result.get(); + } + + // We'll complain below about a non-integral condition type. + break; + + case 1: { + // Apply this conversion. + DeclAccessPair Found = ViableConversions[0]; + CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + + CXXConversionDecl *Conversion + = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); + QualType ConvTy + = Conversion->getConversionType().getNonReferenceType(); + if (ConvDiag.getDiagID()) { + if (isSFINAEContext()) + return ExprError(); + + Diag(Loc, ConvDiag) + << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); + } + + ExprResult Result = BuildCXXMemberCallExpr(From, Found, + cast<CXXConversionDecl>(Found->getUnderlyingDecl())); + if (Result.isInvalid()) + return ExprError(); + + From = Result.get(); + break; + } + + default: + Diag(Loc, AmbigDiag) + << T << From->getSourceRange(); + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { + CXXConversionDecl *Conv + = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); + QualType ConvTy = Conv->getConversionType().getNonReferenceType(); + Diag(Conv->getLocation(), AmbigNote) + << ConvTy->isEnumeralType() << ConvTy; + } + return Owned(From); + } + + if (!From->getType()->isIntegralOrEnumerationType()) + Diag(Loc, NotIntDiag) + << From->getType() << From->getSourceRange(); + + return Owned(From); +} + +/// AddOverloadCandidate - Adds the given function to the set of +/// candidate functions, using the given function call arguments. If +/// @p SuppressUserConversions, then don't allow user-defined +/// conversions via constructors or conversion operators. +/// +/// \para PartialOverloading true if we are performing "partial" overloading +/// based on an incomplete set of function arguments. This feature is used by +/// code completion. +void +Sema::AddOverloadCandidate(FunctionDecl *Function, + DeclAccessPair FoundDecl, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions, + bool PartialOverloading) { + const FunctionProtoType* Proto + = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); + assert(Proto && "Functions without a prototype cannot be overloaded"); + assert(!Function->getDescribedFunctionTemplate() && + "Use AddTemplateOverloadCandidate for function templates"); + + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) { + if (!isa<CXXConstructorDecl>(Method)) { + // If we get here, it's because we're calling a member function + // that is named without a member access expression (e.g., + // "this->f") that was either written explicitly or created + // implicitly. This can happen with a qualified call to a member + // function, e.g., X::f(). We use an empty type for the implied + // object argument (C++ [over.call.func]p3), and the acting context + // is irrelevant. + AddMethodCandidate(Method, FoundDecl, Method->getParent(), + QualType(), Expr::Classification::makeSimpleLValue(), + Args, NumArgs, CandidateSet, + SuppressUserConversions); + return; + } + // We treat a constructor like a non-member function, since its object + // argument doesn't participate in overload resolution. + } + + if (!CandidateSet.isNewCandidate(Function)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Function)){ + // C++ [class.copy]p3: + // A member function template is never instantiated to perform the copy + // of a class object to an object of its class type. + QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); + if (NumArgs == 1 && + Constructor->isSpecializationCopyingObject() && + (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) || + IsDerivedFrom(Args[0]->getType(), ClassType))) + return; + } + + // Add this candidate + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate& Candidate = CandidateSet.back(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = Function; + Candidate.Viable = true; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; + + unsigned NumArgsInProto = Proto->getNumArgs(); + + // (C++ 13.3.2p2): A candidate function having fewer than m + // parameters is viable only if it has an ellipsis in its parameter + // list (8.3.5). + if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto && + !Proto->isVariadic()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_many_arguments; + return; + } + + // (C++ 13.3.2p2): A candidate function having more than m parameters + // is viable only if the (m+1)st parameter has a default argument + // (8.3.6). For the purposes of overload resolution, the + // parameter list is truncated on the right, so that there are + // exactly m parameters. + unsigned MinRequiredArgs = Function->getMinRequiredArguments(); + if (NumArgs < MinRequiredArgs && !PartialOverloading) { + // Not enough arguments. + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_few_arguments; + return; + } + + // Determine the implicit conversion sequences for each of the + // arguments. + Candidate.Conversions.resize(NumArgs); + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + if (ArgIdx < NumArgsInProto) { + // (C++ 13.3.2p3): for F to be a viable function, there shall + // exist for each argument an implicit conversion sequence + // (13.3.3.1) that converts that argument to the corresponding + // parameter of F. + QualType ParamType = Proto->getArgType(ArgIdx); + Candidate.Conversions[ArgIdx] + = TryCopyInitialization(*this, Args[ArgIdx], ParamType, + SuppressUserConversions, + /*InOverloadResolution=*/true); + if (Candidate.Conversions[ArgIdx].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } else { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[ArgIdx].setEllipsis(); + } + } +} + +/// \brief Add all of the function declarations in the given function set to +/// the overload canddiate set. +void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { + NamedDecl *D = F.getDecl()->getUnderlyingDecl(); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) + AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), + cast<CXXMethodDecl>(FD)->getParent(), + Args[0]->getType(), Args[0]->Classify(Context), + Args + 1, NumArgs - 1, + CandidateSet, SuppressUserConversions); + else + AddOverloadCandidate(FD, F.getPair(), Args, NumArgs, CandidateSet, + SuppressUserConversions); + } else { + FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); + if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && + !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) + AddMethodTemplateCandidate(FunTmpl, F.getPair(), + cast<CXXRecordDecl>(FunTmpl->getDeclContext()), + /*FIXME: explicit args */ 0, + Args[0]->getType(), + Args[0]->Classify(Context), + Args + 1, NumArgs - 1, + CandidateSet, + SuppressUserConversions); + else + AddTemplateOverloadCandidate(FunTmpl, F.getPair(), + /*FIXME: explicit args */ 0, + Args, NumArgs, CandidateSet, + SuppressUserConversions); + } + } +} + +/// AddMethodCandidate - Adds a named decl (which is some kind of +/// method) as a method candidate to the given overload set. +void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, + QualType ObjectType, + Expr::Classification ObjectClassification, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + NamedDecl *Decl = FoundDecl.getDecl(); + CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(Decl->getDeclContext()); + + if (isa<UsingShadowDecl>(Decl)) + Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl(); + + if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) { + assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) && + "Expected a member function template"); + AddMethodTemplateCandidate(TD, FoundDecl, ActingContext, + /*ExplicitArgs*/ 0, + ObjectType, ObjectClassification, Args, NumArgs, + CandidateSet, + SuppressUserConversions); + } else { + AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext, + ObjectType, ObjectClassification, Args, NumArgs, + CandidateSet, SuppressUserConversions); + } +} + +/// AddMethodCandidate - Adds the given C++ member function to the set +/// of candidate functions, using the given function call arguments +/// and the object argument (@c Object). For example, in a call +/// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain +/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't +/// allow user-defined conversions via constructors or conversion +/// operators. +void +Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + const FunctionProtoType* Proto + = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); + assert(Proto && "Methods without a prototype cannot be overloaded"); + assert(!isa<CXXConstructorDecl>(Method) && + "Use AddOverloadCandidate for constructors"); + + if (!CandidateSet.isNewCandidate(Method)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + // Add this candidate + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate& Candidate = CandidateSet.back(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = Method; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; + + unsigned NumArgsInProto = Proto->getNumArgs(); + + // (C++ 13.3.2p2): A candidate function having fewer than m + // parameters is viable only if it has an ellipsis in its parameter + // list (8.3.5). + if (NumArgs > NumArgsInProto && !Proto->isVariadic()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_many_arguments; + return; + } + + // (C++ 13.3.2p2): A candidate function having more than m parameters + // is viable only if the (m+1)st parameter has a default argument + // (8.3.6). For the purposes of overload resolution, the + // parameter list is truncated on the right, so that there are + // exactly m parameters. + unsigned MinRequiredArgs = Method->getMinRequiredArguments(); + if (NumArgs < MinRequiredArgs) { + // Not enough arguments. + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_few_arguments; + return; + } + + Candidate.Viable = true; + Candidate.Conversions.resize(NumArgs + 1); + + if (Method->isStatic() || ObjectType.isNull()) + // The implicit object argument is ignored. + Candidate.IgnoreObjectArgument = true; + else { + // Determine the implicit conversion sequence for the object + // parameter. + Candidate.Conversions[0] + = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification, + Method, ActingContext); + if (Candidate.Conversions[0].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + return; + } + } + + // Determine the implicit conversion sequences for each of the + // arguments. + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + if (ArgIdx < NumArgsInProto) { + // (C++ 13.3.2p3): for F to be a viable function, there shall + // exist for each argument an implicit conversion sequence + // (13.3.3.1) that converts that argument to the corresponding + // parameter of F. + QualType ParamType = Proto->getArgType(ArgIdx); + Candidate.Conversions[ArgIdx + 1] + = TryCopyInitialization(*this, Args[ArgIdx], ParamType, + SuppressUserConversions, + /*InOverloadResolution=*/true); + if (Candidate.Conversions[ArgIdx + 1].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } else { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[ArgIdx + 1].setEllipsis(); + } + } +} + +/// \brief Add a C++ member function template as a candidate to the candidate +/// set, using template argument deduction to produce an appropriate member +/// function template specialization. +void +Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + TemplateArgumentListInfo *ExplicitTemplateArgs, + QualType ObjectType, + Expr::Classification ObjectClassification, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + if (!CandidateSet.isNewCandidate(MethodTmpl)) + return; + + // C++ [over.match.funcs]p7: + // In each case where a candidate is a function template, candidate + // function template specializations are generated using template argument + // deduction (14.8.3, 14.8.2). Those candidates are then handled as + // candidate functions in the usual way.113) A given name can refer to one + // or more function templates and also to a set of overloaded non-template + // functions. In such a case, the candidate functions generated from each + // function template are combined with the set of non-template candidate + // functions. + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult Result + = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, + Args, NumArgs, Specialization, Info)) { + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate &Candidate = CandidateSet.back(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = MethodTmpl->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + return; + } + + // Add the function template specialization produced by template argument + // deduction as a candidate. + assert(Specialization && "Missing member function template specialization?"); + assert(isa<CXXMethodDecl>(Specialization) && + "Specialization is not a member function?"); + AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, + ActingContext, ObjectType, ObjectClassification, + Args, NumArgs, CandidateSet, SuppressUserConversions); +} + +/// \brief Add a C++ function template specialization as a candidate +/// in the candidate set, using template argument deduction to produce +/// an appropriate function template specialization. +void +Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, + DeclAccessPair FoundDecl, + TemplateArgumentListInfo *ExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions) { + if (!CandidateSet.isNewCandidate(FunctionTemplate)) + return; + + // C++ [over.match.funcs]p7: + // In each case where a candidate is a function template, candidate + // function template specializations are generated using template argument + // deduction (14.8.3, 14.8.2). Those candidates are then handled as + // candidate functions in the usual way.113) A given name can refer to one + // or more function templates and also to a set of overloaded non-template + // functions. In such a case, the candidate functions generated from each + // function template are combined with the set of non-template candidate + // functions. + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, + Args, NumArgs, Specialization, Info)) { + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate &Candidate = CandidateSet.back(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + return; + } + + // Add the function template specialization produced by template argument + // deduction as a candidate. + assert(Specialization && "Missing function template specialization?"); + AddOverloadCandidate(Specialization, FoundDecl, Args, NumArgs, CandidateSet, + SuppressUserConversions); +} + +/// AddConversionCandidate - Add a C++ conversion function as a +/// candidate in the candidate set (C++ [over.match.conv], +/// C++ [over.match.copy]). From is the expression we're converting from, +/// and ToType is the type that we're eventually trying to convert to +/// (which may or may not be the same type as the type that the +/// conversion function produces). +void +Sema::AddConversionCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + Expr *From, QualType ToType, + OverloadCandidateSet& CandidateSet) { + assert(!Conversion->getDescribedFunctionTemplate() && + "Conversion function templates use AddTemplateConversionCandidate"); + QualType ConvType = Conversion->getConversionType().getNonReferenceType(); + if (!CandidateSet.isNewCandidate(Conversion)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + // Add this candidate + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate& Candidate = CandidateSet.back(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = Conversion; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.FinalConversion.setAsIdentityConversion(); + Candidate.FinalConversion.setFromType(ConvType); + Candidate.FinalConversion.setAllToTypes(ToType); + Candidate.Viable = true; + Candidate.Conversions.resize(1); + Candidate.ExplicitCallArguments = 1; + + // C++ [over.match.funcs]p4: + // For conversion functions, the function is considered to be a member of + // the class of the implicit implied object argument for the purpose of + // defining the type of the implicit object parameter. + // + // Determine the implicit conversion sequence for the implicit + // object parameter. + QualType ImplicitParamType = From->getType(); + if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>()) + ImplicitParamType = FromPtrType->getPointeeType(); + CXXRecordDecl *ConversionContext + = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl()); + + Candidate.Conversions[0] + = TryObjectArgumentInitialization(*this, From->getType(), + From->Classify(Context), + Conversion, ConversionContext); + + if (Candidate.Conversions[0].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + return; + } + + // We won't go through a user-define type conversion function to convert a + // derived to base as such conversions are given Conversion Rank. They only + // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user] + QualType FromCanon + = Context.getCanonicalType(From->getType().getUnqualifiedType()); + QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType(); + if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_trivial_conversion; + return; + } + + // To determine what the conversion from the result of calling the + // conversion function to the type we're eventually trying to + // convert to (ToType), we need to synthesize a call to the + // conversion function and attempt copy initialization from it. This + // makes sure that we get the right semantics with respect to + // lvalues/rvalues and the type. Fortunately, we can allocate this + // call on the stack and we don't need its arguments to be + // well-formed. + DeclRefExpr ConversionRef(Conversion, Conversion->getType(), + VK_LValue, From->getLocStart()); + ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, + Context.getPointerType(Conversion->getType()), + CK_FunctionToPointerDecay, + &ConversionRef, VK_RValue); + + QualType CallResultType + = Conversion->getConversionType().getNonLValueExprType(Context); + if (RequireCompleteType(From->getLocStart(), CallResultType, 0)) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + return; + } + + ExprValueKind VK = Expr::getValueKindForType(Conversion->getConversionType()); + + // Note that it is safe to allocate CallExpr on the stack here because + // there are 0 arguments (i.e., nothing is allocated using ASTContext's + // allocator). + CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK, + From->getLocStart()); + ImplicitConversionSequence ICS = + TryCopyInitialization(*this, &Call, ToType, + /*SuppressUserConversions=*/true, + /*InOverloadResolution=*/false); + + switch (ICS.getKind()) { + case ImplicitConversionSequence::StandardConversion: + Candidate.FinalConversion = ICS.Standard; + + // C++ [over.ics.user]p3: + // If the user-defined conversion is specified by a specialization of a + // conversion function template, the second standard conversion sequence + // shall have exact match rank. + if (Conversion->getPrimaryTemplate() && + GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_final_conversion_not_exact; + } + + // C++0x [dcl.init.ref]p5: + // In the second case, if the reference is an rvalue reference and + // the second standard conversion sequence of the user-defined + // conversion sequence includes an lvalue-to-rvalue conversion, the + // program is ill-formed. + if (ToType->isRValueReferenceType() && + ICS.Standard.First == ICK_Lvalue_To_Rvalue) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + } + break; + + case ImplicitConversionSequence::BadConversion: + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + break; + + default: + assert(false && + "Can only end up with a standard conversion sequence or failure"); + } +} + +/// \brief Adds a conversion function template specialization +/// candidate to the overload set, using template argument deduction +/// to deduce the template arguments of the conversion function +/// template from the type that we are converting to (C++ +/// [temp.deduct.conv]). +void +Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingDC, + Expr *From, QualType ToType, + OverloadCandidateSet &CandidateSet) { + assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) && + "Only conversion function templates permitted here"); + + if (!CandidateSet.isNewCandidate(FunctionTemplate)) + return; + + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + CXXConversionDecl *Specialization = 0; + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, ToType, + Specialization, Info)) { + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate &Candidate = CandidateSet.back(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_deduction; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = 1; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Info); + return; + } + + // Add the conversion function template specialization produced by + // template argument deduction as a candidate. + assert(Specialization && "Missing function template specialization?"); + AddConversionCandidate(Specialization, FoundDecl, ActingDC, From, ToType, + CandidateSet); +} + +/// AddSurrogateCandidate - Adds a "surrogate" candidate function that +/// converts the given @c Object to a function pointer via the +/// conversion function @c Conversion, and then attempts to call it +/// with the given arguments (C++ [over.call.object]p2-4). Proto is +/// the type of function that we'll eventually be calling. +void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, + DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, + const FunctionProtoType *Proto, + Expr *Object, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet) { + if (!CandidateSet.isNewCandidate(Conversion)) + return; + + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate& Candidate = CandidateSet.back(); + Candidate.FoundDecl = FoundDecl; + Candidate.Function = 0; + Candidate.Surrogate = Conversion; + Candidate.Viable = true; + Candidate.IsSurrogate = true; + Candidate.IgnoreObjectArgument = false; + Candidate.Conversions.resize(NumArgs + 1); + Candidate.ExplicitCallArguments = NumArgs; + + // Determine the implicit conversion sequence for the implicit + // object parameter. + ImplicitConversionSequence ObjectInit + = TryObjectArgumentInitialization(*this, Object->getType(), + Object->Classify(Context), + Conversion, ActingContext); + if (ObjectInit.isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + Candidate.Conversions[0] = ObjectInit; + return; + } + + // The first conversion is actually a user-defined conversion whose + // first conversion is ObjectInit's standard conversion (which is + // effectively a reference binding). Record it as such. + Candidate.Conversions[0].setUserDefined(); + Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard; + Candidate.Conversions[0].UserDefined.EllipsisConversion = false; + Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion; + Candidate.Conversions[0].UserDefined.FoundConversionFunction + = FoundDecl.getDecl(); + Candidate.Conversions[0].UserDefined.After + = Candidate.Conversions[0].UserDefined.Before; + Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion(); + + // Find the + unsigned NumArgsInProto = Proto->getNumArgs(); + + // (C++ 13.3.2p2): A candidate function having fewer than m + // parameters is viable only if it has an ellipsis in its parameter + // list (8.3.5). + if (NumArgs > NumArgsInProto && !Proto->isVariadic()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_many_arguments; + return; + } + + // Function types don't have any default arguments, so just check if + // we have enough arguments. + if (NumArgs < NumArgsInProto) { + // Not enough arguments. + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_too_few_arguments; + return; + } + + // Determine the implicit conversion sequences for each of the + // arguments. + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + if (ArgIdx < NumArgsInProto) { + // (C++ 13.3.2p3): for F to be a viable function, there shall + // exist for each argument an implicit conversion sequence + // (13.3.3.1) that converts that argument to the corresponding + // parameter of F. + QualType ParamType = Proto->getArgType(ArgIdx); + Candidate.Conversions[ArgIdx + 1] + = TryCopyInitialization(*this, Args[ArgIdx], ParamType, + /*SuppressUserConversions=*/false, + /*InOverloadResolution=*/false); + if (Candidate.Conversions[ArgIdx + 1].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } else { + // (C++ 13.3.2p2): For the purposes of overload resolution, any + // argument for which there is no corresponding parameter is + // considered to ""match the ellipsis" (C+ 13.3.3.1.3). + Candidate.Conversions[ArgIdx + 1].setEllipsis(); + } + } +} + +/// \brief Add overload candidates for overloaded operators that are +/// member functions. +/// +/// Add the overloaded operator candidates that are member functions +/// for the operator Op that was used in an operator expression such +/// as "x Op y". , Args/NumArgs provides the operator arguments, and +/// CandidateSet will store the added overload candidates. (C++ +/// [over.match.oper]). +void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + SourceRange OpRange) { + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + + // C++ [over.match.oper]p3: + // For a unary operator @ with an operand of a type whose + // cv-unqualified version is T1, and for a binary operator @ with + // a left operand of a type whose cv-unqualified version is T1 and + // a right operand of a type whose cv-unqualified version is T2, + // three sets of candidate functions, designated member + // candidates, non-member candidates and built-in candidates, are + // constructed as follows: + QualType T1 = Args[0]->getType(); + + // -- If T1 is a class type, the set of member candidates is the + // result of the qualified lookup of T1::operator@ + // (13.3.1.1.1); otherwise, the set of member candidates is + // empty. + if (const RecordType *T1Rec = T1->getAs<RecordType>()) { + // Complete the type if it can be completed. Otherwise, we're done. + if (RequireCompleteType(OpLoc, T1, PDiag())) + return; + + LookupResult Operators(*this, OpName, OpLoc, LookupOrdinaryName); + LookupQualifiedName(Operators, T1Rec->getDecl()); + Operators.suppressDiagnostics(); + + for (LookupResult::iterator Oper = Operators.begin(), + OperEnd = Operators.end(); + Oper != OperEnd; + ++Oper) + AddMethodCandidate(Oper.getPair(), Args[0]->getType(), + Args[0]->Classify(Context), Args + 1, NumArgs - 1, + CandidateSet, + /* SuppressUserConversions = */ false); + } +} + +/// AddBuiltinCandidate - Add a candidate for a built-in +/// operator. ResultTy and ParamTys are the result and parameter types +/// of the built-in candidate, respectively. Args and NumArgs are the +/// arguments being passed to the candidate. IsAssignmentOperator +/// should be true when this built-in candidate is an assignment +/// operator. NumContextualBoolArguments is the number of arguments +/// (at the beginning of the argument list) that will be contextually +/// converted to bool. +void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool IsAssignmentOperator, + unsigned NumContextualBoolArguments) { + // Overload resolution is always an unevaluated context. + EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated); + + // Add this candidate + CandidateSet.push_back(OverloadCandidate()); + OverloadCandidate& Candidate = CandidateSet.back(); + Candidate.FoundDecl = DeclAccessPair::make(0, AS_none); + Candidate.Function = 0; + Candidate.IsSurrogate = false; + Candidate.IgnoreObjectArgument = false; + Candidate.BuiltinTypes.ResultTy = ResultTy; + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + Candidate.BuiltinTypes.ParamTypes[ArgIdx] = ParamTys[ArgIdx]; + + // Determine the implicit conversion sequences for each of the + // arguments. + Candidate.Viable = true; + Candidate.Conversions.resize(NumArgs); + Candidate.ExplicitCallArguments = NumArgs; + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + // C++ [over.match.oper]p4: + // For the built-in assignment operators, conversions of the + // left operand are restricted as follows: + // -- no temporaries are introduced to hold the left operand, and + // -- no user-defined conversions are applied to the left + // operand to achieve a type match with the left-most + // parameter of a built-in candidate. + // + // We block these conversions by turning off user-defined + // conversions, since that is the only way that initialization of + // a reference to a non-class type can occur from something that + // is not of the same type. + if (ArgIdx < NumContextualBoolArguments) { + assert(ParamTys[ArgIdx] == Context.BoolTy && + "Contextual conversion to bool requires bool type"); + Candidate.Conversions[ArgIdx] + = TryContextuallyConvertToBool(*this, Args[ArgIdx]); + } else { + Candidate.Conversions[ArgIdx] + = TryCopyInitialization(*this, Args[ArgIdx], ParamTys[ArgIdx], + ArgIdx == 0 && IsAssignmentOperator, + /*InOverloadResolution=*/false); + } + if (Candidate.Conversions[ArgIdx].isBad()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_conversion; + break; + } + } +} + +/// BuiltinCandidateTypeSet - A set of types that will be used for the +/// candidate operator functions for built-in operators (C++ +/// [over.built]). The types are separated into pointer types and +/// enumeration types. +class BuiltinCandidateTypeSet { + /// TypeSet - A set of types. + typedef llvm::SmallPtrSet<QualType, 8> TypeSet; + + /// PointerTypes - The set of pointer types that will be used in the + /// built-in candidates. + TypeSet PointerTypes; + + /// MemberPointerTypes - The set of member pointer types that will be + /// used in the built-in candidates. + TypeSet MemberPointerTypes; + + /// EnumerationTypes - The set of enumeration types that will be + /// used in the built-in candidates. + TypeSet EnumerationTypes; + + /// \brief The set of vector types that will be used in the built-in + /// candidates. + TypeSet VectorTypes; + + /// \brief A flag indicating non-record types are viable candidates + bool HasNonRecordTypes; + + /// \brief A flag indicating whether either arithmetic or enumeration types + /// were present in the candidate set. + bool HasArithmeticOrEnumeralTypes; + + /// \brief A flag indicating whether the nullptr type was present in the + /// candidate set. + bool HasNullPtrType; + + /// Sema - The semantic analysis instance where we are building the + /// candidate type set. + Sema &SemaRef; + + /// Context - The AST context in which we will build the type sets. + ASTContext &Context; + + bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty, + const Qualifiers &VisibleQuals); + bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty); + +public: + /// iterator - Iterates through the types that are part of the set. + typedef TypeSet::iterator iterator; + + BuiltinCandidateTypeSet(Sema &SemaRef) + : HasNonRecordTypes(false), + HasArithmeticOrEnumeralTypes(false), + HasNullPtrType(false), + SemaRef(SemaRef), + Context(SemaRef.Context) { } + + void AddTypesConvertedFrom(QualType Ty, + SourceLocation Loc, + bool AllowUserConversions, + bool AllowExplicitConversions, + const Qualifiers &VisibleTypeConversionsQuals); + + /// pointer_begin - First pointer type found; + iterator pointer_begin() { return PointerTypes.begin(); } + + /// pointer_end - Past the last pointer type found; + iterator pointer_end() { return PointerTypes.end(); } + + /// member_pointer_begin - First member pointer type found; + iterator member_pointer_begin() { return MemberPointerTypes.begin(); } + + /// member_pointer_end - Past the last member pointer type found; + iterator member_pointer_end() { return MemberPointerTypes.end(); } + + /// enumeration_begin - First enumeration type found; + iterator enumeration_begin() { return EnumerationTypes.begin(); } + + /// enumeration_end - Past the last enumeration type found; + iterator enumeration_end() { return EnumerationTypes.end(); } + + iterator vector_begin() { return VectorTypes.begin(); } + iterator vector_end() { return VectorTypes.end(); } + + bool hasNonRecordTypes() { return HasNonRecordTypes; } + bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; } + bool hasNullPtrType() const { return HasNullPtrType; } +}; + +/// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to +/// the set of pointer types along with any more-qualified variants of +/// that type. For example, if @p Ty is "int const *", this routine +/// will add "int const *", "int const volatile *", "int const +/// restrict *", and "int const volatile restrict *" to the set of +/// pointer types. Returns true if the add of @p Ty itself succeeded, +/// false otherwise. +/// +/// FIXME: what to do about extended qualifiers? +bool +BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, + const Qualifiers &VisibleQuals) { + + // Insert this type. + if (!PointerTypes.insert(Ty)) + return false; + + QualType PointeeTy; + const PointerType *PointerTy = Ty->getAs<PointerType>(); + bool buildObjCPtr = false; + if (!PointerTy) { + if (const ObjCObjectPointerType *PTy = Ty->getAs<ObjCObjectPointerType>()) { + PointeeTy = PTy->getPointeeType(); + buildObjCPtr = true; + } + else + assert(false && "type was not a pointer type!"); + } + else + PointeeTy = PointerTy->getPointeeType(); + + // Don't add qualified variants of arrays. For one, they're not allowed + // (the qualifier would sink to the element type), and for another, the + // only overload situation where it matters is subscript or pointer +- int, + // and those shouldn't have qualifier variants anyway. + if (PointeeTy->isArrayType()) + return true; + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); + if (const ConstantArrayType *Array =Context.getAsConstantArrayType(PointeeTy)) + BaseCVR = Array->getElementType().getCVRQualifiers(); + bool hasVolatile = VisibleQuals.hasVolatile(); + bool hasRestrict = VisibleQuals.hasRestrict(); + + // Iterate through all strict supersets of BaseCVR. + for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { + if ((CVR | BaseCVR) != CVR) continue; + // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere + // in the types. + if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue; + if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue; + QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); + if (!buildObjCPtr) + PointerTypes.insert(Context.getPointerType(QPointeeTy)); + else + PointerTypes.insert(Context.getObjCObjectPointerType(QPointeeTy)); + } + + return true; +} + +/// AddMemberPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty +/// to the set of pointer types along with any more-qualified variants of +/// that type. For example, if @p Ty is "int const *", this routine +/// will add "int const *", "int const volatile *", "int const +/// restrict *", and "int const volatile restrict *" to the set of +/// pointer types. Returns true if the add of @p Ty itself succeeded, +/// false otherwise. +/// +/// FIXME: what to do about extended qualifiers? +bool +BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( + QualType Ty) { + // Insert this type. + if (!MemberPointerTypes.insert(Ty)) + return false; + + const MemberPointerType *PointerTy = Ty->getAs<MemberPointerType>(); + assert(PointerTy && "type was not a member pointer type!"); + + QualType PointeeTy = PointerTy->getPointeeType(); + // Don't add qualified variants of arrays. For one, they're not allowed + // (the qualifier would sink to the element type), and for another, the + // only overload situation where it matters is subscript or pointer +- int, + // and those shouldn't have qualifier variants anyway. + if (PointeeTy->isArrayType()) + return true; + const Type *ClassTy = PointerTy->getClass(); + + // Iterate through all strict supersets of the pointee type's CVR + // qualifiers. + unsigned BaseCVR = PointeeTy.getCVRQualifiers(); + for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { + if ((CVR | BaseCVR) != CVR) continue; + + QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); + MemberPointerTypes.insert( + Context.getMemberPointerType(QPointeeTy, ClassTy)); + } + + return true; +} + +/// AddTypesConvertedFrom - Add each of the types to which the type @p +/// Ty can be implicit converted to the given set of @p Types. We're +/// primarily interested in pointer types and enumeration types. We also +/// take member pointer types, for the conditional operator. +/// AllowUserConversions is true if we should look at the conversion +/// functions of a class type, and AllowExplicitConversions if we +/// should also include the explicit conversion functions of a class +/// type. +void +BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, + SourceLocation Loc, + bool AllowUserConversions, + bool AllowExplicitConversions, + const Qualifiers &VisibleQuals) { + // Only deal with canonical types. + Ty = Context.getCanonicalType(Ty); + + // Look through reference types; they aren't part of the type of an + // expression for the purposes of conversions. + if (const ReferenceType *RefTy = Ty->getAs<ReferenceType>()) + Ty = RefTy->getPointeeType(); + + // If we're dealing with an array type, decay to the pointer. + if (Ty->isArrayType()) + Ty = SemaRef.Context.getArrayDecayedType(Ty); + + // Otherwise, we don't care about qualifiers on the type. + Ty = Ty.getLocalUnqualifiedType(); + + // Flag if we ever add a non-record type. + const RecordType *TyRec = Ty->getAs<RecordType>(); + HasNonRecordTypes = HasNonRecordTypes || !TyRec; + + // Flag if we encounter an arithmetic type. + HasArithmeticOrEnumeralTypes = + HasArithmeticOrEnumeralTypes || Ty->isArithmeticType(); + + if (Ty->isObjCIdType() || Ty->isObjCClassType()) + PointerTypes.insert(Ty); + else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) { + // Insert our type, and its more-qualified variants, into the set + // of types. + if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals)) + return; + } else if (Ty->isMemberPointerType()) { + // Member pointers are far easier, since the pointee can't be converted. + if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty)) + return; + } else if (Ty->isEnumeralType()) { + HasArithmeticOrEnumeralTypes = true; + EnumerationTypes.insert(Ty); + } else if (Ty->isVectorType()) { + // We treat vector types as arithmetic types in many contexts as an + // extension. + HasArithmeticOrEnumeralTypes = true; + VectorTypes.insert(Ty); + } else if (Ty->isNullPtrType()) { + HasNullPtrType = true; + } else if (AllowUserConversions && TyRec) { + // No conversion functions in incomplete types. + if (SemaRef.RequireCompleteType(Loc, Ty, 0)) + return; + + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); + const UnresolvedSetImpl *Conversions + = ClassDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = I.getDecl(); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + // Skip conversion function templates; they don't tell us anything + // about which builtin types we can convert to. + if (isa<FunctionTemplateDecl>(D)) + continue; + + CXXConversionDecl *Conv = cast<CXXConversionDecl>(D); + if (AllowExplicitConversions || !Conv->isExplicit()) { + AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false, + VisibleQuals); + } + } + } +} + +/// \brief Helper function for AddBuiltinOperatorCandidates() that adds +/// the volatile- and non-volatile-qualified assignment operators for the +/// given type to the candidate set. +static void AddBuiltinAssignmentOperatorCandidates(Sema &S, + QualType T, + Expr **Args, + unsigned NumArgs, + OverloadCandidateSet &CandidateSet) { + QualType ParamTypes[2]; + + // T& operator=(T&, T) + ParamTypes[0] = S.Context.getLValueReferenceType(T); + ParamTypes[1] = T; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssignmentOperator=*/true); + + if (!S.Context.getCanonicalType(T).isVolatileQualified()) { + // volatile T& operator=(volatile T&, T) + ParamTypes[0] + = S.Context.getLValueReferenceType(S.Context.getVolatileType(T)); + ParamTypes[1] = T; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssignmentOperator=*/true); + } +} + +/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers, +/// if any, found in visible type conversion functions found in ArgExpr's type. +static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { + Qualifiers VRQuals; + const RecordType *TyRec; + if (const MemberPointerType *RHSMPType = + ArgExpr->getType()->getAs<MemberPointerType>()) + TyRec = RHSMPType->getClass()->getAs<RecordType>(); + else + TyRec = ArgExpr->getType()->getAs<RecordType>(); + if (!TyRec) { + // Just to be safe, assume the worst case. + VRQuals.addVolatile(); + VRQuals.addRestrict(); + return VRQuals; + } + + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); + if (!ClassDecl->hasDefinition()) + return VRQuals; + + const UnresolvedSetImpl *Conversions = + ClassDecl->getVisibleConversionFunctions(); + + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = I.getDecl(); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(D)) { + QualType CanTy = Context.getCanonicalType(Conv->getConversionType()); + if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>()) + CanTy = ResTypeRef->getPointeeType(); + // Need to go down the pointer/mempointer chain and add qualifiers + // as see them. + bool done = false; + while (!done) { + if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>()) + CanTy = ResTypePtr->getPointeeType(); + else if (const MemberPointerType *ResTypeMPtr = + CanTy->getAs<MemberPointerType>()) + CanTy = ResTypeMPtr->getPointeeType(); + else + done = true; + if (CanTy.isVolatileQualified()) + VRQuals.addVolatile(); + if (CanTy.isRestrictQualified()) + VRQuals.addRestrict(); + if (VRQuals.hasRestrict() && VRQuals.hasVolatile()) + return VRQuals; + } + } + } + return VRQuals; +} + +namespace { + +/// \brief Helper class to manage the addition of builtin operator overload +/// candidates. It provides shared state and utility methods used throughout +/// the process, as well as a helper method to add each group of builtin +/// operator overloads from the standard to a candidate set. +class BuiltinOperatorOverloadBuilder { + // Common instance state available to all overload candidate addition methods. + Sema &S; + Expr **Args; + unsigned NumArgs; + Qualifiers VisibleTypeConversionsQuals; + bool HasArithmeticOrEnumeralCandidateType; + llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes; + OverloadCandidateSet &CandidateSet; + + // Define some constants used to index and iterate over the arithemetic types + // provided via the getArithmeticType() method below. + // The "promoted arithmetic types" are the arithmetic + // types are that preserved by promotion (C++ [over.built]p2). + static const unsigned FirstIntegralType = 3; + static const unsigned LastIntegralType = 18; + static const unsigned FirstPromotedIntegralType = 3, + LastPromotedIntegralType = 9; + static const unsigned FirstPromotedArithmeticType = 0, + LastPromotedArithmeticType = 9; + static const unsigned NumArithmeticTypes = 18; + + /// \brief Get the canonical type for a given arithmetic type index. + CanQualType getArithmeticType(unsigned index) { + assert(index < NumArithmeticTypes); + static CanQualType ASTContext::* const + ArithmeticTypes[NumArithmeticTypes] = { + // Start of promoted types. + &ASTContext::FloatTy, + &ASTContext::DoubleTy, + &ASTContext::LongDoubleTy, + + // Start of integral types. + &ASTContext::IntTy, + &ASTContext::LongTy, + &ASTContext::LongLongTy, + &ASTContext::UnsignedIntTy, + &ASTContext::UnsignedLongTy, + &ASTContext::UnsignedLongLongTy, + // End of promoted types. + + &ASTContext::BoolTy, + &ASTContext::CharTy, + &ASTContext::WCharTy, + &ASTContext::Char16Ty, + &ASTContext::Char32Ty, + &ASTContext::SignedCharTy, + &ASTContext::ShortTy, + &ASTContext::UnsignedCharTy, + &ASTContext::UnsignedShortTy, + // End of integral types. + // FIXME: What about complex? + }; + return S.Context.*ArithmeticTypes[index]; + } + + /// \brief Gets the canonical type resulting from the usual arithemetic + /// converions for the given arithmetic types. + CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) { + // Accelerator table for performing the usual arithmetic conversions. + // The rules are basically: + // - if either is floating-point, use the wider floating-point + // - if same signedness, use the higher rank + // - if same size, use unsigned of the higher rank + // - use the larger type + // These rules, together with the axiom that higher ranks are + // never smaller, are sufficient to precompute all of these results + // *except* when dealing with signed types of higher rank. + // (we could precompute SLL x UI for all known platforms, but it's + // better not to make any assumptions). + enum PromotedType { + Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL, Dep=-1 + }; + static PromotedType ConversionsTable[LastPromotedArithmeticType] + [LastPromotedArithmeticType] = { + /* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt }, + /* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl }, + /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl }, + /* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL }, + /* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, Dep, UL, ULL }, + /* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, Dep, Dep, ULL }, + /* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, UI, UL, ULL }, + /* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, UL, UL, ULL }, + /* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, ULL, ULL, ULL }, + }; + + assert(L < LastPromotedArithmeticType); + assert(R < LastPromotedArithmeticType); + int Idx = ConversionsTable[L][R]; + + // Fast path: the table gives us a concrete answer. + if (Idx != Dep) return getArithmeticType(Idx); + + // Slow path: we need to compare widths. + // An invariant is that the signed type has higher rank. + CanQualType LT = getArithmeticType(L), + RT = getArithmeticType(R); + unsigned LW = S.Context.getIntWidth(LT), + RW = S.Context.getIntWidth(RT); + + // If they're different widths, use the signed type. + if (LW > RW) return LT; + else if (LW < RW) return RT; + + // Otherwise, use the unsigned type of the signed type's rank. + if (L == SL || R == SL) return S.Context.UnsignedLongTy; + assert(L == SLL || R == SLL); + return S.Context.UnsignedLongLongTy; + } + + /// \brief Helper method to factor out the common pattern of adding overloads + /// for '++' and '--' builtin operators. + void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy, + bool HasVolatile) { + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(CandidateTy), + S.Context.IntTy + }; + + // Non-volatile version. + if (NumArgs == 1) + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); + else + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + + // Use a heuristic to reduce number of builtin candidates in the set: + // add volatile version only if there are conversions to a volatile type. + if (HasVolatile) { + ParamTypes[0] = + S.Context.getLValueReferenceType( + S.Context.getVolatileType(CandidateTy)); + if (NumArgs == 1) + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); + else + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + } + } + +public: + BuiltinOperatorOverloadBuilder( + Sema &S, Expr **Args, unsigned NumArgs, + Qualifiers VisibleTypeConversionsQuals, + bool HasArithmeticOrEnumeralCandidateType, + llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes, + OverloadCandidateSet &CandidateSet) + : S(S), Args(Args), NumArgs(NumArgs), + VisibleTypeConversionsQuals(VisibleTypeConversionsQuals), + HasArithmeticOrEnumeralCandidateType( + HasArithmeticOrEnumeralCandidateType), + CandidateTypes(CandidateTypes), + CandidateSet(CandidateSet) { + // Validate some of our static helper constants in debug builds. + assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy && + "Invalid first promoted integral type"); + assert(getArithmeticType(LastPromotedIntegralType - 1) + == S.Context.UnsignedLongLongTy && + "Invalid last promoted integral type"); + assert(getArithmeticType(FirstPromotedArithmeticType) + == S.Context.FloatTy && + "Invalid first promoted arithmetic type"); + assert(getArithmeticType(LastPromotedArithmeticType - 1) + == S.Context.UnsignedLongLongTy && + "Invalid last promoted arithmetic type"); + } + + // C++ [over.built]p3: + // + // For every pair (T, VQ), where T is an arithmetic type, and VQ + // is either volatile or empty, there exist candidate operator + // functions of the form + // + // VQ T& operator++(VQ T&); + // T operator++(VQ T&, int); + // + // C++ [over.built]p4: + // + // For every pair (T, VQ), where T is an arithmetic type other + // than bool, and VQ is either volatile or empty, there exist + // candidate operator functions of the form + // + // VQ T& operator--(VQ T&); + // T operator--(VQ T&, int); + void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1); + Arith < NumArithmeticTypes; ++Arith) { + addPlusPlusMinusMinusStyleOverloads( + getArithmeticType(Arith), + VisibleTypeConversionsQuals.hasVolatile()); + } + } + + // C++ [over.built]p5: + // + // For every pair (T, VQ), where T is a cv-qualified or + // cv-unqualified object type, and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // T*VQ& operator++(T*VQ&); + // T*VQ& operator--(T*VQ&); + // T* operator++(T*VQ&, int); + // T* operator--(T*VQ&, int); + void addPlusPlusMinusMinusPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Skip pointer types that aren't pointers to object types. + if (!(*Ptr)->getPointeeType()->isObjectType()) + continue; + + addPlusPlusMinusMinusStyleOverloads(*Ptr, + (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile())); + } + } + + // C++ [over.built]p6: + // For every cv-qualified or cv-unqualified object type T, there + // exist candidate operator functions of the form + // + // T& operator*(T*); + // + // C++ [over.built]p7: + // For every function type T that does not have cv-qualifiers or a + // ref-qualifier, there exist candidate operator functions of the form + // T& operator*(T*); + void addUnaryStarPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTy = *Ptr; + QualType PointeeTy = ParamTy->getPointeeType(); + if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType()) + continue; + + if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>()) + if (Proto->getTypeQuals() || Proto->getRefQualifier()) + continue; + + S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy), + &ParamTy, Args, 1, CandidateSet); + } + } + + // C++ [over.built]p9: + // For every promoted arithmetic type T, there exist candidate + // operator functions of the form + // + // T operator+(T); + // T operator-(T); + void addUnaryPlusOrMinusArithmeticOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Arith = FirstPromotedArithmeticType; + Arith < LastPromotedArithmeticType; ++Arith) { + QualType ArithTy = getArithmeticType(Arith); + S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet); + } + + // Extension: We also add these operators for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec = CandidateTypes[0].vector_begin(), + VecEnd = CandidateTypes[0].vector_end(); + Vec != VecEnd; ++Vec) { + QualType VecTy = *Vec; + S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + } + } + + // C++ [over.built]p8: + // For every type T, there exist candidate operator functions of + // the form + // + // T* operator+(T*); + void addUnaryPlusPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTy = *Ptr; + S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet); + } + } + + // C++ [over.built]p10: + // For every promoted integral type T, there exist candidate + // operator functions of the form + // + // T operator~(T); + void addUnaryTildePromotedIntegralOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Int = FirstPromotedIntegralType; + Int < LastPromotedIntegralType; ++Int) { + QualType IntTy = getArithmeticType(Int); + S.AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet); + } + + // Extension: We also add this operator for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec = CandidateTypes[0].vector_begin(), + VecEnd = CandidateTypes[0].vector_end(); + Vec != VecEnd; ++Vec) { + QualType VecTy = *Vec; + S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + } + } + + // C++ [over.match.oper]p16: + // For every pointer to member type T, there exist candidate operator + // functions of the form + // + // bool operator==(T,T); + // bool operator!=(T,T); + void addEqualEqualOrNotEqualMemberPointerOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; + ++MemPtr) { + // Don't add the same builtin candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; + + QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + } + } + + // C++ [over.built]p15: + // + // For every T, where T is an enumeration type, a pointer type, or + // std::nullptr_t, there exist candidate operator functions of the form + // + // bool operator<(T, T); + // bool operator>(T, T); + // bool operator<=(T, T); + // bool operator>=(T, T); + // bool operator==(T, T); + // bool operator!=(T, T); + void addRelationalPointerOrEnumeralOverloads() { + // C++ [over.built]p1: + // If there is a user-written candidate with the same name and parameter + // types as a built-in candidate operator function, the built-in operator + // function is hidden and is not included in the set of candidate + // functions. + // + // The text is actually in a note, but if we don't implement it then we end + // up with ambiguities when the user provides an overloaded operator for + // an enumeration type. Note that only enumeration types have this problem, + // so we track which enumeration types we've seen operators for. Also, the + // only other overloaded operator with enumeration argumenst, operator=, + // cannot be overloaded for enumeration types, so this is the only place + // where we must suppress candidates like this. + llvm::DenseSet<std::pair<CanQualType, CanQualType> > + UserDefinedBinaryOperators; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + if (CandidateTypes[ArgIdx].enumeration_begin() != + CandidateTypes[ArgIdx].enumeration_end()) { + for (OverloadCandidateSet::iterator C = CandidateSet.begin(), + CEnd = CandidateSet.end(); + C != CEnd; ++C) { + if (!C->Viable || !C->Function || C->Function->getNumParams() != 2) + continue; + + QualType FirstParamType = + C->Function->getParamDecl(0)->getType().getUnqualifiedType(); + QualType SecondParamType = + C->Function->getParamDecl(1)->getType().getUnqualifiedType(); + + // Skip if either parameter isn't of enumeral type. + if (!FirstParamType->isEnumeralType() || + !SecondParamType->isEnumeralType()) + continue; + + // Add this operator to the set of known user-defined operators. + UserDefinedBinaryOperators.insert( + std::make_pair(S.Context.getCanonicalType(FirstParamType), + S.Context.getCanonicalType(SecondParamType))); + } + } + } + + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[ArgIdx].pointer_begin(), + PtrEnd = CandidateTypes[ArgIdx].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Don't add the same builtin candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + CanQualType CanonType = S.Context.getCanonicalType(*Enum); + + // Don't add the same builtin candidate twice, or if a user defined + // candidate exists. + if (!AddedTypes.insert(CanonType) || + UserDefinedBinaryOperators.count(std::make_pair(CanonType, + CanonType))) + continue; + + QualType ParamTypes[2] = { *Enum, *Enum }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + + if (CandidateTypes[ArgIdx].hasNullPtrType()) { + CanQualType NullPtrTy = S.Context.getCanonicalType(S.Context.NullPtrTy); + if (AddedTypes.insert(NullPtrTy) && + !UserDefinedBinaryOperators.count(std::make_pair(NullPtrTy, + NullPtrTy))) { + QualType ParamTypes[2] = { NullPtrTy, NullPtrTy }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + } + } + } + + // C++ [over.built]p13: + // + // For every cv-qualified or cv-unqualified object type T + // there exist candidate operator functions of the form + // + // T* operator+(T*, ptrdiff_t); + // T& operator[](T*, ptrdiff_t); [BELOW] + // T* operator-(T*, ptrdiff_t); + // T* operator+(ptrdiff_t, T*); + // T& operator[](ptrdiff_t, T*); [BELOW] + // + // C++ [over.built]p14: + // + // For every T, where T is a pointer to object type, there + // exist candidate operator functions of the form + // + // ptrdiff_t operator-(T, T); + void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (int Arg = 0; Arg < 2; ++Arg) { + QualType AsymetricParamTypes[2] = { + S.Context.getPointerDiffType(), + S.Context.getPointerDiffType(), + }; + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[Arg].pointer_begin(), + PtrEnd = CandidateTypes[Arg].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType PointeeTy = (*Ptr)->getPointeeType(); + if (!PointeeTy->isObjectType()) + continue; + + AsymetricParamTypes[Arg] = *Ptr; + if (Arg == 0 || Op == OO_Plus) { + // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) + // T* operator+(ptrdiff_t, T*); + S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, 2, + CandidateSet); + } + if (Op == OO_Minus) { + // ptrdiff_t operator-(T, T); + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes, + Args, 2, CandidateSet); + } + } + } + } + + // C++ [over.built]p12: + // + // For every pair of promoted arithmetic types L and R, there + // exist candidate operator functions of the form + // + // LR operator*(L, R); + // LR operator/(L, R); + // LR operator+(L, R); + // LR operator-(L, R); + // bool operator<(L, R); + // bool operator>(L, R); + // bool operator<=(L, R); + // bool operator>=(L, R); + // bool operator==(L, R); + // bool operator!=(L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + // + // C++ [over.built]p24: + // + // For every pair of promoted arithmetic types L and R, there exist + // candidate operator functions of the form + // + // LR operator?(bool, L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + // Our candidates ignore the first parameter. + void addGenericBinaryArithmeticOverloads(bool isComparison) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = FirstPromotedArithmeticType; + Left < LastPromotedArithmeticType; ++Left) { + for (unsigned Right = FirstPromotedArithmeticType; + Right < LastPromotedArithmeticType; ++Right) { + QualType LandR[2] = { getArithmeticType(Left), + getArithmeticType(Right) }; + QualType Result = + isComparison ? S.Context.BoolTy + : getUsualArithmeticConversions(Left, Right); + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + } + } + + // Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the + // conditional operator for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec1 = CandidateTypes[0].vector_begin(), + Vec1End = CandidateTypes[0].vector_end(); + Vec1 != Vec1End; ++Vec1) { + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes[1].vector_begin(), + Vec2End = CandidateTypes[1].vector_end(); + Vec2 != Vec2End; ++Vec2) { + QualType LandR[2] = { *Vec1, *Vec2 }; + QualType Result = S.Context.BoolTy; + if (!isComparison) { + if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType()) + Result = *Vec1; + else + Result = *Vec2; + } + + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + } + } + } + + // C++ [over.built]p17: + // + // For every pair of promoted integral types L and R, there + // exist candidate operator functions of the form + // + // LR operator%(L, R); + // LR operator&(L, R); + // LR operator^(L, R); + // LR operator|(L, R); + // L operator<<(L, R); + // L operator>>(L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = FirstPromotedIntegralType; + Left < LastPromotedIntegralType; ++Left) { + for (unsigned Right = FirstPromotedIntegralType; + Right < LastPromotedIntegralType; ++Right) { + QualType LandR[2] = { getArithmeticType(Left), + getArithmeticType(Right) }; + QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater) + ? LandR[0] + : getUsualArithmeticConversions(Left, Right); + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + } + } + } + + // C++ [over.built]p20: + // + // For every pair (T, VQ), where T is an enumeration or + // pointer to member type and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // VQ T& operator=(VQ T&, T); + void addAssignmentMemberPointerOrEnumeralOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum))) + continue; + + AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, 2, + CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; + + AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, 2, + CandidateSet); + } + } + } + + // C++ [over.built]p19: + // + // For every pair (T, VQ), where T is any type and VQ is either + // volatile or empty, there exist candidate operator functions + // of the form + // + // T*VQ& operator=(T*VQ&, T*); + // + // C++ [over.built]p21: + // + // For every pair (T, VQ), where T is a cv-qualified or + // cv-unqualified object type and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // T*VQ& operator+=(T*VQ&, ptrdiff_t); + // T*VQ& operator-=(T*VQ&, ptrdiff_t); + void addAssignmentPointerOverloads(bool isEqualOp) { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // If this is operator=, keep track of the builtin candidates we added. + if (isEqualOp) + AddedTypes.insert(S.Context.getCanonicalType(*Ptr)); + else if (!(*Ptr)->getPointeeType()->isObjectType()) + continue; + + // non-volatile version + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(*Ptr), + isEqualOp ? *Ptr : S.Context.getPointerDiffType(), + }; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/ isEqualOp); + + if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile()) { + // volatile version + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + } + } + + if (isEqualOp) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[1].pointer_begin(), + PtrEnd = CandidateTypes[1].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Make sure we don't add the same candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(*Ptr), + *Ptr, + }; + + // non-volatile version + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/true); + + if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile()) { + // volatile version + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, /*IsAssigmentOperator=*/true); + } + } + } + } + + // C++ [over.built]p18: + // + // For every triple (L, VQ, R), where L is an arithmetic type, + // VQ is either volatile or empty, and R is a promoted + // arithmetic type, there exist candidate operator functions of + // the form + // + // VQ L& operator=(VQ L&, R); + // VQ L& operator*=(VQ L&, R); + // VQ L& operator/=(VQ L&, R); + // VQ L& operator+=(VQ L&, R); + // VQ L& operator-=(VQ L&, R); + void addAssignmentArithmeticOverloads(bool isEqualOp) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) { + for (unsigned Right = FirstPromotedArithmeticType; + Right < LastPromotedArithmeticType; ++Right) { + QualType ParamTypes[2]; + ParamTypes[1] = getArithmeticType(Right); + + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = + S.Context.getLValueReferenceType(getArithmeticType(Left)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + + // Add this built-in operator as a candidate (VQ is 'volatile'). + if (VisibleTypeConversionsQuals.hasVolatile()) { + ParamTypes[0] = + S.Context.getVolatileType(getArithmeticType(Left)); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + } + } + } + + // Extension: Add the binary operators =, +=, -=, *=, /= for vector types. + for (BuiltinCandidateTypeSet::iterator + Vec1 = CandidateTypes[0].vector_begin(), + Vec1End = CandidateTypes[0].vector_end(); + Vec1 != Vec1End; ++Vec1) { + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes[1].vector_begin(), + Vec2End = CandidateTypes[1].vector_end(); + Vec2 != Vec2End; ++Vec2) { + QualType ParamTypes[2]; + ParamTypes[1] = *Vec2; + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + + // Add this built-in operator as a candidate (VQ is 'volatile'). + if (VisibleTypeConversionsQuals.hasVolatile()) { + ParamTypes[0] = S.Context.getVolatileType(*Vec1); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + } + } + } + } + + // C++ [over.built]p22: + // + // For every triple (L, VQ, R), where L is an integral type, VQ + // is either volatile or empty, and R is a promoted integral + // type, there exist candidate operator functions of the form + // + // VQ L& operator%=(VQ L&, R); + // VQ L& operator<<=(VQ L&, R); + // VQ L& operator>>=(VQ L&, R); + // VQ L& operator&=(VQ L&, R); + // VQ L& operator^=(VQ L&, R); + // VQ L& operator|=(VQ L&, R); + void addAssignmentIntegralOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; + + for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) { + for (unsigned Right = FirstPromotedIntegralType; + Right < LastPromotedIntegralType; ++Right) { + QualType ParamTypes[2]; + ParamTypes[1] = getArithmeticType(Right); + + // Add this built-in operator as a candidate (VQ is empty). + ParamTypes[0] = + S.Context.getLValueReferenceType(getArithmeticType(Left)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); + if (VisibleTypeConversionsQuals.hasVolatile()) { + // Add this built-in operator as a candidate (VQ is 'volatile'). + ParamTypes[0] = getArithmeticType(Left); + ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet); + } + } + } + } + + // C++ [over.operator]p23: + // + // There also exist candidate operator functions of the form + // + // bool operator!(bool); + // bool operator&&(bool, bool); + // bool operator||(bool, bool); + void addExclaimOverload() { + QualType ParamTy = S.Context.BoolTy; + S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet, + /*IsAssignmentOperator=*/false, + /*NumContextualBoolArguments=*/1); + } + void addAmpAmpOrPipePipeOverload() { + QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, CandidateSet, + /*IsAssignmentOperator=*/false, + /*NumContextualBoolArguments=*/2); + } + + // C++ [over.built]p13: + // + // For every cv-qualified or cv-unqualified object type T there + // exist candidate operator functions of the form + // + // T* operator+(T*, ptrdiff_t); [ABOVE] + // T& operator[](T*, ptrdiff_t); + // T* operator-(T*, ptrdiff_t); [ABOVE] + // T* operator+(ptrdiff_t, T*); [ABOVE] + // T& operator[](ptrdiff_t, T*); + void addSubscriptOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() }; + QualType PointeeType = (*Ptr)->getPointeeType(); + if (!PointeeType->isObjectType()) + continue; + + QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); + + // T& operator[](T*, ptrdiff_t) + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[1].pointer_begin(), + PtrEnd = CandidateTypes[1].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr }; + QualType PointeeType = (*Ptr)->getPointeeType(); + if (!PointeeType->isObjectType()) + continue; + + QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); + + // T& operator[](ptrdiff_t, T*) + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + } + + // C++ [over.built]p11: + // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type, + // C1 is the same type as C2 or is a derived class of C2, T is an object + // type or a function type, and CV1 and CV2 are cv-qualifier-seqs, + // there exist candidate operator functions of the form + // + // CV12 T& operator->*(CV1 C1*, CV2 T C2::*); + // + // where CV12 is the union of CV1 and CV2. + void addArrowStarOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType C1Ty = (*Ptr); + QualType C1; + QualifierCollector Q1; + C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0); + if (!isa<RecordType>(C1)) + continue; + // heuristic to reduce number of builtin candidates in the set. + // Add volatile/restrict version only if there are conversions to a + // volatile/restrict type. + if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile()) + continue; + if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict()) + continue; + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[1].member_pointer_begin(), + MemPtrEnd = CandidateTypes[1].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr); + QualType C2 = QualType(mptr->getClass(), 0); + C2 = C2.getUnqualifiedType(); + if (C1 != C2 && !S.IsDerivedFrom(C1, C2)) + break; + QualType ParamTypes[2] = { *Ptr, *MemPtr }; + // build CV12 T& + QualType T = mptr->getPointeeType(); + if (!VisibleTypeConversionsQuals.hasVolatile() && + T.isVolatileQualified()) + continue; + if (!VisibleTypeConversionsQuals.hasRestrict() && + T.isRestrictQualified()) + continue; + T = Q1.apply(S.Context, T); + QualType ResultTy = S.Context.getLValueReferenceType(T); + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + } + } + + // Note that we don't consider the first argument, since it has been + // contextually converted to bool long ago. The candidates below are + // therefore added as binary. + // + // C++ [over.built]p25: + // For every type T, where T is a pointer, pointer-to-member, or scoped + // enumeration type, there exist candidate operator functions of the form + // + // T operator?(bool, T, T); + // + void addConditionalOperatorOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[ArgIdx].pointer_begin(), + PtrEnd = CandidateTypes[ArgIdx].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; + + QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet); + } + + if (S.getLangOptions().CPlusPlus0x) { + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped()) + continue; + + if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum))) + continue; + + QualType ParamTypes[2] = { *Enum, *Enum }; + S.AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet); + } + } + } + } +}; + +} // end anonymous namespace + +/// AddBuiltinOperatorCandidates - Add the appropriate built-in +/// operator overloads to the candidate set (C++ [over.built]), based +/// on the operator @p Op and the arguments given. For example, if the +/// operator is a binary '+', this routine might add "int +/// operator+(int, int)" to cover integer addition. +void +Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet) { + // Find all of the types that the arguments can convert to, but only + // if the operator we're looking at has built-in operator candidates + // that make use of these types. Also record whether we encounter non-record + // candidate types or either arithmetic or enumeral candidate types. + Qualifiers VisibleTypeConversionsQuals; + VisibleTypeConversionsQuals.addConst(); + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]); + + bool HasNonRecordCandidateType = false; + bool HasArithmeticOrEnumeralCandidateType = false; + llvm::SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes; + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + CandidateTypes.push_back(BuiltinCandidateTypeSet(*this)); + CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(), + OpLoc, + true, + (Op == OO_Exclaim || + Op == OO_AmpAmp || + Op == OO_PipePipe), + VisibleTypeConversionsQuals); + HasNonRecordCandidateType = HasNonRecordCandidateType || + CandidateTypes[ArgIdx].hasNonRecordTypes(); + HasArithmeticOrEnumeralCandidateType = + HasArithmeticOrEnumeralCandidateType || + CandidateTypes[ArgIdx].hasArithmeticOrEnumeralTypes(); + } + + // Exit early when no non-record types have been added to the candidate set + // for any of the arguments to the operator. + if (!HasNonRecordCandidateType) + return; + + // Setup an object to manage the common state for building overloads. + BuiltinOperatorOverloadBuilder OpBuilder(*this, Args, NumArgs, + VisibleTypeConversionsQuals, + HasArithmeticOrEnumeralCandidateType, + CandidateTypes, CandidateSet); + + // Dispatch over the operation to add in only those overloads which apply. + switch (Op) { + case OO_None: + case NUM_OVERLOADED_OPERATORS: + assert(false && "Expected an overloaded operator"); + break; + + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + case OO_Call: + assert(false && "Special operators don't use AddBuiltinOperatorCandidates"); + break; + + case OO_Comma: + case OO_Arrow: + // C++ [over.match.oper]p3: + // -- For the operator ',', the unary operator '&', or the + // operator '->', the built-in candidates set is empty. + break; + + case OO_Plus: // '+' is either unary or binary + if (NumArgs == 1) + OpBuilder.addUnaryPlusPointerOverloads(); + // Fall through. + + case OO_Minus: // '-' is either unary or binary + if (NumArgs == 1) { + OpBuilder.addUnaryPlusOrMinusArithmeticOverloads(); + } else { + OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + } + break; + + case OO_Star: // '*' is either unary or binary + if (NumArgs == 1) + OpBuilder.addUnaryStarPointerOverloads(); + else + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + + case OO_Slash: + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + + case OO_PlusPlus: + case OO_MinusMinus: + OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op); + OpBuilder.addPlusPlusMinusMinusPointerOverloads(); + break; + + case OO_EqualEqual: + case OO_ExclaimEqual: + OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads(); + // Fall through. + + case OO_Less: + case OO_Greater: + case OO_LessEqual: + case OO_GreaterEqual: + OpBuilder.addRelationalPointerOrEnumeralOverloads(); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true); + break; + + case OO_Percent: + case OO_Caret: + case OO_Pipe: + case OO_LessLess: + case OO_GreaterGreater: + OpBuilder.addBinaryBitwiseArithmeticOverloads(Op); + break; + + case OO_Amp: // '&' is either unary or binary + if (NumArgs == 1) + // C++ [over.match.oper]p3: + // -- For the operator ',', the unary operator '&', or the + // operator '->', the built-in candidates set is empty. + break; + + OpBuilder.addBinaryBitwiseArithmeticOverloads(Op); + break; + + case OO_Tilde: + OpBuilder.addUnaryTildePromotedIntegralOverloads(); + break; + + case OO_Equal: + OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads(); + // Fall through. + + case OO_PlusEqual: + case OO_MinusEqual: + OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal); + // Fall through. + + case OO_StarEqual: + case OO_SlashEqual: + OpBuilder.addAssignmentArithmeticOverloads(Op == OO_Equal); + break; + + case OO_PercentEqual: + case OO_LessLessEqual: + case OO_GreaterGreaterEqual: + case OO_AmpEqual: + case OO_CaretEqual: + case OO_PipeEqual: + OpBuilder.addAssignmentIntegralOverloads(); + break; + + case OO_Exclaim: + OpBuilder.addExclaimOverload(); + break; + + case OO_AmpAmp: + case OO_PipePipe: + OpBuilder.addAmpAmpOrPipePipeOverload(); + break; + + case OO_Subscript: + OpBuilder.addSubscriptOverloads(); + break; + + case OO_ArrowStar: + OpBuilder.addArrowStarOverloads(); + break; + + case OO_Conditional: + OpBuilder.addConditionalOperatorOverloads(); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + } +} + +/// \brief Add function candidates found via argument-dependent lookup +/// to the set of overloading candidates. +/// +/// This routine performs argument-dependent name lookup based on the +/// given function name (which may also be an operator name) and adds +/// all of the overload candidates found by ADL to the overload +/// candidate set (C++ [basic.lookup.argdep]). +void +Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, + bool Operator, + Expr **Args, unsigned NumArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, + OverloadCandidateSet& CandidateSet, + bool PartialOverloading, + bool StdNamespaceIsAssociated) { + ADLResult Fns; + + // FIXME: This approach for uniquing ADL results (and removing + // redundant candidates from the set) relies on pointer-equality, + // which means we need to key off the canonical decl. However, + // always going back to the canonical decl might not get us the + // right set of default arguments. What default arguments are + // we supposed to consider on ADL candidates, anyway? + + // FIXME: Pass in the explicit template arguments? + ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns, + StdNamespaceIsAssociated); + + // Erase all of the candidates we already knew about. + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), + CandEnd = CandidateSet.end(); + Cand != CandEnd; ++Cand) + if (Cand->Function) { + Fns.erase(Cand->Function); + if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) + Fns.erase(FunTmpl); + } + + // For each of the ADL candidates we found, add it to the overload + // set. + for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { + DeclAccessPair FoundDecl = DeclAccessPair::make(*I, AS_none); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { + if (ExplicitTemplateArgs) + continue; + + AddOverloadCandidate(FD, FoundDecl, Args, NumArgs, CandidateSet, + false, PartialOverloading); + } else + AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), + FoundDecl, ExplicitTemplateArgs, + Args, NumArgs, CandidateSet); + } +} + +/// isBetterOverloadCandidate - Determines whether the first overload +/// candidate is a better candidate than the second (C++ 13.3.3p1). +bool +isBetterOverloadCandidate(Sema &S, + const OverloadCandidate &Cand1, + const OverloadCandidate &Cand2, + SourceLocation Loc, + bool UserDefinedConversion) { + // Define viable functions to be better candidates than non-viable + // functions. + if (!Cand2.Viable) + return Cand1.Viable; + else if (!Cand1.Viable) + return false; + + // C++ [over.match.best]p1: + // + // -- if F is a static member function, ICS1(F) is defined such + // that ICS1(F) is neither better nor worse than ICS1(G) for + // any function G, and, symmetrically, ICS1(G) is neither + // better nor worse than ICS1(F). + unsigned StartArg = 0; + if (Cand1.IgnoreObjectArgument || Cand2.IgnoreObjectArgument) + StartArg = 1; + + // C++ [over.match.best]p1: + // A viable function F1 is defined to be a better function than another + // viable function F2 if for all arguments i, ICSi(F1) is not a worse + // conversion sequence than ICSi(F2), and then... + unsigned NumArgs = Cand1.Conversions.size(); + assert(Cand2.Conversions.size() == NumArgs && "Overload candidate mismatch"); + bool HasBetterConversion = false; + for (unsigned ArgIdx = StartArg; ArgIdx < NumArgs; ++ArgIdx) { + switch (CompareImplicitConversionSequences(S, + Cand1.Conversions[ArgIdx], + Cand2.Conversions[ArgIdx])) { + case ImplicitConversionSequence::Better: + // Cand1 has a better conversion sequence. + HasBetterConversion = true; + break; + + case ImplicitConversionSequence::Worse: + // Cand1 can't be better than Cand2. + return false; + + case ImplicitConversionSequence::Indistinguishable: + // Do nothing. + break; + } + } + + // -- for some argument j, ICSj(F1) is a better conversion sequence than + // ICSj(F2), or, if not that, + if (HasBetterConversion) + return true; + + // - F1 is a non-template function and F2 is a function template + // specialization, or, if not that, + if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) && + Cand2.Function && Cand2.Function->getPrimaryTemplate()) + return true; + + // -- F1 and F2 are function template specializations, and the function + // template for F1 is more specialized than the template for F2 + // according to the partial ordering rules described in 14.5.5.2, or, + // if not that, + if (Cand1.Function && Cand1.Function->getPrimaryTemplate() && + Cand2.Function && Cand2.Function->getPrimaryTemplate()) { + if (FunctionTemplateDecl *BetterTemplate + = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(), + Cand2.Function->getPrimaryTemplate(), + Loc, + isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion + : TPOC_Call, + Cand1.ExplicitCallArguments)) + return BetterTemplate == Cand1.Function->getPrimaryTemplate(); + } + + // -- the context is an initialization by user-defined conversion + // (see 8.5, 13.3.1.5) and the standard conversion sequence + // from the return type of F1 to the destination type (i.e., + // the type of the entity being initialized) is a better + // conversion sequence than the standard conversion sequence + // from the return type of F2 to the destination type. + if (UserDefinedConversion && Cand1.Function && Cand2.Function && + isa<CXXConversionDecl>(Cand1.Function) && + isa<CXXConversionDecl>(Cand2.Function)) { + switch (CompareStandardConversionSequences(S, + Cand1.FinalConversion, + Cand2.FinalConversion)) { + case ImplicitConversionSequence::Better: + // Cand1 has a better conversion sequence. + return true; + + case ImplicitConversionSequence::Worse: + // Cand1 can't be better than Cand2. + return false; + + case ImplicitConversionSequence::Indistinguishable: + // Do nothing + break; + } + } + + return false; +} + +/// \brief Computes the best viable function (C++ 13.3.3) +/// within an overload candidate set. +/// +/// \param CandidateSet the set of candidate functions. +/// +/// \param Loc the location of the function name (or operator symbol) for +/// which overload resolution occurs. +/// +/// \param Best f overload resolution was successful or found a deleted +/// function, Best points to the candidate function found. +/// +/// \returns The result of overload resolution. +OverloadingResult +OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, + iterator &Best, + bool UserDefinedConversion) { + // Find the best viable function. + Best = end(); + for (iterator Cand = begin(); Cand != end(); ++Cand) { + if (Cand->Viable) + if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc, + UserDefinedConversion)) + Best = Cand; + } + + // If we didn't find any viable functions, abort. + if (Best == end()) + return OR_No_Viable_Function; + + // Make sure that this function is better than every other viable + // function. If not, we have an ambiguity. + for (iterator Cand = begin(); Cand != end(); ++Cand) { + if (Cand->Viable && + Cand != Best && + !isBetterOverloadCandidate(S, *Best, *Cand, Loc, + UserDefinedConversion)) { + Best = end(); + return OR_Ambiguous; + } + } + + // Best is the best viable function. + if (Best->Function && + (Best->Function->isDeleted() || Best->Function->isUnavailable())) + return OR_Deleted; + + return OR_Success; +} + +namespace { + +enum OverloadCandidateKind { + oc_function, + oc_method, + oc_constructor, + oc_function_template, + oc_method_template, + oc_constructor_template, + oc_implicit_default_constructor, + oc_implicit_copy_constructor, + oc_implicit_move_constructor, + oc_implicit_copy_assignment, + oc_implicit_move_assignment, + oc_implicit_inherited_constructor +}; + +OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, + FunctionDecl *Fn, + std::string &Description) { + bool isTemplate = false; + + if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) { + isTemplate = true; + Description = S.getTemplateArgumentBindingsText( + FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs()); + } + + if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) { + if (!Ctor->isImplicit()) + return isTemplate ? oc_constructor_template : oc_constructor; + + if (Ctor->getInheritedConstructor()) + return oc_implicit_inherited_constructor; + + if (Ctor->isDefaultConstructor()) + return oc_implicit_default_constructor; + + if (Ctor->isMoveConstructor()) + return oc_implicit_move_constructor; + + assert(Ctor->isCopyConstructor() && + "unexpected sort of implicit constructor"); + return oc_implicit_copy_constructor; + } + + if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) { + // This actually gets spelled 'candidate function' for now, but + // it doesn't hurt to split it out. + if (!Meth->isImplicit()) + return isTemplate ? oc_method_template : oc_method; + + if (Meth->isMoveAssignmentOperator()) + return oc_implicit_move_assignment; + + assert(Meth->isCopyAssignmentOperator() + && "implicit method is not copy assignment operator?"); + return oc_implicit_copy_assignment; + } + + return isTemplate ? oc_function_template : oc_function; +} + +void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) { + const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn); + if (!Ctor) return; + + Ctor = Ctor->getInheritedConstructor(); + if (!Ctor) return; + + S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor); +} + +} // end anonymous namespace + +// Notes the location of an overload candidate. +void Sema::NoteOverloadCandidate(FunctionDecl *Fn) { + std::string FnDesc; + OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc); + Diag(Fn->getLocation(), diag::note_ovl_candidate) + << (unsigned) K << FnDesc; + MaybeEmitInheritedConstructorNote(*this, Fn); +} + +//Notes the location of all overload candidates designated through +// OverloadedExpr +void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr) { + assert(OverloadedExpr->getType() == Context.OverloadTy); + + OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr); + OverloadExpr *OvlExpr = Ovl.Expression; + + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + IEnd = OvlExpr->decls_end(); + I != IEnd; ++I) { + if (FunctionTemplateDecl *FunTmpl = + dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) { + NoteOverloadCandidate(FunTmpl->getTemplatedDecl()); + } else if (FunctionDecl *Fun + = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) { + NoteOverloadCandidate(Fun); + } + } +} + +/// Diagnoses an ambiguous conversion. The partial diagnostic is the +/// "lead" diagnostic; it will be given two arguments, the source and +/// target types of the conversion. +void ImplicitConversionSequence::DiagnoseAmbiguousConversion( + Sema &S, + SourceLocation CaretLoc, + const PartialDiagnostic &PDiag) const { + S.Diag(CaretLoc, PDiag) + << Ambiguous.getFromType() << Ambiguous.getToType(); + for (AmbiguousConversionSequence::const_iterator + I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) { + S.NoteOverloadCandidate(*I); + } +} + +namespace { + +void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { + const ImplicitConversionSequence &Conv = Cand->Conversions[I]; + assert(Conv.isBad()); + assert(Cand->Function && "for now, candidate must be a function"); + FunctionDecl *Fn = Cand->Function; + + // There's a conversion slot for the object argument if this is a + // non-constructor method. Note that 'I' corresponds the + // conversion-slot index. + bool isObjectArgument = false; + if (isa<CXXMethodDecl>(Fn) && !isa<CXXConstructorDecl>(Fn)) { + if (I == 0) + isObjectArgument = true; + else + I--; + } + + std::string FnDesc; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); + + Expr *FromExpr = Conv.Bad.FromExpr; + QualType FromTy = Conv.Bad.getFromType(); + QualType ToTy = Conv.Bad.getToType(); + + if (FromTy == S.Context.OverloadTy) { + assert(FromExpr && "overload set argument came from implicit argument?"); + Expr *E = FromExpr->IgnoreParens(); + if (isa<UnaryOperator>(E)) + E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); + DeclarationName Name = cast<OverloadExpr>(E)->getName(); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << ToTy << Name << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // Do some hand-waving analysis to see if the non-viability is due + // to a qualifier mismatch. + CanQualType CFromTy = S.Context.getCanonicalType(FromTy); + CanQualType CToTy = S.Context.getCanonicalType(ToTy); + if (CanQual<ReferenceType> RT = CToTy->getAs<ReferenceType>()) + CToTy = RT->getPointeeType(); + else { + // TODO: detect and diagnose the full richness of const mismatches. + if (CanQual<PointerType> FromPT = CFromTy->getAs<PointerType>()) + if (CanQual<PointerType> ToPT = CToTy->getAs<PointerType>()) + CFromTy = FromPT->getPointeeType(), CToTy = ToPT->getPointeeType(); + } + + if (CToTy.getUnqualifiedType() == CFromTy.getUnqualifiedType() && + !CToTy.isAtLeastAsQualifiedAs(CFromTy)) { + // It is dumb that we have to do this here. + while (isa<ArrayType>(CFromTy)) + CFromTy = CFromTy->getAs<ArrayType>()->getElementType(); + while (isa<ArrayType>(CToTy)) + CToTy = CFromTy->getAs<ArrayType>()->getElementType(); + + Qualifiers FromQs = CFromTy.getQualifiers(); + Qualifiers ToQs = CToTy.getQualifiers(); + + if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy + << FromQs.getAddressSpace() << ToQs.getAddressSpace() + << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy + << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr() + << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); + assert(CVR && "unexpected qualifiers mismatch"); + + if (isObjectArgument) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << (CVR - 1); + } else { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << (CVR - 1) << I+1; + } + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // Diagnose references or pointers to incomplete types differently, + // since it's far from impossible that the incompleteness triggered + // the failure. + QualType TempFromTy = FromTy.getNonReferenceType(); + if (const PointerType *PTy = TempFromTy->getAs<PointerType>()) + TempFromTy = PTy->getPointeeType(); + if (TempFromTy->isIncompleteType()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // Diagnose base -> derived pointer conversions. + unsigned BaseToDerivedConversion = 0; + if (const PointerType *FromPtrTy = FromTy->getAs<PointerType>()) { + if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) { + if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( + FromPtrTy->getPointeeType()) && + !FromPtrTy->getPointeeType()->isIncompleteType() && + !ToPtrTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToPtrTy->getPointeeType(), + FromPtrTy->getPointeeType())) + BaseToDerivedConversion = 1; + } + } else if (const ObjCObjectPointerType *FromPtrTy + = FromTy->getAs<ObjCObjectPointerType>()) { + if (const ObjCObjectPointerType *ToPtrTy + = ToTy->getAs<ObjCObjectPointerType>()) + if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl()) + if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl()) + if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( + FromPtrTy->getPointeeType()) && + FromIface->isSuperClassOf(ToIface)) + BaseToDerivedConversion = 2; + } else if (const ReferenceType *ToRefTy = ToTy->getAs<ReferenceType>()) { + if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && + !FromTy->isIncompleteType() && + !ToRefTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) + BaseToDerivedConversion = 3; + } + + if (BaseToDerivedConversion) { + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_bad_base_to_derived_conv) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << (BaseToDerivedConversion - 1) + << FromTy << ToTy << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // TODO: specialize more based on the kind of mismatch + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); +} + +void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, + unsigned NumFormalArgs) { + // TODO: treat calls to a missing default constructor as a special case + + FunctionDecl *Fn = Cand->Function; + const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>(); + + unsigned MinParams = Fn->getMinRequiredArguments(); + + // With invalid overloaded operators, it's possible that we think we + // have an arity mismatch when it fact it looks like we have the + // right number of arguments, because only overloaded operators have + // the weird behavior of overloading member and non-member functions. + // Just don't report anything. + if (Fn->isInvalidDecl() && + Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) + return; + + // at least / at most / exactly + unsigned mode, modeCount; + if (NumFormalArgs < MinParams) { + assert((Cand->FailureKind == ovl_fail_too_few_arguments) || + (Cand->FailureKind == ovl_fail_bad_deduction && + Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments)); + if (MinParams != FnTy->getNumArgs() || + FnTy->isVariadic() || FnTy->isTemplateVariadic()) + mode = 0; // "at least" + else + mode = 2; // "exactly" + modeCount = MinParams; + } else { + assert((Cand->FailureKind == ovl_fail_too_many_arguments) || + (Cand->FailureKind == ovl_fail_bad_deduction && + Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments)); + if (MinParams != FnTy->getNumArgs()) + mode = 1; // "at most" + else + mode = 2; // "exactly" + modeCount = FnTy->getNumArgs(); + } + + std::string Description; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity) + << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode + << modeCount << NumFormalArgs; + MaybeEmitInheritedConstructorNote(S, Fn); +} + +/// Diagnose a failed template-argument deduction. +void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, + Expr **Args, unsigned NumArgs) { + FunctionDecl *Fn = Cand->Function; // pattern + + TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter(); + NamedDecl *ParamD; + (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) || + (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) || + (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>()); + switch (Cand->DeductionFailure.Result) { + case Sema::TDK_Success: + llvm_unreachable("TDK_success while diagnosing bad deduction"); + + case Sema::TDK_Incomplete: { + assert(ParamD && "no parameter found for incomplete deduction result"); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction) + << ParamD->getDeclName(); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + case Sema::TDK_Underqualified: { + assert(ParamD && "no parameter found for bad qualifiers deduction result"); + TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD); + + QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType(); + + // Param will have been canonicalized, but it should just be a + // qualified version of ParamD, so move the qualifiers to that. + QualifierCollector Qs; + Qs.strip(Param); + QualType NonCanonParam = Qs.apply(S.Context, TParam->getTypeForDecl()); + assert(S.Context.hasSameType(Param, NonCanonParam)); + + // Arg has also been canonicalized, but there's nothing we can do + // about that. It also doesn't matter as much, because it won't + // have any template parameters in it (because deduction isn't + // done on dependent types). + QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType(); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified) + << ParamD->getDeclName() << Arg << NonCanonParam; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + case Sema::TDK_Inconsistent: { + assert(ParamD && "no parameter found for inconsistent deduction result"); + int which = 0; + if (isa<TemplateTypeParmDecl>(ParamD)) + which = 0; + else if (isa<NonTypeTemplateParmDecl>(ParamD)) + which = 1; + else { + which = 2; + } + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction) + << which << ParamD->getDeclName() + << *Cand->DeductionFailure.getFirstArg() + << *Cand->DeductionFailure.getSecondArg(); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + case Sema::TDK_InvalidExplicitArguments: + assert(ParamD && "no parameter found for invalid explicit arguments"); + if (ParamD->getDeclName()) + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_explicit_arg_mismatch_named) + << ParamD->getDeclName(); + else { + int index = 0; + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD)) + index = TTP->getIndex(); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) + index = NTTP->getIndex(); + else + index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex(); + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_explicit_arg_mismatch_unnamed) + << (index + 1); + } + MaybeEmitInheritedConstructorNote(S, Fn); + return; + + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + DiagnoseArityMismatch(S, Cand, NumArgs); + return; + + case Sema::TDK_InstantiationDepth: + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + + case Sema::TDK_SubstitutionFailure: { + std::string ArgString; + if (TemplateArgumentList *Args + = Cand->DeductionFailure.getTemplateArgumentList()) + ArgString = S.getTemplateArgumentBindingsText( + Fn->getDescribedFunctionTemplate()->getTemplateParameters(), + *Args); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure) + << ArgString; + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // TODO: diagnose these individually, then kill off + // note_ovl_candidate_bad_deduction, which is uselessly vague. + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } +} + +/// Generates a 'note' diagnostic for an overload candidate. We've +/// already generated a primary error at the call site. +/// +/// It really does need to be a single diagnostic with its caret +/// pointed at the candidate declaration. Yes, this creates some +/// major challenges of technical writing. Yes, this makes pointing +/// out problems with specific arguments quite awkward. It's still +/// better than generating twenty screens of text for every failed +/// overload. +/// +/// It would be great to be able to express per-candidate problems +/// more richly for those diagnostic clients that cared, but we'd +/// still have to be just as careful with the default diagnostics. +void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, + Expr **Args, unsigned NumArgs) { + FunctionDecl *Fn = Cand->Function; + + // Note deleted candidates, but only if they're viable. + if (Cand->Viable && (Fn->isDeleted() || Fn->isUnavailable())) { + std::string FnDesc; + OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) + << FnKind << FnDesc << Fn->isDeleted(); + MaybeEmitInheritedConstructorNote(S, Fn); + return; + } + + // We don't really have anything else to say about viable candidates. + if (Cand->Viable) { + S.NoteOverloadCandidate(Fn); + return; + } + + switch (Cand->FailureKind) { + case ovl_fail_too_many_arguments: + case ovl_fail_too_few_arguments: + return DiagnoseArityMismatch(S, Cand, NumArgs); + + case ovl_fail_bad_deduction: + return DiagnoseBadDeduction(S, Cand, Args, NumArgs); + + case ovl_fail_trivial_conversion: + case ovl_fail_bad_final_conversion: + case ovl_fail_final_conversion_not_exact: + return S.NoteOverloadCandidate(Fn); + + case ovl_fail_bad_conversion: { + unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0); + for (unsigned N = Cand->Conversions.size(); I != N; ++I) + if (Cand->Conversions[I].isBad()) + return DiagnoseBadConversion(S, Cand, I); + + // FIXME: this currently happens when we're called from SemaInit + // when user-conversion overload fails. Figure out how to handle + // those conditions and diagnose them well. + return S.NoteOverloadCandidate(Fn); + } + } +} + +void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { + // Desugar the type of the surrogate down to a function type, + // retaining as many typedefs as possible while still showing + // the function type (and, therefore, its parameter types). + QualType FnType = Cand->Surrogate->getConversionType(); + bool isLValueReference = false; + bool isRValueReference = false; + bool isPointer = false; + if (const LValueReferenceType *FnTypeRef = + FnType->getAs<LValueReferenceType>()) { + FnType = FnTypeRef->getPointeeType(); + isLValueReference = true; + } else if (const RValueReferenceType *FnTypeRef = + FnType->getAs<RValueReferenceType>()) { + FnType = FnTypeRef->getPointeeType(); + isRValueReference = true; + } + if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) { + FnType = FnTypePtr->getPointeeType(); + isPointer = true; + } + // Desugar down to a function type. + FnType = QualType(FnType->getAs<FunctionType>(), 0); + // Reconstruct the pointer/reference as appropriate. + if (isPointer) FnType = S.Context.getPointerType(FnType); + if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType); + if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType); + + S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand) + << FnType; + MaybeEmitInheritedConstructorNote(S, Cand->Surrogate); +} + +void NoteBuiltinOperatorCandidate(Sema &S, + const char *Opc, + SourceLocation OpLoc, + OverloadCandidate *Cand) { + assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary"); + std::string TypeStr("operator"); + TypeStr += Opc; + TypeStr += "("; + TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); + if (Cand->Conversions.size() == 1) { + TypeStr += ")"; + S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr; + } else { + TypeStr += ", "; + TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString(); + TypeStr += ")"; + S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr; + } +} + +void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, + OverloadCandidate *Cand) { + unsigned NoOperands = Cand->Conversions.size(); + for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) { + const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx]; + if (ICS.isBad()) break; // all meaningless after first invalid + if (!ICS.isAmbiguous()) continue; + + ICS.DiagnoseAmbiguousConversion(S, OpLoc, + S.PDiag(diag::note_ambiguous_type_conversion)); + } +} + +SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { + if (Cand->Function) + return Cand->Function->getLocation(); + if (Cand->IsSurrogate) + return Cand->Surrogate->getLocation(); + return SourceLocation(); +} + +struct CompareOverloadCandidatesForDisplay { + Sema &S; + CompareOverloadCandidatesForDisplay(Sema &S) : S(S) {} + + bool operator()(const OverloadCandidate *L, + const OverloadCandidate *R) { + // Fast-path this check. + if (L == R) return false; + + // Order first by viability. + if (L->Viable) { + if (!R->Viable) return true; + + // TODO: introduce a tri-valued comparison for overload + // candidates. Would be more worthwhile if we had a sort + // that could exploit it. + if (isBetterOverloadCandidate(S, *L, *R, SourceLocation())) return true; + if (isBetterOverloadCandidate(S, *R, *L, SourceLocation())) return false; + } else if (R->Viable) + return false; + + assert(L->Viable == R->Viable); + + // Criteria by which we can sort non-viable candidates: + if (!L->Viable) { + // 1. Arity mismatches come after other candidates. + if (L->FailureKind == ovl_fail_too_many_arguments || + L->FailureKind == ovl_fail_too_few_arguments) + return false; + if (R->FailureKind == ovl_fail_too_many_arguments || + R->FailureKind == ovl_fail_too_few_arguments) + return true; + + // 2. Bad conversions come first and are ordered by the number + // of bad conversions and quality of good conversions. + if (L->FailureKind == ovl_fail_bad_conversion) { + if (R->FailureKind != ovl_fail_bad_conversion) + return true; + + // If there's any ordering between the defined conversions... + // FIXME: this might not be transitive. + assert(L->Conversions.size() == R->Conversions.size()); + + int leftBetter = 0; + unsigned I = (L->IgnoreObjectArgument || R->IgnoreObjectArgument); + for (unsigned E = L->Conversions.size(); I != E; ++I) { + switch (CompareImplicitConversionSequences(S, + L->Conversions[I], + R->Conversions[I])) { + case ImplicitConversionSequence::Better: + leftBetter++; + break; + + case ImplicitConversionSequence::Worse: + leftBetter--; + break; + + case ImplicitConversionSequence::Indistinguishable: + break; + } + } + if (leftBetter > 0) return true; + if (leftBetter < 0) return false; + + } else if (R->FailureKind == ovl_fail_bad_conversion) + return false; + + // TODO: others? + } + + // Sort everything else by location. + SourceLocation LLoc = GetLocationForCandidate(L); + SourceLocation RLoc = GetLocationForCandidate(R); + + // Put candidates without locations (e.g. builtins) at the end. + if (LLoc.isInvalid()) return false; + if (RLoc.isInvalid()) return true; + + return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc); + } +}; + +/// CompleteNonViableCandidate - Normally, overload resolution only +/// computes up to the first +void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, + Expr **Args, unsigned NumArgs) { + assert(!Cand->Viable); + + // Don't do anything on failures other than bad conversion. + if (Cand->FailureKind != ovl_fail_bad_conversion) return; + + // Skip forward to the first bad conversion. + unsigned ConvIdx = (Cand->IgnoreObjectArgument ? 1 : 0); + unsigned ConvCount = Cand->Conversions.size(); + while (true) { + assert(ConvIdx != ConvCount && "no bad conversion in candidate"); + ConvIdx++; + if (Cand->Conversions[ConvIdx - 1].isBad()) + break; + } + + if (ConvIdx == ConvCount) + return; + + assert(!Cand->Conversions[ConvIdx].isInitialized() && + "remaining conversion is initialized?"); + + // FIXME: this should probably be preserved from the overload + // operation somehow. + bool SuppressUserConversions = false; + + const FunctionProtoType* Proto; + unsigned ArgIdx = ConvIdx; + + if (Cand->IsSurrogate) { + QualType ConvType + = Cand->Surrogate->getConversionType().getNonReferenceType(); + if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) + ConvType = ConvPtrType->getPointeeType(); + Proto = ConvType->getAs<FunctionProtoType>(); + ArgIdx--; + } else if (Cand->Function) { + Proto = Cand->Function->getType()->getAs<FunctionProtoType>(); + if (isa<CXXMethodDecl>(Cand->Function) && + !isa<CXXConstructorDecl>(Cand->Function)) + ArgIdx--; + } else { + // Builtin binary operator with a bad first conversion. + assert(ConvCount <= 3); + for (; ConvIdx != ConvCount; ++ConvIdx) + Cand->Conversions[ConvIdx] + = TryCopyInitialization(S, Args[ConvIdx], + Cand->BuiltinTypes.ParamTypes[ConvIdx], + SuppressUserConversions, + /*InOverloadResolution*/ true); + return; + } + + // Fill in the rest of the conversions. + unsigned NumArgsInProto = Proto->getNumArgs(); + for (; ConvIdx != ConvCount; ++ConvIdx, ++ArgIdx) { + if (ArgIdx < NumArgsInProto) + Cand->Conversions[ConvIdx] + = TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx), + SuppressUserConversions, + /*InOverloadResolution=*/true); + else + Cand->Conversions[ConvIdx].setEllipsis(); + } +} + +} // end anonymous namespace + +/// PrintOverloadCandidates - When overload resolution fails, prints +/// diagnostic messages containing the candidates in the candidate +/// set. +void OverloadCandidateSet::NoteCandidates(Sema &S, + OverloadCandidateDisplayKind OCD, + Expr **Args, unsigned NumArgs, + const char *Opc, + SourceLocation OpLoc) { + // Sort the candidates by viability and position. Sorting directly would + // be prohibitive, so we make a set of pointers and sort those. + llvm::SmallVector<OverloadCandidate*, 32> Cands; + if (OCD == OCD_AllCandidates) Cands.reserve(size()); + for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) { + if (Cand->Viable) + Cands.push_back(Cand); + else if (OCD == OCD_AllCandidates) { + CompleteNonViableCandidate(S, Cand, Args, NumArgs); + if (Cand->Function || Cand->IsSurrogate) + Cands.push_back(Cand); + // Otherwise, this a non-viable builtin candidate. We do not, in general, + // want to list every possible builtin candidate. + } + } + + std::sort(Cands.begin(), Cands.end(), + CompareOverloadCandidatesForDisplay(S)); + + bool ReportedAmbiguousConversions = false; + + llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E; + const Diagnostic::OverloadsShown ShowOverloads = S.Diags.getShowOverloads(); + unsigned CandsShown = 0; + for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { + OverloadCandidate *Cand = *I; + + // Set an arbitrary limit on the number of candidate functions we'll spam + // the user with. FIXME: This limit should depend on details of the + // candidate list. + if (CandsShown >= 4 && ShowOverloads == Diagnostic::Ovl_Best) { + break; + } + ++CandsShown; + + if (Cand->Function) + NoteFunctionCandidate(S, Cand, Args, NumArgs); + else if (Cand->IsSurrogate) + NoteSurrogateCandidate(S, Cand); + else { + assert(Cand->Viable && + "Non-viable built-in candidates are not added to Cands."); + // Generally we only see ambiguities including viable builtin + // operators if overload resolution got screwed up by an + // ambiguous user-defined conversion. + // + // FIXME: It's quite possible for different conversions to see + // different ambiguities, though. + if (!ReportedAmbiguousConversions) { + NoteAmbiguousUserConversions(S, OpLoc, Cand); + ReportedAmbiguousConversions = true; + } + + // If this is a viable builtin, print it. + NoteBuiltinOperatorCandidate(S, Opc, OpLoc, Cand); + } + } + + if (I != E) + S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); +} + +// [PossiblyAFunctionType] --> [Return] +// NonFunctionType --> NonFunctionType +// R (A) --> R(A) +// R (*)(A) --> R (A) +// R (&)(A) --> R (A) +// R (S::*)(A) --> R (A) +QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) { + QualType Ret = PossiblyAFunctionType; + if (const PointerType *ToTypePtr = + PossiblyAFunctionType->getAs<PointerType>()) + Ret = ToTypePtr->getPointeeType(); + else if (const ReferenceType *ToTypeRef = + PossiblyAFunctionType->getAs<ReferenceType>()) + Ret = ToTypeRef->getPointeeType(); + else if (const MemberPointerType *MemTypePtr = + PossiblyAFunctionType->getAs<MemberPointerType>()) + Ret = MemTypePtr->getPointeeType(); + Ret = + Context.getCanonicalType(Ret).getUnqualifiedType(); + return Ret; +} + +// A helper class to help with address of function resolution +// - allows us to avoid passing around all those ugly parameters +class AddressOfFunctionResolver +{ + Sema& S; + Expr* SourceExpr; + const QualType& TargetType; + QualType TargetFunctionType; // Extracted function type from target type + + bool Complain; + //DeclAccessPair& ResultFunctionAccessPair; + ASTContext& Context; + + bool TargetTypeIsNonStaticMemberFunction; + bool FoundNonTemplateFunction; + + OverloadExpr::FindResult OvlExprInfo; + OverloadExpr *OvlExpr; + TemplateArgumentListInfo OvlExplicitTemplateArgs; + llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches; + +public: + AddressOfFunctionResolver(Sema &S, Expr* SourceExpr, + const QualType& TargetType, bool Complain) + : S(S), SourceExpr(SourceExpr), TargetType(TargetType), + Complain(Complain), Context(S.getASTContext()), + TargetTypeIsNonStaticMemberFunction( + !!TargetType->getAs<MemberPointerType>()), + FoundNonTemplateFunction(false), + OvlExprInfo(OverloadExpr::find(SourceExpr)), + OvlExpr(OvlExprInfo.Expression) + { + ExtractUnqualifiedFunctionTypeFromTargetType(); + + if (!TargetFunctionType->isFunctionType()) { + if (OvlExpr->hasExplicitTemplateArgs()) { + DeclAccessPair dap; + if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( + OvlExpr, false, &dap) ) { + + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { + if (!Method->isStatic()) { + // If the target type is a non-function type and the function + // found is a non-static member function, pretend as if that was + // the target, it's the only possible type to end up with. + TargetTypeIsNonStaticMemberFunction = true; + + // And skip adding the function if its not in the proper form. + // We'll diagnose this due to an empty set of functions. + if (!OvlExprInfo.HasFormOfMemberPointer) + return; + } + } + + Matches.push_back(std::make_pair(dap,Fn)); + } + } + return; + } + + if (OvlExpr->hasExplicitTemplateArgs()) + OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs); + + if (FindAllFunctionsThatMatchTargetTypeExactly()) { + // C++ [over.over]p4: + // If more than one function is selected, [...] + if (Matches.size() > 1) { + if (FoundNonTemplateFunction) + EliminateAllTemplateMatches(); + else + EliminateAllExceptMostSpecializedTemplate(); + } + } + } + +private: + bool isTargetTypeAFunction() const { + return TargetFunctionType->isFunctionType(); + } + + // [ToType] [Return] + + // R (*)(A) --> R (A), IsNonStaticMemberFunction = false + // R (&)(A) --> R (A), IsNonStaticMemberFunction = false + // R (S::*)(A) --> R (A), IsNonStaticMemberFunction = true + void inline ExtractUnqualifiedFunctionTypeFromTargetType() { + TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType); + } + + // return true if any matching specializations were found + bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate, + const DeclAccessPair& CurAccessFunPair) { + if (CXXMethodDecl *Method + = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) { + // Skip non-static function templates when converting to pointer, and + // static when converting to member pointer. + if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + return false; + } + else if (TargetTypeIsNonStaticMemberFunction) + return false; + + // C++ [over.over]p2: + // If the name is a function template, template argument deduction is + // done (14.8.2.2), and if the argument deduction succeeds, the + // resulting template argument list is used to generate a single + // function template specialization, which is added to the set of + // overloaded functions considered. + FunctionDecl *Specialization = 0; + TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); + if (Sema::TemplateDeductionResult Result + = S.DeduceTemplateArguments(FunctionTemplate, + &OvlExplicitTemplateArgs, + TargetFunctionType, Specialization, + Info)) { + // FIXME: make a note of the failed deduction for diagnostics. + (void)Result; + return false; + } + + // Template argument deduction ensures that we have an exact match. + // This function template specicalization works. + Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl()); + assert(TargetFunctionType + == Context.getCanonicalType(Specialization->getType())); + Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); + return true; + } + + bool AddMatchingNonTemplateFunction(NamedDecl* Fn, + const DeclAccessPair& CurAccessFunPair) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { + // Skip non-static functions when converting to pointer, and static + // when converting to member pointer. + if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + return false; + } + else if (TargetTypeIsNonStaticMemberFunction) + return false; + + if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) { + QualType ResultTy; + if (Context.hasSameUnqualifiedType(TargetFunctionType, + FunDecl->getType()) || + IsNoReturnConversion(Context, FunDecl->getType(), TargetFunctionType, + ResultTy)) { + Matches.push_back(std::make_pair(CurAccessFunPair, + cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); + FoundNonTemplateFunction = true; + return true; + } + } + + return false; + } + + bool FindAllFunctionsThatMatchTargetTypeExactly() { + bool Ret = false; + + // If the overload expression doesn't have the form of a pointer to + // member, don't try to convert it to a pointer-to-member type. + if (IsInvalidFormOfPointerToMemberFunction()) + return false; + + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + E = OvlExpr->decls_end(); + I != E; ++I) { + // Look through any using declarations to find the underlying function. + NamedDecl *Fn = (*I)->getUnderlyingDecl(); + + // C++ [over.over]p3: + // Non-member functions and static member functions match + // targets of type "pointer-to-function" or "reference-to-function." + // Nonstatic member functions match targets of + // type "pointer-to-member-function." + // Note that according to DR 247, the containing class does not matter. + if (FunctionTemplateDecl *FunctionTemplate + = dyn_cast<FunctionTemplateDecl>(Fn)) { + if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair())) + Ret = true; + } + // If we have explicit template arguments supplied, skip non-templates. + else if (!OvlExpr->hasExplicitTemplateArgs() && + AddMatchingNonTemplateFunction(Fn, I.getPair())) + Ret = true; + } + assert(Ret || Matches.empty()); + return Ret; + } + + void EliminateAllExceptMostSpecializedTemplate() { + // [...] and any given function template specialization F1 is + // eliminated if the set contains a second function template + // specialization whose function template is more specialized + // than the function template of F1 according to the partial + // ordering rules of 14.5.5.2. + + // The algorithm specified above is quadratic. We instead use a + // two-pass algorithm (similar to the one used to identify the + // best viable function in an overload set) that identifies the + // best function template (if it exists). + + UnresolvedSet<4> MatchesCopy; // TODO: avoid! + for (unsigned I = 0, E = Matches.size(); I != E; ++I) + MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess()); + + UnresolvedSetIterator Result = + S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(), + TPOC_Other, 0, SourceExpr->getLocStart(), + S.PDiag(), + S.PDiag(diag::err_addr_ovl_ambiguous) + << Matches[0].second->getDeclName(), + S.PDiag(diag::note_ovl_candidate) + << (unsigned) oc_function_template, + Complain); + + if (Result != MatchesCopy.end()) { + // Make it the first and only element + Matches[0].first = Matches[Result - MatchesCopy.begin()].first; + Matches[0].second = cast<FunctionDecl>(*Result); + Matches.resize(1); + } + } + + void EliminateAllTemplateMatches() { + // [...] any function template specializations in the set are + // eliminated if the set also contains a non-template function, [...] + for (unsigned I = 0, N = Matches.size(); I != N; ) { + if (Matches[I].second->getPrimaryTemplate() == 0) + ++I; + else { + Matches[I] = Matches[--N]; + Matches.set_size(N); + } + } + } + +public: + void ComplainNoMatchesFound() const { + assert(Matches.empty()); + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable) + << OvlExpr->getName() << TargetFunctionType + << OvlExpr->getSourceRange(); + S.NoteAllOverloadCandidates(OvlExpr); + } + + bool IsInvalidFormOfPointerToMemberFunction() const { + return TargetTypeIsNonStaticMemberFunction && + !OvlExprInfo.HasFormOfMemberPointer; + } + + void ComplainIsInvalidFormOfPointerToMemberFunction() const { + // TODO: Should we condition this on whether any functions might + // have matched, or is it more appropriate to do that in callers? + // TODO: a fixit wouldn't hurt. + S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier) + << TargetType << OvlExpr->getSourceRange(); + } + + void ComplainOfInvalidConversion() const { + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref) + << OvlExpr->getName() << TargetType; + } + + void ComplainMultipleMatchesFound() const { + assert(Matches.size() > 1); + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous) + << OvlExpr->getName() + << OvlExpr->getSourceRange(); + S.NoteAllOverloadCandidates(OvlExpr); + } + + int getNumMatches() const { return Matches.size(); } + + FunctionDecl* getMatchingFunctionDecl() const { + if (Matches.size() != 1) return 0; + return Matches[0].second; + } + + const DeclAccessPair* getMatchingFunctionAccessPair() const { + if (Matches.size() != 1) return 0; + return &Matches[0].first; + } +}; + +/// ResolveAddressOfOverloadedFunction - Try to resolve the address of +/// an overloaded function (C++ [over.over]), where @p From is an +/// expression with overloaded function type and @p ToType is the type +/// we're trying to resolve to. For example: +/// +/// @code +/// int f(double); +/// int f(int); +/// +/// int (*pfd)(double) = f; // selects f(double) +/// @endcode +/// +/// This routine returns the resulting FunctionDecl if it could be +/// resolved, and NULL otherwise. When @p Complain is true, this +/// routine will emit diagnostics if there is an error. +FunctionDecl * +Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, + bool Complain, + DeclAccessPair &FoundResult) { + + assert(AddressOfExpr->getType() == Context.OverloadTy); + + AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, Complain); + int NumMatches = Resolver.getNumMatches(); + FunctionDecl* Fn = 0; + if ( NumMatches == 0 && Complain) { + if (Resolver.IsInvalidFormOfPointerToMemberFunction()) + Resolver.ComplainIsInvalidFormOfPointerToMemberFunction(); + else + Resolver.ComplainNoMatchesFound(); + } + else if (NumMatches > 1 && Complain) + Resolver.ComplainMultipleMatchesFound(); + else if (NumMatches == 1) { + Fn = Resolver.getMatchingFunctionDecl(); + assert(Fn); + FoundResult = *Resolver.getMatchingFunctionAccessPair(); + MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn); + if (Complain) + CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); + } + + return Fn; +} + +/// \brief Given an expression that refers to an overloaded function, try to +/// resolve that overloaded function expression down to a single function. +/// +/// This routine can only resolve template-ids that refer to a single function +/// template, where that template-id refers to a single template whose template +/// arguments are either provided by the template-id or have defaults, +/// as described in C++0x [temp.arg.explicit]p3. +FunctionDecl * +Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, + bool Complain, + DeclAccessPair *FoundResult) { + // C++ [over.over]p1: + // [...] [Note: any redundant set of parentheses surrounding the + // overloaded function name is ignored (5.1). ] + // C++ [over.over]p1: + // [...] The overloaded function name can be preceded by the & + // operator. + + // If we didn't actually find any template-ids, we're done. + if (!ovl->hasExplicitTemplateArgs()) + return 0; + + TemplateArgumentListInfo ExplicitTemplateArgs; + ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); + + // Look through all of the overloaded functions, searching for one + // whose type matches exactly. + FunctionDecl *Matched = 0; + for (UnresolvedSetIterator I = ovl->decls_begin(), + E = ovl->decls_end(); I != E; ++I) { + // C++0x [temp.arg.explicit]p3: + // [...] In contexts where deduction is done and fails, or in contexts + // where deduction is not done, if a template argument list is + // specified and it, along with any default template arguments, + // identifies a single function template specialization, then the + // template-id is an lvalue for the function template specialization. + FunctionTemplateDecl *FunctionTemplate + = cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()); + + // C++ [over.over]p2: + // If the name is a function template, template argument deduction is + // done (14.8.2.2), and if the argument deduction succeeds, the + // resulting template argument list is used to generate a single + // function template specialization, which is added to the set of + // overloaded functions considered. + FunctionDecl *Specialization = 0; + TemplateDeductionInfo Info(Context, ovl->getNameLoc()); + if (TemplateDeductionResult Result + = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, + Specialization, Info)) { + // FIXME: make a note of the failed deduction for diagnostics. + (void)Result; + continue; + } + + assert(Specialization && "no specialization and no error?"); + + // Multiple matches; we can't resolve to a single declaration. + if (Matched) { + if (Complain) { + Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous) + << ovl->getName(); + NoteAllOverloadCandidates(ovl); + } + return 0; + } + + Matched = Specialization; + if (FoundResult) *FoundResult = I.getPair(); + } + + return Matched; +} + + + + +// Resolve and fix an overloaded expression that +// can be resolved because it identifies a single function +// template specialization +// Last three arguments should only be supplied if Complain = true +ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization( + Expr *SrcExpr, bool doFunctionPointerConverion, bool complain, + const SourceRange& OpRangeForComplaining, + QualType DestTypeForComplaining, + unsigned DiagIDForComplaining) { + assert(SrcExpr->getType() == Context.OverloadTy); + + OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr); + + DeclAccessPair found; + ExprResult SingleFunctionExpression; + if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( + ovl.Expression, /*complain*/ false, &found)) { + if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin())) + return ExprError(); + + // It is only correct to resolve to an instance method if we're + // resolving a form that's permitted to be a pointer to member. + // Otherwise we'll end up making a bound member expression, which + // is illegal in all the contexts we resolve like this. + if (!ovl.HasFormOfMemberPointer && + isa<CXXMethodDecl>(fn) && + cast<CXXMethodDecl>(fn)->isInstance()) { + if (complain) { + Diag(ovl.Expression->getExprLoc(), + diag::err_invalid_use_of_bound_member_func) + << ovl.Expression->getSourceRange(); + // TODO: I believe we only end up here if there's a mix of + // static and non-static candidates (otherwise the expression + // would have 'bound member' type, not 'overload' type). + // Ideally we would note which candidate was chosen and why + // the static candidates were rejected. + } + + return ExprError(); + } + + // Fix the expresion to refer to 'fn'. + SingleFunctionExpression = + Owned(FixOverloadedFunctionReference(SrcExpr, found, fn)); + + // If desired, do function-to-pointer decay. + if (doFunctionPointerConverion) + SingleFunctionExpression = + DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take()); + } + + if (!SingleFunctionExpression.isUsable()) { + if (complain) { + Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining) + << ovl.Expression->getName() + << DestTypeForComplaining + << OpRangeForComplaining + << ovl.Expression->getQualifierLoc().getSourceRange(); + NoteAllOverloadCandidates(SrcExpr); + } + return ExprError(); + } + + return SingleFunctionExpression; +} + +/// \brief Add a single candidate to the overload set. +static void AddOverloadedCallCandidate(Sema &S, + DeclAccessPair FoundDecl, + TemplateArgumentListInfo *ExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading) { + NamedDecl *Callee = FoundDecl.getDecl(); + if (isa<UsingShadowDecl>(Callee)) + Callee = cast<UsingShadowDecl>(Callee)->getTargetDecl(); + + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) { + assert(!ExplicitTemplateArgs && "Explicit template arguments?"); + S.AddOverloadCandidate(Func, FoundDecl, Args, NumArgs, CandidateSet, + false, PartialOverloading); + return; + } + + if (FunctionTemplateDecl *FuncTemplate + = dyn_cast<FunctionTemplateDecl>(Callee)) { + S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, + ExplicitTemplateArgs, + Args, NumArgs, CandidateSet); + return; + } + + assert(false && "unhandled case in overloaded call candidate"); + + // do nothing? +} + +/// \brief Add the overload candidates named by callee and/or found by argument +/// dependent lookup to the given overload set. +void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet, + bool PartialOverloading) { + +#ifndef NDEBUG + // Verify that ArgumentDependentLookup is consistent with the rules + // in C++0x [basic.lookup.argdep]p3: + // + // Let X be the lookup set produced by unqualified lookup (3.4.1) + // and let Y be the lookup set produced by argument dependent + // lookup (defined as follows). If X contains + // + // -- a declaration of a class member, or + // + // -- a block-scope function declaration that is not a + // using-declaration, or + // + // -- a declaration that is neither a function or a function + // template + // + // then Y is empty. + + if (ULE->requiresADL()) { + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) { + assert(!(*I)->getDeclContext()->isRecord()); + assert(isa<UsingShadowDecl>(*I) || + !(*I)->getDeclContext()->isFunctionOrMethod()); + assert((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate()); + } + } +#endif + + // It would be nice to avoid this copy. + TemplateArgumentListInfo TABuffer; + TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + + for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), + E = ULE->decls_end(); I != E; ++I) + AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, + Args, NumArgs, CandidateSet, + PartialOverloading); + + if (ULE->requiresADL()) + AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false, + Args, NumArgs, + ExplicitTemplateArgs, + CandidateSet, + PartialOverloading, + ULE->isStdAssociatedNamespace()); +} + +/// Attempt to recover from an ill-formed use of a non-dependent name in a +/// template, where the non-dependent name was declared after the template +/// was defined. This is common in code written for a compilers which do not +/// correctly implement two-stage name lookup. +/// +/// Returns true if a viable candidate was found and a diagnostic was issued. +static bool +DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, + const CXXScopeSpec &SS, LookupResult &R, + TemplateArgumentListInfo *ExplicitTemplateArgs, + Expr **Args, unsigned NumArgs) { + if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty()) + return false; + + for (DeclContext *DC = SemaRef.CurContext; DC; DC = DC->getParent()) { + SemaRef.LookupQualifiedName(R, DC); + + if (!R.empty()) { + R.suppressDiagnostics(); + + if (isa<CXXRecordDecl>(DC)) { + // Don't diagnose names we find in classes; we get much better + // diagnostics for these from DiagnoseEmptyLookup. + R.clear(); + return false; + } + + OverloadCandidateSet Candidates(FnLoc); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + AddOverloadedCallCandidate(SemaRef, I.getPair(), + ExplicitTemplateArgs, Args, NumArgs, + Candidates, false); + + OverloadCandidateSet::iterator Best; + if (Candidates.BestViableFunction(SemaRef, FnLoc, Best) != OR_Success) + // No viable functions. Don't bother the user with notes for functions + // which don't work and shouldn't be found anyway. + return false; + + // Find the namespaces where ADL would have looked, and suggest + // declaring the function there instead. + Sema::AssociatedNamespaceSet AssociatedNamespaces; + Sema::AssociatedClassSet AssociatedClasses; + SemaRef.FindAssociatedClassesAndNamespaces(Args, NumArgs, + AssociatedNamespaces, + AssociatedClasses); + // Never suggest declaring a function within namespace 'std'. + Sema::AssociatedNamespaceSet SuggestedNamespaces; + if (DeclContext *Std = SemaRef.getStdNamespace()) { + for (Sema::AssociatedNamespaceSet::iterator + it = AssociatedNamespaces.begin(), + end = AssociatedNamespaces.end(); it != end; ++it) { + if (!Std->Encloses(*it)) + SuggestedNamespaces.insert(*it); + } + } else { + // Lacking the 'std::' namespace, use all of the associated namespaces. + SuggestedNamespaces = AssociatedNamespaces; + } + + SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup) + << R.getLookupName(); + if (SuggestedNamespaces.empty()) { + SemaRef.Diag(Best->Function->getLocation(), + diag::note_not_found_by_two_phase_lookup) + << R.getLookupName() << 0; + } else if (SuggestedNamespaces.size() == 1) { + SemaRef.Diag(Best->Function->getLocation(), + diag::note_not_found_by_two_phase_lookup) + << R.getLookupName() << 1 << *SuggestedNamespaces.begin(); + } else { + // FIXME: It would be useful to list the associated namespaces here, + // but the diagnostics infrastructure doesn't provide a way to produce + // a localized representation of a list of items. + SemaRef.Diag(Best->Function->getLocation(), + diag::note_not_found_by_two_phase_lookup) + << R.getLookupName() << 2; + } + + // Try to recover by calling this function. + return true; + } + + R.clear(); + } + + return false; +} + +/// Attempt to recover from ill-formed use of a non-dependent operator in a +/// template, where the non-dependent operator was declared after the template +/// was defined. +/// +/// Returns true if a viable candidate was found and a diagnostic was issued. +static bool +DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs) { + DeclarationName OpName = + SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); + LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName); + return DiagnoseTwoPhaseLookup(SemaRef, OpLoc, CXXScopeSpec(), R, + /*ExplicitTemplateArgs=*/0, Args, NumArgs); +} + +/// Attempts to recover from a call where no functions were found. +/// +/// Returns true if new candidates were found. +static ExprResult +BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + bool EmptyLookup) { + + CXXScopeSpec SS; + SS.Adopt(ULE->getQualifierLoc()); + + TemplateArgumentListInfo TABuffer; + TemplateArgumentListInfo *ExplicitTemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TABuffer); + ExplicitTemplateArgs = &TABuffer; + } + + LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(), + Sema::LookupOrdinaryName); + if (!DiagnoseTwoPhaseLookup(SemaRef, Fn->getExprLoc(), SS, R, + ExplicitTemplateArgs, Args, NumArgs) && + (!EmptyLookup || + SemaRef.DiagnoseEmptyLookup(S, SS, R, Sema::CTC_Expression))) + return ExprError(); + + assert(!R.empty() && "lookup results empty despite recovery"); + + // Build an implicit member call if appropriate. Just drop the + // casts and such from the call, we don't really care. + ExprResult NewFn = ExprError(); + if ((*R.begin())->isCXXClassMember()) + NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, + ExplicitTemplateArgs); + else if (ExplicitTemplateArgs) + NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs); + else + NewFn = SemaRef.BuildDeclarationNameExpr(SS, R, false); + + if (NewFn.isInvalid()) + return ExprError(); + + // This shouldn't cause an infinite loop because we're giving it + // an expression with viable lookup results, which should never + // end up here. + return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc, + MultiExprArg(Args, NumArgs), RParenLoc); +} + +/// ResolveOverloadedCallFn - Given the call expression that calls Fn +/// (which eventually refers to the declaration Func) and the call +/// arguments Args/NumArgs, attempt to resolve the function call down +/// to a specific function. If overload resolution succeeds, returns +/// the function declaration produced by overload +/// resolution. Otherwise, emits diagnostics, deletes all of the +/// arguments and Fn, and returns NULL. +ExprResult +Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + Expr *ExecConfig) { +#ifndef NDEBUG + if (ULE->requiresADL()) { + // To do ADL, we must have found an unqualified name. + assert(!ULE->getQualifier() && "qualified name with ADL"); + + // We don't perform ADL for implicit declarations of builtins. + // Verify that this was correctly set up. + FunctionDecl *F; + if (ULE->decls_begin() + 1 == ULE->decls_end() && + (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) && + F->getBuiltinID() && F->isImplicit()) + assert(0 && "performing ADL for builtin"); + + // We don't perform ADL in C. + assert(getLangOptions().CPlusPlus && "ADL enabled in C"); + } else + assert(!ULE->isStdAssociatedNamespace() && + "std is associated namespace but not doing ADL"); +#endif + + OverloadCandidateSet CandidateSet(Fn->getExprLoc()); + + // Add the functions denoted by the callee to the set of candidate + // functions, including those from argument-dependent lookup. + AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet); + + // If we found nothing, try to recover. + // BuildRecoveryCallExpr diagnoses the error itself, so we just bail + // out if it fails. + if (CandidateSet.empty()) + return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, + RParenLoc, /*EmptyLookup=*/true); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { + case OR_Success: { + FunctionDecl *FDecl = Best->Function; + MarkDeclarationReferenced(Fn->getExprLoc(), FDecl); + CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); + DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(), + ULE->getNameLoc()); + Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc, + ExecConfig); + } + + case OR_No_Viable_Function: { + // Try to recover by looking for viable functions which the user might + // have meant to call. + ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, + Args, NumArgs, RParenLoc, + /*EmptyLookup=*/false); + if (!Recovery.isInvalid()) + return Recovery; + + Diag(Fn->getSourceRange().getBegin(), + diag::err_ovl_no_viable_function_in_call) + << ULE->getName() << Fn->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + break; + } + + case OR_Ambiguous: + Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call) + << ULE->getName() << Fn->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); + break; + + case OR_Deleted: + { + Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << ULE->getName() + << getDeletedOrUnavailableSuffix(Best->Function) + << Fn->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + } + break; + } + + // Overload resolution failed. + return ExprError(); +} + +static bool IsOverloaded(const UnresolvedSetImpl &Functions) { + return Functions.size() > 1 || + (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); +} + +/// \brief Create a unary operation that may resolve to an overloaded +/// operator. +/// +/// \param OpLoc The location of the operator itself (e.g., '*'). +/// +/// \param OpcIn The UnaryOperator::Opcode that describes this +/// operator. +/// +/// \param Functions The set of non-member functions that will be +/// considered by overload resolution. The caller needs to build this +/// set based on the context using, e.g., +/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This +/// set should not contain any member functions; those will be added +/// by CreateOverloadedUnaryOp(). +/// +/// \param input The input argument. +ExprResult +Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, + const UnresolvedSetImpl &Fns, + Expr *Input) { + UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn); + + OverloadedOperatorKind Op = UnaryOperator::getOverloadedOperator(Opc); + assert(Op != OO_None && "Invalid opcode for overloaded unary operator"); + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + // TODO: provide better source location info. + DeclarationNameInfo OpNameInfo(OpName, OpLoc); + + if (Input->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Input); + if (Result.isInvalid()) + return ExprError(); + Input = Result.take(); + } + + Expr *Args[2] = { Input, 0 }; + unsigned NumArgs = 1; + + // For post-increment and post-decrement, add the implicit '0' as + // the second argument, so that we know this is a post-increment or + // post-decrement. + if (Opc == UO_PostInc || Opc == UO_PostDec) { + llvm::APSInt Zero(Context.getTypeSize(Context.IntTy), false); + Args[1] = IntegerLiteral::Create(Context, Zero, Context.IntTy, + SourceLocation()); + NumArgs = 2; + } + + if (Input->isTypeDependent()) { + if (Fns.empty()) + return Owned(new (Context) UnaryOperator(Input, + Opc, + Context.DependentTy, + VK_RValue, OK_Ordinary, + OpLoc)); + + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators + UnresolvedLookupExpr *Fn + = UnresolvedLookupExpr::Create(Context, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, IsOverloaded(Fns), + Fns.begin(), Fns.end()); + return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, + &Args[0], NumArgs, + Context.DependentTy, + VK_RValue, + OpLoc)); + } + + // Build an empty overload set. + OverloadCandidateSet CandidateSet(OpLoc); + + // Add the candidates from the given function set. + AddFunctionCandidates(Fns, &Args[0], NumArgs, CandidateSet, false); + + // Add operator candidates that are member functions. + AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); + + // Add candidates from ADL. + AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, + Args, NumArgs, + /*ExplicitTemplateArgs*/ 0, + CandidateSet); + + // Add builtin operator candidates. + AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + MarkDeclarationReferenced(OpLoc, FnDecl); + + // Convert the arguments. + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { + CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl); + + ExprResult InputRes = + PerformObjectArgumentInitialization(Input, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (InputRes.isInvalid()) + return ExprError(); + Input = InputRes.take(); + } else { + // Convert the arguments. + ExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, + FnDecl->getParamDecl(0)), + SourceLocation(), + Input); + if (InputInit.isInvalid()) + return ExprError(); + Input = InputInit.take(); + } + + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + // Build the actual expression node. + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl); + if (FnExpr.isInvalid()) + return ExprError(); + + Args[0] = Input; + CallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), + Args, NumArgs, ResultTy, VK, OpLoc); + + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, + FnDecl)) + return ExprError(); + + return MaybeBindToTemporary(TheCall); + } else { + // We matched a built-in operator. Convert the arguments, then + // break out so that we will build the appropriate built-in + // operator node. + ExprResult InputRes = + PerformImplicitConversion(Input, Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (InputRes.isInvalid()) + return ExprError(); + Input = InputRes.take(); + break; + } + } + + case OR_No_Viable_Function: + // This is an erroneous use of an operator which can be overloaded by + // a non-member function. Check for non-member operators which were + // defined too late to be candidates. + if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args, NumArgs)) + // FIXME: Recover by calling the found function. + return ExprError(); + + // No viable function; fall through to handling this as a + // built-in operator, which will produce an error message for us. + break; + + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) + << UnaryOperator::getOpcodeStr(Opc) + << Input->getType() + << Input->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, + Args, NumArgs, + UnaryOperator::getOpcodeStr(Opc), OpLoc); + return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << UnaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function) + << Input->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + return ExprError(); + } + + // Either we found no viable overloaded operator or we matched a + // built-in operator. In either case, fall through to trying to + // build a built-in operation. + return CreateBuiltinUnaryOp(OpLoc, Opc, Input); +} + +/// \brief Create a binary operation that may resolve to an overloaded +/// operator. +/// +/// \param OpLoc The location of the operator itself (e.g., '+'). +/// +/// \param OpcIn The BinaryOperator::Opcode that describes this +/// operator. +/// +/// \param Functions The set of non-member functions that will be +/// considered by overload resolution. The caller needs to build this +/// set based on the context using, e.g., +/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This +/// set should not contain any member functions; those will be added +/// by CreateOverloadedBinOp(). +/// +/// \param LHS Left-hand argument. +/// \param RHS Right-hand argument. +ExprResult +Sema::CreateOverloadedBinOp(SourceLocation OpLoc, + unsigned OpcIn, + const UnresolvedSetImpl &Fns, + Expr *LHS, Expr *RHS) { + Expr *Args[2] = { LHS, RHS }; + LHS=RHS=0; //Please use only Args instead of LHS/RHS couple + + BinaryOperator::Opcode Opc = static_cast<BinaryOperator::Opcode>(OpcIn); + OverloadedOperatorKind Op = BinaryOperator::getOverloadedOperator(Opc); + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); + + // If either side is type-dependent, create an appropriate dependent + // expression. + if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { + if (Fns.empty()) { + // If there are no functions to store, just build a dependent + // BinaryOperator or CompoundAssignment. + if (Opc <= BO_Assign || Opc > BO_OrAssign) + return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc, + Context.DependentTy, + VK_RValue, OK_Ordinary, + OpLoc)); + + return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc, + Context.DependentTy, + VK_LValue, + OK_Ordinary, + Context.DependentTy, + Context.DependentTy, + OpLoc)); + } + + // FIXME: save results of ADL from here? + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators + // TODO: provide better source location info in DNLoc component. + DeclarationNameInfo OpNameInfo(OpName, OpLoc); + UnresolvedLookupExpr *Fn + = UnresolvedLookupExpr::Create(Context, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, IsOverloaded(Fns), + Fns.begin(), Fns.end()); + return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, + Args, 2, + Context.DependentTy, + VK_RValue, + OpLoc)); + } + + // Always do property rvalue conversions on the RHS. + if (Args[1]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[1]); + if (Result.isInvalid()) + return ExprError(); + Args[1] = Result.take(); + } + + // The LHS is more complicated. + if (Args[0]->getObjectKind() == OK_ObjCProperty) { + + // There's a tension for assignment operators between primitive + // property assignment and the overloaded operators. + if (BinaryOperator::isAssignmentOp(Opc)) { + const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty(); + + // Is the property "logically" settable? + bool Settable = (PRE->isExplicitProperty() || + PRE->getImplicitPropertySetter()); + + // To avoid gratuitously inventing semantics, use the primitive + // unless it isn't. Thoughts in case we ever really care: + // - If the property isn't logically settable, we have to + // load and hope. + // - If the property is settable and this is simple assignment, + // we really should use the primitive. + // - If the property is settable, then we could try overloading + // on a generic lvalue of the appropriate type; if it works + // out to a builtin candidate, we would do that same operation + // on the property, and otherwise just error. + if (Settable) + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + } + + ExprResult Result = ConvertPropertyForRValue(Args[0]); + if (Result.isInvalid()) + return ExprError(); + Args[0] = Result.take(); + } + + // If this is the assignment operator, we only perform overload resolution + // if the left-hand side is a class or enumeration type. This is actually + // a hack. The standard requires that we do overload resolution between the + // various built-in candidates, but as DR507 points out, this can lead to + // problems. So we do it this way, which pretty much follows what GCC does. + // Note that we go the traditional code path for compound assignment forms. + if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType()) + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + + // If this is the .* operator, which is not overloadable, just + // create a built-in binary operator. + if (Opc == BO_PtrMemD) + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + + // Build an empty overload set. + OverloadCandidateSet CandidateSet(OpLoc); + + // Add the candidates from the given function set. + AddFunctionCandidates(Fns, Args, 2, CandidateSet, false); + + // Add operator candidates that are member functions. + AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); + + // Add candidates from ADL. + AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, + Args, 2, + /*ExplicitTemplateArgs*/ 0, + CandidateSet); + + // Add builtin operator candidates. + AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + MarkDeclarationReferenced(OpLoc, FnDecl); + + // Convert the arguments. + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { + // Best->Access is only meaningful for class members. + CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl); + + ExprResult Arg1 = + PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(0)), + SourceLocation(), Owned(Args[1])); + if (Arg1.isInvalid()) + return ExprError(); + + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) + return ExprError(); + Args[0] = Arg0.takeAs<Expr>(); + Args[1] = RHS = Arg1.takeAs<Expr>(); + } else { + // Convert the arguments. + ExprResult Arg0 = PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(0)), + SourceLocation(), Owned(Args[0])); + if (Arg0.isInvalid()) + return ExprError(); + + ExprResult Arg1 = + PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(1)), + SourceLocation(), Owned(Args[1])); + if (Arg1.isInvalid()) + return ExprError(); + Args[0] = LHS = Arg0.takeAs<Expr>(); + Args[1] = RHS = Arg1.takeAs<Expr>(); + } + + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + // Build the actual expression node. + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc); + if (FnExpr.isInvalid()) + return ExprError(); + + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), + Args, 2, ResultTy, VK, OpLoc); + + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, + FnDecl)) + return ExprError(); + + return MaybeBindToTemporary(TheCall); + } else { + // We matched a built-in operator. Convert the arguments, then + // break out so that we will build the appropriate built-in + // operator node. + ExprResult ArgsRes0 = + PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (ArgsRes0.isInvalid()) + return ExprError(); + Args[0] = ArgsRes0.take(); + + ExprResult ArgsRes1 = + PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], AA_Passing); + if (ArgsRes1.isInvalid()) + return ExprError(); + Args[1] = ArgsRes1.take(); + break; + } + } + + case OR_No_Viable_Function: { + // C++ [over.match.oper]p9: + // If the operator is the operator , [...] and there are no + // viable functions, then the operator is assumed to be the + // built-in operator and interpreted according to clause 5. + if (Opc == BO_Comma) + break; + + // For class as left operand for assignment or compound assigment + // operator do not fall through to handling in built-in, but report that + // no overloaded assignment operator found + ExprResult Result = ExprError(); + if (Args[0]->getType()->isRecordType() && + Opc >= BO_Assign && Opc <= BO_OrAssign) { + Diag(OpLoc, diag::err_ovl_no_viable_oper) + << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + } else { + // This is an erroneous use of an operator which can be overloaded by + // a non-member function. Check for non-member operators which were + // defined too late to be candidates. + if (DiagnoseTwoPhaseOperatorLookup(*this, Op, OpLoc, Args, 2)) + // FIXME: Recover by calling the found function. + return ExprError(); + + // No viable function; try to create a built-in operation, which will + // produce an error. Then, show the non-viable candidates. + Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + } + assert(Result.isInvalid() && + "C++ binary operator overloading is missing candidates!"); + if (Result.isInvalid()) + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + BinaryOperator::getOpcodeStr(Opc), OpLoc); + return move(Result); + } + + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_binary) + << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getType() << Args[1]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, + BinaryOperator::getOpcodeStr(Opc), OpLoc); + return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << BinaryOperator::getOpcodeStr(Opc) + << getDeletedOrUnavailableSuffix(Best->Function) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2); + return ExprError(); + } + + // We matched a built-in operator; build it. + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); +} + +ExprResult +Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, + SourceLocation RLoc, + Expr *Base, Expr *Idx) { + Expr *Args[2] = { Base, Idx }; + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Subscript); + + // If either side is type-dependent, create an appropriate dependent + // expression. + if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { + + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators + // CHECKME: no 'operator' keyword? + DeclarationNameInfo OpNameInfo(OpName, LLoc); + OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); + UnresolvedLookupExpr *Fn + = UnresolvedLookupExpr::Create(Context, NamingClass, + NestedNameSpecifierLoc(), OpNameInfo, + /*ADL*/ true, /*Overloaded*/ false, + UnresolvedSetIterator(), + UnresolvedSetIterator()); + // Can't add any actual overloads yet + + return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn, + Args, 2, + Context.DependentTy, + VK_RValue, + RLoc)); + } + + if (Args[0]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[0]); + if (Result.isInvalid()) + return ExprError(); + Args[0] = Result.take(); + } + if (Args[1]->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Args[1]); + if (Result.isInvalid()) + return ExprError(); + Args[1] = Result.take(); + } + + // Build an empty overload set. + OverloadCandidateSet CandidateSet(LLoc); + + // Subscript can only be overloaded as a member function. + + // Add operator candidates that are member functions. + AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet); + + // Add builtin operator candidates. + AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, LLoc, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + MarkDeclarationReferenced(LLoc, FnDecl); + + CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LLoc); + + // Convert the arguments. + CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); + ExprResult Arg0 = + PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + Best->FoundDecl, Method); + if (Arg0.isInvalid()) + return ExprError(); + Args[0] = Arg0.take(); + + // Convert the arguments. + ExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, + FnDecl->getParamDecl(0)), + SourceLocation(), + Owned(Args[1])); + if (InputInit.isInvalid()) + return ExprError(); + + Args[1] = InputInit.takeAs<Expr>(); + + // Determine the result type + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + // Build the actual expression node. + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc); + if (FnExpr.isInvalid()) + return ExprError(); + + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Subscript, + FnExpr.take(), Args, 2, + ResultTy, VK, RLoc); + + if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, + FnDecl)) + return ExprError(); + + return MaybeBindToTemporary(TheCall); + } else { + // We matched a built-in operator. Convert the arguments, then + // break out so that we will build the appropriate built-in + // operator node. + ExprResult ArgsRes0 = + PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], AA_Passing); + if (ArgsRes0.isInvalid()) + return ExprError(); + Args[0] = ArgsRes0.take(); + + ExprResult ArgsRes1 = + PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], AA_Passing); + if (ArgsRes1.isInvalid()) + return ExprError(); + Args[1] = ArgsRes1.take(); + + break; + } + } + + case OR_No_Viable_Function: { + if (CandidateSet.empty()) + Diag(LLoc, diag::err_ovl_no_oper) + << Args[0]->getType() << /*subscript*/ 0 + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + else + Diag(LLoc, diag::err_ovl_no_viable_subscript) + << Args[0]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + "[]", LLoc); + return ExprError(); + } + + case OR_Ambiguous: + Diag(LLoc, diag::err_ovl_ambiguous_oper_binary) + << "[]" + << Args[0]->getType() << Args[1]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, + "[]", LLoc); + return ExprError(); + + case OR_Deleted: + Diag(LLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() << "[]" + << getDeletedOrUnavailableSuffix(Best->Function) + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, + "[]", LLoc); + return ExprError(); + } + + // We matched a built-in operator; build it. + return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc); +} + +/// BuildCallToMemberFunction - Build a call to a member +/// function. MemExpr is the expression that refers to the member +/// function (and includes the object parameter), Args/NumArgs are the +/// arguments to the function call (not including the object +/// parameter). The caller needs to validate that the member +/// expression refers to a non-static member function or an overloaded +/// member function. +ExprResult +Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, + SourceLocation LParenLoc, Expr **Args, + unsigned NumArgs, SourceLocation RParenLoc) { + assert(MemExprE->getType() == Context.BoundMemberTy || + MemExprE->getType() == Context.OverloadTy); + + // Dig out the member expression. This holds both the object + // argument and the member function we're referring to. + Expr *NakedMemExpr = MemExprE->IgnoreParens(); + + // Determine whether this is a call to a pointer-to-member function. + if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) { + assert(op->getType() == Context.BoundMemberTy); + assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI); + + QualType fnType = + op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType(); + + const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>(); + QualType resultType = proto->getCallResultType(Context); + ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType()); + + // Check that the object type isn't more qualified than the + // member function we're calling. + Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals()); + + QualType objectType = op->getLHS()->getType(); + if (op->getOpcode() == BO_PtrMemI) + objectType = objectType->castAs<PointerType>()->getPointeeType(); + Qualifiers objectQuals = objectType.getQualifiers(); + + Qualifiers difference = objectQuals - funcQuals; + difference.removeObjCGCAttr(); + difference.removeAddressSpace(); + if (difference) { + std::string qualsString = difference.getAsString(); + Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals) + << fnType.getUnqualifiedType() + << qualsString + << (qualsString.find(' ') == std::string::npos ? 1 : 2); + } + + CXXMemberCallExpr *call + = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + resultType, valueKind, RParenLoc); + + if (CheckCallReturnType(proto->getResultType(), + op->getRHS()->getSourceRange().getBegin(), + call, 0)) + return ExprError(); + + if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc)) + return ExprError(); + + return MaybeBindToTemporary(call); + } + + MemberExpr *MemExpr; + CXXMethodDecl *Method = 0; + DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public); + NestedNameSpecifier *Qualifier = 0; + if (isa<MemberExpr>(NakedMemExpr)) { + MemExpr = cast<MemberExpr>(NakedMemExpr); + Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl()); + FoundDecl = MemExpr->getFoundDecl(); + Qualifier = MemExpr->getQualifier(); + } else { + UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr); + Qualifier = UnresExpr->getQualifier(); + + QualType ObjectType = UnresExpr->getBaseType(); + Expr::Classification ObjectClassification + = UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue() + : UnresExpr->getBase()->Classify(Context); + + // Add overload candidates + OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc()); + + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; + if (UnresExpr->hasExplicitTemplateArgs()) { + UnresExpr->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + + for (UnresolvedMemberExpr::decls_iterator I = UnresExpr->decls_begin(), + E = UnresExpr->decls_end(); I != E; ++I) { + + NamedDecl *Func = *I; + CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(Func->getDeclContext()); + if (isa<UsingShadowDecl>(Func)) + Func = cast<UsingShadowDecl>(Func)->getTargetDecl(); + + + // Microsoft supports direct constructor calls. + if (getLangOptions().Microsoft && isa<CXXConstructorDecl>(Func)) { + AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, NumArgs, + CandidateSet); + } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { + // If explicit template arguments were provided, we can't call a + // non-template member function. + if (TemplateArgs) + continue; + + AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, + ObjectClassification, + Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/false); + } else { + AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func), + I.getPair(), ActingDC, TemplateArgs, + ObjectType, ObjectClassification, + Args, NumArgs, CandidateSet, + /*SuppressUsedConversions=*/false); + } + } + + DeclarationName DeclName = UnresExpr->getMemberName(); + + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(), + Best)) { + case OR_Success: + Method = cast<CXXMethodDecl>(Best->Function); + MarkDeclarationReferenced(UnresExpr->getMemberLoc(), Method); + FoundDecl = Best->FoundDecl; + CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); + break; + + case OR_No_Viable_Function: + Diag(UnresExpr->getMemberLoc(), + diag::err_ovl_no_viable_member_function_in_call) + << DeclName << MemExprE->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + // FIXME: Leaking incoming expressions! + return ExprError(); + + case OR_Ambiguous: + Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call) + << DeclName << MemExprE->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + // FIXME: Leaking incoming expressions! + return ExprError(); + + case OR_Deleted: + Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) + << Best->Function->isDeleted() + << DeclName + << getDeletedOrUnavailableSuffix(Best->Function) + << MemExprE->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + // FIXME: Leaking incoming expressions! + return ExprError(); + } + + MemExprE = FixOverloadedFunctionReference(MemExprE, FoundDecl, Method); + + // If overload resolution picked a static member, build a + // non-member call based on that function. + if (Method->isStatic()) { + return BuildResolvedCallExpr(MemExprE, Method, LParenLoc, + Args, NumArgs, RParenLoc); + } + + MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens()); + } + + QualType ResultType = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultType); + ResultType = ResultType.getNonLValueExprType(Context); + + assert(Method && "Member call to something that isn't a method?"); + CXXMemberCallExpr *TheCall = + new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + ResultType, VK, RParenLoc); + + // Check for a valid return type. + if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(), + TheCall, Method)) + return ExprError(); + + // Convert the object argument (for a non-static member function call). + // We only need to do this if there was actually an overload; otherwise + // it was done at lookup. + if (!Method->isStatic()) { + ExprResult ObjectArg = + PerformObjectArgumentInitialization(MemExpr->getBase(), Qualifier, + FoundDecl, Method); + if (ObjectArg.isInvalid()) + return ExprError(); + MemExpr->setBase(ObjectArg.take()); + } + + // Convert the rest of the arguments + const FunctionProtoType *Proto = + Method->getType()->getAs<FunctionProtoType>(); + if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs, + RParenLoc)) + return ExprError(); + + if (CheckFunctionCall(Method, TheCall)) + return ExprError(); + + if ((isa<CXXConstructorDecl>(CurContext) || + isa<CXXDestructorDecl>(CurContext)) && + TheCall->getMethodDecl()->isPure()) { + const CXXMethodDecl *MD = TheCall->getMethodDecl(); + + if (isa<CXXThisExpr>(MemExpr->getBase()->IgnoreParenCasts())) + Diag(MemExpr->getLocStart(), + diag::warn_call_to_pure_virtual_member_function_from_ctor_dtor) + << MD->getDeclName() << isa<CXXDestructorDecl>(CurContext) + << MD->getParent()->getDeclName(); + + Diag(MD->getLocStart(), diag::note_previous_decl) << MD->getDeclName(); + } + return MaybeBindToTemporary(TheCall); +} + +/// BuildCallToObjectOfClassType - Build a call to an object of class +/// type (C++ [over.call.object]), which can end up invoking an +/// overloaded function call operator (@c operator()) or performing a +/// user-defined conversion on the object argument. +ExprResult +Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc) { + ExprResult Object = Owned(Obj); + if (Object.get()->getObjectKind() == OK_ObjCProperty) { + Object = ConvertPropertyForRValue(Object.take()); + if (Object.isInvalid()) + return ExprError(); + } + + assert(Object.get()->getType()->isRecordType() && "Requires object type argument"); + const RecordType *Record = Object.get()->getType()->getAs<RecordType>(); + + // C++ [over.call.object]p1: + // If the primary-expression E in the function call syntax + // evaluates to a class object of type "cv T", then the set of + // candidate functions includes at least the function call + // operators of T. The function call operators of T are obtained by + // ordinary lookup of the name operator() in the context of + // (E).operator(). + OverloadCandidateSet CandidateSet(LParenLoc); + DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); + + if (RequireCompleteType(LParenLoc, Object.get()->getType(), + PDiag(diag::err_incomplete_object_call) + << Object.get()->getSourceRange())) + return true; + + LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); + LookupQualifiedName(R, Record->getDecl()); + R.suppressDiagnostics(); + + for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); + Oper != OperEnd; ++Oper) { + AddMethodCandidate(Oper.getPair(), Object.get()->getType(), + Object.get()->Classify(Context), Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/ false); + } + + // C++ [over.call.object]p2: + // In addition, for each conversion function declared in T of the + // form + // + // operator conversion-type-id () cv-qualifier; + // + // where cv-qualifier is the same cv-qualification as, or a + // greater cv-qualification than, cv, and where conversion-type-id + // denotes the type "pointer to function of (P1,...,Pn) returning + // R", or the type "reference to pointer to function of + // (P1,...,Pn) returning R", or the type "reference to function + // of (P1,...,Pn) returning R", a surrogate call function [...] + // is also considered as a candidate function. Similarly, + // surrogate call functions are added to the set of candidate + // functions for each conversion function declared in an + // accessible base class provided the function is not hidden + // within T by another intervening declaration. + const UnresolvedSetImpl *Conversions + = cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + // Skip over templated conversion functions; they aren't + // surrogates. + if (isa<FunctionTemplateDecl>(D)) + continue; + + CXXConversionDecl *Conv = cast<CXXConversionDecl>(D); + + // Strip the reference type (if any) and then the pointer type (if + // any) to get down to what might be a function type. + QualType ConvType = Conv->getConversionType().getNonReferenceType(); + if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) + ConvType = ConvPtrType->getPointeeType(); + + if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) + AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto, + Object.get(), Args, NumArgs, CandidateSet); + } + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, Object.get()->getLocStart(), + Best)) { + case OR_Success: + // Overload resolution succeeded; we'll build the appropriate call + // below. + break; + + case OR_No_Viable_Function: + if (CandidateSet.empty()) + Diag(Object.get()->getSourceRange().getBegin(), diag::err_ovl_no_oper) + << Object.get()->getType() << /*call*/ 1 + << Object.get()->getSourceRange(); + else + Diag(Object.get()->getSourceRange().getBegin(), + diag::err_ovl_no_viable_object_call) + << Object.get()->getType() << Object.get()->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + break; + + case OR_Ambiguous: + Diag(Object.get()->getSourceRange().getBegin(), + diag::err_ovl_ambiguous_object_call) + << Object.get()->getType() << Object.get()->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs); + break; + + case OR_Deleted: + Diag(Object.get()->getSourceRange().getBegin(), + diag::err_ovl_deleted_object_call) + << Best->Function->isDeleted() + << Object.get()->getType() + << getDeletedOrUnavailableSuffix(Best->Function) + << Object.get()->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, NumArgs); + break; + } + + if (Best == CandidateSet.end()) + return true; + + if (Best->Function == 0) { + // Since there is no function declaration, this is one of the + // surrogate candidates. Dig out the conversion function. + CXXConversionDecl *Conv + = cast<CXXConversionDecl>( + Best->Conversions[0].UserDefined.ConversionFunction); + + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); + + // We selected one of the surrogate functions that converts the + // object parameter to a function pointer. Perform the conversion + // on the object argument, then let ActOnCallExpr finish the job. + + // Create an implicit member expr to refer to the conversion operator. + // and then call it. + ExprResult Call = BuildCXXMemberCallExpr(Object.get(), Best->FoundDecl, Conv); + if (Call.isInvalid()) + return ExprError(); + + return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs), + RParenLoc); + } + + MarkDeclarationReferenced(LParenLoc, Best->Function); + CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc); + + // We found an overloaded operator(). Build a CXXOperatorCallExpr + // that calls this method, using Object for the implicit object + // parameter and passing along the remaining arguments. + CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); + const FunctionProtoType *Proto = + Method->getType()->getAs<FunctionProtoType>(); + + unsigned NumArgsInProto = Proto->getNumArgs(); + unsigned NumArgsToCheck = NumArgs; + + // Build the full argument list for the method call (the + // implicit object parameter is placed at the beginning of the + // list). + Expr **MethodArgs; + if (NumArgs < NumArgsInProto) { + NumArgsToCheck = NumArgsInProto; + MethodArgs = new Expr*[NumArgsInProto + 1]; + } else { + MethodArgs = new Expr*[NumArgs + 1]; + } + MethodArgs[0] = Object.get(); + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + MethodArgs[ArgIdx + 1] = Args[ArgIdx]; + + ExprResult NewFn = CreateFunctionRefExpr(*this, Method); + if (NewFn.isInvalid()) + return true; + + // Once we've built TheCall, all of the expressions are properly + // owned. + QualType ResultTy = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), + MethodArgs, NumArgs + 1, + ResultTy, VK, RParenLoc); + delete [] MethodArgs; + + if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, + Method)) + return true; + + // We may have default arguments. If so, we need to allocate more + // slots in the call for them. + if (NumArgs < NumArgsInProto) + TheCall->setNumArgs(Context, NumArgsInProto + 1); + else if (NumArgs > NumArgsInProto) + NumArgsToCheck = NumArgsInProto; + + bool IsError = false; + + // Initialize the implicit object parameter. + ExprResult ObjRes = + PerformObjectArgumentInitialization(Object.get(), /*Qualifier=*/0, + Best->FoundDecl, Method); + if (ObjRes.isInvalid()) + IsError = true; + else + Object = move(ObjRes); + TheCall->setArg(0, Object.take()); + + // Check the argument types. + for (unsigned i = 0; i != NumArgsToCheck; i++) { + Expr *Arg; + if (i < NumArgs) { + Arg = Args[i]; + + // Pass the argument. + + ExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, + Method->getParamDecl(i)), + SourceLocation(), Arg); + + IsError |= InputInit.isInvalid(); + Arg = InputInit.takeAs<Expr>(); + } else { + ExprResult DefArg + = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i)); + if (DefArg.isInvalid()) { + IsError = true; + break; + } + + Arg = DefArg.takeAs<Expr>(); + } + + TheCall->setArg(i + 1, Arg); + } + + // If this is a variadic call, handle args passed through "...". + if (Proto->isVariadic()) { + // Promote the arguments (C99 6.5.2.2p7). + for (unsigned i = NumArgsInProto; i != NumArgs; i++) { + ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, 0); + IsError |= Arg.isInvalid(); + TheCall->setArg(i + 1, Arg.take()); + } + } + + if (IsError) return true; + + if (CheckFunctionCall(Method, TheCall)) + return true; + + return MaybeBindToTemporary(TheCall); +} + +/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> +/// (if one exists), where @c Base is an expression of class type and +/// @c Member is the name of the member we're trying to find. +ExprResult +Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { + assert(Base->getType()->isRecordType() && + "left-hand side must have class type"); + + if (Base->getObjectKind() == OK_ObjCProperty) { + ExprResult Result = ConvertPropertyForRValue(Base); + if (Result.isInvalid()) + return ExprError(); + Base = Result.take(); + } + + SourceLocation Loc = Base->getExprLoc(); + + // C++ [over.ref]p1: + // + // [...] An expression x->m is interpreted as (x.operator->())->m + // for a class object x of type T if T::operator->() exists and if + // the operator is selected as the best match function by the + // overload resolution mechanism (13.3). + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Arrow); + OverloadCandidateSet CandidateSet(Loc); + const RecordType *BaseRecord = Base->getType()->getAs<RecordType>(); + + if (RequireCompleteType(Loc, Base->getType(), + PDiag(diag::err_typecheck_incomplete_tag) + << Base->getSourceRange())) + return ExprError(); + + LookupResult R(*this, OpName, OpLoc, LookupOrdinaryName); + LookupQualifiedName(R, BaseRecord->getDecl()); + R.suppressDiagnostics(); + + for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); + Oper != OperEnd; ++Oper) { + AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context), + 0, 0, CandidateSet, /*SuppressUserConversions=*/false); + } + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (CandidateSet.BestViableFunction(*this, OpLoc, Best)) { + case OR_Success: + // Overload resolution succeeded; we'll build the call below. + break; + + case OR_No_Viable_Function: + if (CandidateSet.empty()) + Diag(OpLoc, diag::err_typecheck_member_reference_arrow) + << Base->getType() << Base->getSourceRange(); + else + Diag(OpLoc, diag::err_ovl_no_viable_oper) + << "operator->" << Base->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); + return ExprError(); + + case OR_Ambiguous: + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) + << "->" << Base->getType() << Base->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, &Base, 1); + return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << "->" + << getDeletedOrUnavailableSuffix(Best->Function) + << Base->getSourceRange(); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &Base, 1); + return ExprError(); + } + + MarkDeclarationReferenced(OpLoc, Best->Function); + CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); + DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); + + // Convert the object parameter. + CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); + ExprResult BaseResult = + PerformObjectArgumentInitialization(Base, /*Qualifier=*/0, + Best->FoundDecl, Method); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + + // Build the operator call. + ExprResult FnExpr = CreateFunctionRefExpr(*this, Method); + if (FnExpr.isInvalid()) + return ExprError(); + + QualType ResultTy = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + CXXOperatorCallExpr *TheCall = + new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(), + &Base, 1, ResultTy, VK, OpLoc); + + if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, + Method)) + return ExprError(); + + return MaybeBindToTemporary(TheCall); +} + +/// FixOverloadedFunctionReference - E is an expression that refers to +/// a C++ overloaded function (possibly with some parentheses and +/// perhaps a '&' around it). We have resolved the overloaded function +/// to the function declaration Fn, so patch up the expression E to +/// refer (possibly indirectly) to Fn. Returns the new expr. +Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, + FunctionDecl *Fn) { + if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { + Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), + Found, Fn); + if (SubExpr == PE->getSubExpr()) + return PE; + + return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr); + } + + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), + Found, Fn); + assert(Context.hasSameType(ICE->getSubExpr()->getType(), + SubExpr->getType()) && + "Implicit cast type cannot be determined from overload"); + assert(ICE->path_empty() && "fixing up hierarchy conversion?"); + if (SubExpr == ICE->getSubExpr()) + return ICE; + + return ImplicitCastExpr::Create(Context, ICE->getType(), + ICE->getCastKind(), + SubExpr, 0, + ICE->getValueKind()); + } + + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) { + assert(UnOp->getOpcode() == UO_AddrOf && + "Can only take the address of an overloaded function"); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { + if (Method->isStatic()) { + // Do nothing: static member functions aren't any different + // from non-member functions. + } else { + // Fix the sub expression, which really has to be an + // UnresolvedLookupExpr holding an overloaded member function + // or template. + Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), + Found, Fn); + if (SubExpr == UnOp->getSubExpr()) + return UnOp; + + assert(isa<DeclRefExpr>(SubExpr) + && "fixed to something other than a decl ref"); + assert(cast<DeclRefExpr>(SubExpr)->getQualifier() + && "fixed to a member ref with no nested name qualifier"); + + // We have taken the address of a pointer to member + // function. Perform the computation here so that we get the + // appropriate pointer to member type. + QualType ClassType + = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); + QualType MemPtrType + = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr()); + + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType, + VK_RValue, OK_Ordinary, + UnOp->getOperatorLoc()); + } + } + Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), + Found, Fn); + if (SubExpr == UnOp->getSubExpr()) + return UnOp; + + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, + Context.getPointerType(SubExpr->getType()), + VK_RValue, OK_Ordinary, + UnOp->getOperatorLoc()); + } + + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; + if (ULE->hasExplicitTemplateArgs()) { + ULE->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + + return DeclRefExpr::Create(Context, + ULE->getQualifierLoc(), + Fn, + ULE->getNameLoc(), + Fn->getType(), + VK_LValue, + Found.getDecl(), + TemplateArgs); + } + + if (UnresolvedMemberExpr *MemExpr = dyn_cast<UnresolvedMemberExpr>(E)) { + // FIXME: avoid copy. + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; + if (MemExpr->hasExplicitTemplateArgs()) { + MemExpr->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + + Expr *Base; + + // If we're filling in a static method where we used to have an + // implicit member access, rewrite to a simple decl ref. + if (MemExpr->isImplicitAccess()) { + if (cast<CXXMethodDecl>(Fn)->isStatic()) { + return DeclRefExpr::Create(Context, + MemExpr->getQualifierLoc(), + Fn, + MemExpr->getMemberLoc(), + Fn->getType(), + VK_LValue, + Found.getDecl(), + TemplateArgs); + } else { + SourceLocation Loc = MemExpr->getMemberLoc(); + if (MemExpr->getQualifier()) + Loc = MemExpr->getQualifierLoc().getBeginLoc(); + Base = new (Context) CXXThisExpr(Loc, + MemExpr->getBaseType(), + /*isImplicit=*/true); + } + } else + Base = MemExpr->getBase(); + + ExprValueKind valueKind; + QualType type; + if (cast<CXXMethodDecl>(Fn)->isStatic()) { + valueKind = VK_LValue; + type = Fn->getType(); + } else { + valueKind = VK_RValue; + type = Context.BoundMemberTy; + } + + return MemberExpr::Create(Context, Base, + MemExpr->isArrow(), + MemExpr->getQualifierLoc(), + Fn, + Found, + MemExpr->getMemberNameInfo(), + TemplateArgs, + type, valueKind, OK_Ordinary); + } + + llvm_unreachable("Invalid reference to overloaded function"); + return E; +} + +ExprResult Sema::FixOverloadedFunctionReference(ExprResult E, + DeclAccessPair Found, + FunctionDecl *Fn) { + return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn)); +} + +} // end namespace clang diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp new file mode 100644 index 0000000..d7c0a54 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -0,0 +1,2312 @@ +//===--- SemaStmt.cpp - Semantic Analysis for Statements ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for statements. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/APValue.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/ArrayRef.h" +#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(); + if (!E) // FIXME: FullExprArg has no error state? + return StmtError(); + + // C99 6.8.3p2: The expression in an expression statement is evaluated as a + // void expression for its side effects. Conversion to void allows any + // operand, even incomplete types. + + // Same thing in for stmt first clause (when expr) and third clause. + return Owned(static_cast<Stmt*>(E)); +} + + +StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, + SourceLocation LeadingEmptyMacroLoc) { + return Owned(new (Context) NullStmt(SemiLoc, LeadingEmptyMacroLoc)); +} + +StmtResult Sema::ActOnDeclStmt(DeclGroupPtrTy dg, SourceLocation StartLoc, + SourceLocation EndLoc) { + DeclGroupRef DG = dg.getAsVal<DeclGroupRef>(); + + // If we have an invalid decl, just return an error. + if (DG.isNull()) return StmtError(); + + return Owned(new (Context) DeclStmt(DG, StartLoc, EndLoc)); +} + +void Sema::ActOnForEachDeclStmt(DeclGroupPtrTy dg) { + DeclGroupRef DG = dg.getAsVal<DeclGroupRef>(); + + // If we have an invalid decl, just return. + if (DG.isNull() || !DG.isSingleDecl()) return; + // suppress any potential 'unused variable' warning. + DG.getSingleDecl()->setUsed(); +} + +void Sema::DiagnoseUnusedExprResult(const Stmt *S) { + if (const LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S)) + return DiagnoseUnusedExprResult(Label->getSubStmt()); + + const Expr *E = dyn_cast_or_null<Expr>(S); + if (!E) + return; + + SourceLocation Loc; + SourceRange R1, R2; + if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) + return; + + // Okay, we have an unused result. Depending on what the base expression is, + // we might want to make a more specific diagnostic. Check for one of these + // cases now. + unsigned DiagID = diag::warn_unused_expr; + if (const ExprWithCleanups *Temps = dyn_cast<ExprWithCleanups>(E)) + E = Temps->getSubExpr(); + if (const CXXBindTemporaryExpr *TempExpr = dyn_cast<CXXBindTemporaryExpr>(E)) + E = TempExpr->getSubExpr(); + + E = E->IgnoreParenImpCasts(); + if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { + if (E->getType()->isVoidType()) + return; + + // If the callee has attribute pure, const, or warn_unused_result, warn with + // a more specific message to make it clear what is happening. + if (const Decl *FD = CE->getCalleeDecl()) { + if (FD->getAttr<WarnUnusedResultAttr>()) { + Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result"; + return; + } + if (FD->getAttr<PureAttr>()) { + Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure"; + return; + } + if (FD->getAttr<ConstAttr>()) { + Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const"; + return; + } + } + } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { + const ObjCMethodDecl *MD = ME->getMethodDecl(); + if (MD && MD->getAttr<WarnUnusedResultAttr>()) { + Diag(Loc, diag::warn_unused_call) << R1 << R2 << "warn_unused_result"; + return; + } + } else if (isa<ObjCPropertyRefExpr>(E)) { + DiagID = diag::warn_unused_property_expr; + } else if (const CXXFunctionalCastExpr *FC + = dyn_cast<CXXFunctionalCastExpr>(E)) { + if (isa<CXXConstructExpr>(FC->getSubExpr()) || + isa<CXXTemporaryObjectExpr>(FC->getSubExpr())) + return; + } + // Diagnose "(void*) blah" as a typo for "(void) blah". + else if (const CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(E)) { + TypeSourceInfo *TI = CE->getTypeInfoAsWritten(); + QualType T = TI->getType(); + + // We really do want to use the non-canonical type here. + if (T == Context.VoidPtrTy) { + PointerTypeLoc TL = cast<PointerTypeLoc>(TI->getTypeLoc()); + + Diag(Loc, diag::warn_unused_voidptr) + << FixItHint::CreateRemoval(TL.getStarLoc()); + return; + } + } + + DiagRuntimeBehavior(Loc, 0, PDiag(DiagID) << R1 << R2); +} + +StmtResult +Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, + MultiStmtArg elts, bool isStmtExpr) { + unsigned NumElts = elts.size(); + Stmt **Elts = reinterpret_cast<Stmt**>(elts.release()); + // If we're in C89 mode, check that we don't have any decls after stmts. If + // so, emit an extension diagnostic. + if (!getLangOptions().C99 && !getLangOptions().CPlusPlus) { + // Note that __extension__ can be around a decl. + unsigned i = 0; + // Skip over all declarations. + for (; i != NumElts && isa<DeclStmt>(Elts[i]); ++i) + /*empty*/; + + // We found the end of the list or a statement. Scan for another declstmt. + for (; i != NumElts && !isa<DeclStmt>(Elts[i]); ++i) + /*empty*/; + + if (i != NumElts) { + Decl *D = *cast<DeclStmt>(Elts[i])->decl_begin(); + Diag(D->getLocation(), diag::ext_mixed_decls_code); + } + } + // Warn about unused expressions in statements. + for (unsigned i = 0; i != NumElts; ++i) { + // Ignore statements that are last in a statement expression. + if (isStmtExpr && i == NumElts - 1) + continue; + + DiagnoseUnusedExprResult(Elts[i]); + } + + return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R)); +} + +StmtResult +Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, + SourceLocation DotDotDotLoc, Expr *RHSVal, + SourceLocation ColonLoc) { + assert((LHSVal != 0) && "missing expression in case statement"); + + // C99 6.8.4.2p3: The expression shall be an integer constant. + // However, GCC allows any evaluatable integer expression. + if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent() && + VerifyIntegerConstantExpression(LHSVal)) + return StmtError(); + + // GCC extension: The expression shall be an integer constant. + + if (RHSVal && !RHSVal->isTypeDependent() && !RHSVal->isValueDependent() && + VerifyIntegerConstantExpression(RHSVal)) { + RHSVal = 0; // Recover by just forgetting about it. + } + + if (getCurFunction()->SwitchStack.empty()) { + Diag(CaseLoc, diag::err_case_not_in_switch); + return StmtError(); + } + + CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc, + ColonLoc); + getCurFunction()->SwitchStack.back()->addSwitchCase(CS); + return Owned(CS); +} + +/// ActOnCaseStmtBody - This installs a statement as the body of a case. +void Sema::ActOnCaseStmtBody(Stmt *caseStmt, Stmt *SubStmt) { + CaseStmt *CS = static_cast<CaseStmt*>(caseStmt); + CS->setSubStmt(SubStmt); +} + +StmtResult +Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, + Stmt *SubStmt, Scope *CurScope) { + if (getCurFunction()->SwitchStack.empty()) { + Diag(DefaultLoc, diag::err_default_not_in_switch); + return Owned(SubStmt); + } + + DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt); + getCurFunction()->SwitchStack.back()->addSwitchCase(DS); + return Owned(DS); +} + +StmtResult +Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, + SourceLocation ColonLoc, Stmt *SubStmt) { + + // If the label was multiply defined, reject it now. + if (TheDecl->getStmt()) { + Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName(); + Diag(TheDecl->getLocation(), diag::note_previous_definition); + return Owned(SubStmt); + } + + // Otherwise, things are good. Fill in the declaration and return it. + LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); + TheDecl->setStmt(LS); + if (!TheDecl->isGnuLocal()) + TheDecl->setLocation(IdentLoc); + return Owned(LS); +} + +StmtResult +Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, + Stmt *thenStmt, SourceLocation ElseLoc, + Stmt *elseStmt) { + ExprResult CondResult(CondVal.release()); + + VarDecl *ConditionVar = 0; + if (CondVar) { + ConditionVar = cast<VarDecl>(CondVar); + CondResult = CheckConditionVariable(ConditionVar, IfLoc, true); + if (CondResult.isInvalid()) + return StmtError(); + } + Expr *ConditionExpr = CondResult.takeAs<Expr>(); + if (!ConditionExpr) + return StmtError(); + + DiagnoseUnusedExprResult(thenStmt); + + // Warn if the if block has a null body without an else value. + // this helps prevent bugs due to typos, such as + // if (condition); + // do_stuff(); + // + if (!elseStmt) { + if (NullStmt* stmt = dyn_cast<NullStmt>(thenStmt)) + // But do not warn if the body is a macro that expands to nothing, e.g: + // + // #define CALL(x) + // if (condition) + // CALL(0); + // + if (!stmt->hasLeadingEmptyMacro()) + Diag(stmt->getSemiLoc(), diag::warn_empty_if_body); + } + + DiagnoseUnusedExprResult(elseStmt); + + return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, + thenStmt, ElseLoc, elseStmt)); +} + +/// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have +/// the specified width and sign. If an overflow occurs, detect it and emit +/// the specified diagnostic. +void Sema::ConvertIntegerToTypeWarnOnOverflow(llvm::APSInt &Val, + unsigned NewWidth, bool NewSign, + SourceLocation Loc, + unsigned DiagID) { + // Perform a conversion to the promoted condition type if needed. + if (NewWidth > Val.getBitWidth()) { + // If this is an extension, just do it. + Val = Val.extend(NewWidth); + Val.setIsSigned(NewSign); + + // If the input was signed and negative and the output is + // unsigned, don't bother to warn: this is implementation-defined + // behavior. + // FIXME: Introduce a second, default-ignored warning for this case? + } else if (NewWidth < Val.getBitWidth()) { + // If this is a truncation, check for overflow. + llvm::APSInt ConvVal(Val); + ConvVal = ConvVal.trunc(NewWidth); + ConvVal.setIsSigned(NewSign); + ConvVal = ConvVal.extend(Val.getBitWidth()); + ConvVal.setIsSigned(Val.isSigned()); + if (ConvVal != Val) + Diag(Loc, DiagID) << Val.toString(10) << ConvVal.toString(10); + + // Regardless of whether a diagnostic was emitted, really do the + // truncation. + Val = Val.trunc(NewWidth); + Val.setIsSigned(NewSign); + } else if (NewSign != Val.isSigned()) { + // Convert the sign to match the sign of the condition. This can cause + // overflow as well: unsigned(INTMIN) + // We don't diagnose this overflow, because it is implementation-defined + // behavior. + // FIXME: Introduce a second, default-ignored warning for this case? + llvm::APSInt OldVal(Val); + Val.setIsSigned(NewSign); + } +} + +namespace { + struct CaseCompareFunctor { + bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS, + const llvm::APSInt &RHS) { + return LHS.first < RHS; + } + bool operator()(const std::pair<llvm::APSInt, CaseStmt*> &LHS, + const std::pair<llvm::APSInt, CaseStmt*> &RHS) { + return LHS.first < RHS.first; + } + bool operator()(const llvm::APSInt &LHS, + const std::pair<llvm::APSInt, CaseStmt*> &RHS) { + return LHS < RHS.first; + } + }; +} + +/// CmpCaseVals - Comparison predicate for sorting case values. +/// +static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs, + const std::pair<llvm::APSInt, CaseStmt*>& rhs) { + if (lhs.first < rhs.first) + return true; + + if (lhs.first == rhs.first && + lhs.second->getCaseLoc().getRawEncoding() + < rhs.second->getCaseLoc().getRawEncoding()) + return true; + return false; +} + +/// CmpEnumVals - Comparison predicate for sorting enumeration values. +/// +static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, + const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs) +{ + return lhs.first < rhs.first; +} + +/// EqEnumVals - Comparison preficate for uniqing enumeration values. +/// +static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, + const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs) +{ + return lhs.first == rhs.first; +} + +/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of +/// potentially integral-promoted expression @p expr. +static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { + if (const CastExpr *ImplicitCast = dyn_cast<ImplicitCastExpr>(expr)) { + const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr(); + QualType TypeBeforePromotion = ExprBeforePromotion->getType(); + if (TypeBeforePromotion->isIntegralOrEnumerationType()) { + return TypeBeforePromotion; + } + } + return expr->getType(); +} + +StmtResult +Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, + Decl *CondVar) { + ExprResult CondResult; + + VarDecl *ConditionVar = 0; + if (CondVar) { + ConditionVar = cast<VarDecl>(CondVar); + CondResult = CheckConditionVariable(ConditionVar, SourceLocation(), false); + if (CondResult.isInvalid()) + return StmtError(); + + Cond = CondResult.release(); + } + + if (!Cond) + return StmtError(); + + CondResult + = ConvertToIntegralOrEnumerationType(SwitchLoc, Cond, + PDiag(diag::err_typecheck_statement_requires_integer), + PDiag(diag::err_switch_incomplete_class_type) + << Cond->getSourceRange(), + PDiag(diag::err_switch_explicit_conversion), + PDiag(diag::note_switch_conversion), + PDiag(diag::err_switch_multiple_conversions), + PDiag(diag::note_switch_conversion), + PDiag(0)); + if (CondResult.isInvalid()) return StmtError(); + Cond = CondResult.take(); + + if (!CondVar) { + CheckImplicitConversions(Cond, SwitchLoc); + CondResult = MaybeCreateExprWithCleanups(Cond); + if (CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.take(); + } + + getCurFunction()->setHasBranchIntoScope(); + + SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, Cond); + getCurFunction()->SwitchStack.push_back(SS); + return Owned(SS); +} + +static void AdjustAPSInt(llvm::APSInt &Val, unsigned BitWidth, bool IsSigned) { + if (Val.getBitWidth() < BitWidth) + Val = Val.extend(BitWidth); + else if (Val.getBitWidth() > BitWidth) + Val = Val.trunc(BitWidth); + Val.setIsSigned(IsSigned); +} + +StmtResult +Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, + Stmt *BodyStmt) { + SwitchStmt *SS = cast<SwitchStmt>(Switch); + assert(SS == getCurFunction()->SwitchStack.back() && + "switch stack missing push/pop!"); + + SS->setBody(BodyStmt, SwitchLoc); + getCurFunction()->SwitchStack.pop_back(); + + if (SS->getCond() == 0) + return StmtError(); + + Expr *CondExpr = SS->getCond(); + Expr *CondExprBeforePromotion = CondExpr; + QualType CondTypeBeforePromotion = + GetTypeBeforeIntegralPromotion(CondExpr); + + // C99 6.8.4.2p5 - Integer promotions are performed on the controlling expr. + ExprResult CondResult = UsualUnaryConversions(CondExpr); + if (CondResult.isInvalid()) + return StmtError(); + CondExpr = CondResult.take(); + QualType CondType = CondExpr->getType(); + SS->setCond(CondExpr); + + // C++ 6.4.2.p2: + // Integral promotions are performed (on the switch condition). + // + // A case value unrepresentable by the original switch condition + // type (before the promotion) doesn't make sense, even when it can + // be represented by the promoted type. Therefore we need to find + // the pre-promotion type of the switch condition. + if (!CondExpr->isTypeDependent()) { + // We have already converted the expression to an integral or enumeration + // type, when we started the switch statement. If we don't have an + // appropriate type now, just return an error. + if (!CondType->isIntegralOrEnumerationType()) + return StmtError(); + + if (CondExpr->isKnownToHaveBooleanValue()) { + // switch(bool_expr) {...} is often a programmer error, e.g. + // switch(n && mask) { ... } // Doh - should be "n & mask". + // One can always use an if statement instead of switch(bool_expr). + Diag(SwitchLoc, diag::warn_bool_switch_condition) + << CondExpr->getSourceRange(); + } + } + + // Get the bitwidth of the switched-on value before promotions. We must + // convert the integer case values to this width before comparison. + bool HasDependentValue + = CondExpr->isTypeDependent() || CondExpr->isValueDependent(); + unsigned CondWidth + = HasDependentValue ? 0 : Context.getIntWidth(CondTypeBeforePromotion); + bool CondIsSigned + = CondTypeBeforePromotion->isSignedIntegerOrEnumerationType(); + + // Accumulate all of the case values in a vector so that we can sort them + // and detect duplicates. This vector contains the APInt for the case after + // it has been converted to the condition type. + typedef llvm::SmallVector<std::pair<llvm::APSInt, CaseStmt*>, 64> CaseValsTy; + CaseValsTy CaseVals; + + // Keep track of any GNU case ranges we see. The APSInt is the low value. + typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy; + CaseRangesTy CaseRanges; + + DefaultStmt *TheDefaultStmt = 0; + + bool CaseListIsErroneous = false; + + for (SwitchCase *SC = SS->getSwitchCaseList(); SC && !HasDependentValue; + SC = SC->getNextSwitchCase()) { + + if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) { + if (TheDefaultStmt) { + Diag(DS->getDefaultLoc(), diag::err_multiple_default_labels_defined); + Diag(TheDefaultStmt->getDefaultLoc(), diag::note_duplicate_case_prev); + + // FIXME: Remove the default statement from the switch block so that + // we'll return a valid AST. This requires recursing down the AST and + // finding it, not something we are set up to do right now. For now, + // just lop the entire switch stmt out of the AST. + CaseListIsErroneous = true; + } + TheDefaultStmt = DS; + + } else { + CaseStmt *CS = cast<CaseStmt>(SC); + + // We already verified that the expression has a i-c-e value (C99 + // 6.8.4.2p3) - get that value now. + Expr *Lo = CS->getLHS(); + + if (Lo->isTypeDependent() || Lo->isValueDependent()) { + HasDependentValue = true; + break; + } + + llvm::APSInt LoVal = Lo->EvaluateAsInt(Context); + + // Convert the value to the same width/sign as the condition. + ConvertIntegerToTypeWarnOnOverflow(LoVal, CondWidth, CondIsSigned, + Lo->getLocStart(), + diag::warn_case_value_overflow); + + // If the LHS is not the same type as the condition, insert an implicit + // cast. + Lo = ImpCastExprToType(Lo, CondType, CK_IntegralCast).take(); + CS->setLHS(Lo); + + // If this is a case range, remember it in CaseRanges, otherwise CaseVals. + if (CS->getRHS()) { + if (CS->getRHS()->isTypeDependent() || + CS->getRHS()->isValueDependent()) { + HasDependentValue = true; + break; + } + CaseRanges.push_back(std::make_pair(LoVal, CS)); + } else + CaseVals.push_back(std::make_pair(LoVal, CS)); + } + } + + if (!HasDependentValue) { + // If we don't have a default statement, check whether the + // condition is constant. + llvm::APSInt ConstantCondValue; + bool HasConstantCond = false; + bool ShouldCheckConstantCond = false; + if (!HasDependentValue && !TheDefaultStmt) { + Expr::EvalResult Result; + HasConstantCond = CondExprBeforePromotion->Evaluate(Result, Context); + if (HasConstantCond) { + assert(Result.Val.isInt() && "switch condition evaluated to non-int"); + ConstantCondValue = Result.Val.getInt(); + ShouldCheckConstantCond = true; + + assert(ConstantCondValue.getBitWidth() == CondWidth && + ConstantCondValue.isSigned() == CondIsSigned); + } + } + + // Sort all the scalar case values so we can easily detect duplicates. + std::stable_sort(CaseVals.begin(), CaseVals.end(), CmpCaseVals); + + if (!CaseVals.empty()) { + for (unsigned i = 0, e = CaseVals.size(); i != e; ++i) { + if (ShouldCheckConstantCond && + CaseVals[i].first == ConstantCondValue) + ShouldCheckConstantCond = false; + + if (i != 0 && CaseVals[i].first == CaseVals[i-1].first) { + // If we have a duplicate, report it. + Diag(CaseVals[i].second->getLHS()->getLocStart(), + diag::err_duplicate_case) << CaseVals[i].first.toString(10); + Diag(CaseVals[i-1].second->getLHS()->getLocStart(), + diag::note_duplicate_case_prev); + // FIXME: We really want to remove the bogus case stmt from the + // substmt, but we have no way to do this right now. + CaseListIsErroneous = true; + } + } + } + + // Detect duplicate case ranges, which usually don't exist at all in + // the first place. + if (!CaseRanges.empty()) { + // Sort all the case ranges by their low value so we can easily detect + // overlaps between ranges. + std::stable_sort(CaseRanges.begin(), CaseRanges.end()); + + // Scan the ranges, computing the high values and removing empty ranges. + std::vector<llvm::APSInt> HiVals; + for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) { + llvm::APSInt &LoVal = CaseRanges[i].first; + CaseStmt *CR = CaseRanges[i].second; + Expr *Hi = CR->getRHS(); + llvm::APSInt HiVal = Hi->EvaluateAsInt(Context); + + // Convert the value to the same width/sign as the condition. + ConvertIntegerToTypeWarnOnOverflow(HiVal, CondWidth, CondIsSigned, + Hi->getLocStart(), + diag::warn_case_value_overflow); + + // If the LHS is not the same type as the condition, insert an implicit + // cast. + Hi = ImpCastExprToType(Hi, CondType, CK_IntegralCast).take(); + CR->setRHS(Hi); + + // If the low value is bigger than the high value, the case is empty. + if (LoVal > HiVal) { + Diag(CR->getLHS()->getLocStart(), diag::warn_case_empty_range) + << SourceRange(CR->getLHS()->getLocStart(), + Hi->getLocEnd()); + CaseRanges.erase(CaseRanges.begin()+i); + --i, --e; + continue; + } + + if (ShouldCheckConstantCond && + LoVal <= ConstantCondValue && + ConstantCondValue <= HiVal) + ShouldCheckConstantCond = false; + + HiVals.push_back(HiVal); + } + + // Rescan the ranges, looking for overlap with singleton values and other + // ranges. Since the range list is sorted, we only need to compare case + // ranges with their neighbors. + for (unsigned i = 0, e = CaseRanges.size(); i != e; ++i) { + llvm::APSInt &CRLo = CaseRanges[i].first; + llvm::APSInt &CRHi = HiVals[i]; + CaseStmt *CR = CaseRanges[i].second; + + // Check to see whether the case range overlaps with any + // singleton cases. + CaseStmt *OverlapStmt = 0; + llvm::APSInt OverlapVal(32); + + // Find the smallest value >= the lower bound. If I is in the + // case range, then we have overlap. + CaseValsTy::iterator I = std::lower_bound(CaseVals.begin(), + CaseVals.end(), CRLo, + CaseCompareFunctor()); + if (I != CaseVals.end() && I->first < CRHi) { + OverlapVal = I->first; // Found overlap with scalar. + OverlapStmt = I->second; + } + + // Find the smallest value bigger than the upper bound. + I = std::upper_bound(I, CaseVals.end(), CRHi, CaseCompareFunctor()); + if (I != CaseVals.begin() && (I-1)->first >= CRLo) { + OverlapVal = (I-1)->first; // Found overlap with scalar. + OverlapStmt = (I-1)->second; + } + + // Check to see if this case stmt overlaps with the subsequent + // case range. + if (i && CRLo <= HiVals[i-1]) { + OverlapVal = HiVals[i-1]; // Found overlap with range. + OverlapStmt = CaseRanges[i-1].second; + } + + if (OverlapStmt) { + // If we have a duplicate, report it. + Diag(CR->getLHS()->getLocStart(), diag::err_duplicate_case) + << OverlapVal.toString(10); + Diag(OverlapStmt->getLHS()->getLocStart(), + diag::note_duplicate_case_prev); + // FIXME: We really want to remove the bogus case stmt from the + // substmt, but we have no way to do this right now. + CaseListIsErroneous = true; + } + } + } + + // Complain if we have a constant condition and we didn't find a match. + if (!CaseListIsErroneous && ShouldCheckConstantCond) { + // TODO: it would be nice if we printed enums as enums, chars as + // chars, etc. + Diag(CondExpr->getExprLoc(), diag::warn_missing_case_for_condition) + << ConstantCondValue.toString(10) + << CondExpr->getSourceRange(); + } + + // Check to see if switch is over an Enum and handles all of its + // values. We only issue a warning if there is not 'default:', but + // we still do the analysis to preserve this information in the AST + // (which can be used by flow-based analyes). + // + const EnumType *ET = CondTypeBeforePromotion->getAs<EnumType>(); + + // If switch has default case, then ignore it. + if (!CaseListIsErroneous && !HasConstantCond && ET) { + const EnumDecl *ED = ET->getDecl(); + typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> + EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, + // allowing easier comparison with CaseVals. + for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); + EDI != ED->enumerator_end(); ++EDI) { + llvm::APSInt Val = EDI->getInitVal(); + AdjustAPSInt(Val, CondWidth, CondIsSigned); + EnumVals.push_back(std::make_pair(Val, *EDI)); + } + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = + std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + + // See which case values aren't in enum. + // TODO: we might want to check whether case values are out of the + // enum even if we don't want to check whether all cases are handled. + if (!TheDefaultStmt) { + EnumValsTy::const_iterator EI = EnumVals.begin(); + for (CaseValsTy::const_iterator CI = CaseVals.begin(); + CI != CaseVals.end(); CI++) { + while (EI != EIend && EI->first < CI->first) + EI++; + if (EI == EIend || EI->first > CI->first) + Diag(CI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) + << ED->getDeclName(); + } + // See which of case ranges aren't in enum + EI = EnumVals.begin(); + for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); + RI != CaseRanges.end() && EI != EIend; RI++) { + while (EI != EIend && EI->first < RI->first) + EI++; + + if (EI == EIend || EI->first != RI->first) { + Diag(RI->second->getLHS()->getExprLoc(), diag::warn_not_in_enum) + << ED->getDeclName(); + } + + llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + AdjustAPSInt(Hi, CondWidth, CondIsSigned); + while (EI != EIend && EI->first < Hi) + EI++; + if (EI == EIend || EI->first != Hi) + Diag(RI->second->getRHS()->getExprLoc(), diag::warn_not_in_enum) + << ED->getDeclName(); + } + } + + // Check which enum vals aren't in switch + CaseValsTy::const_iterator CI = CaseVals.begin(); + CaseRangesTy::const_iterator RI = CaseRanges.begin(); + bool hasCasesNotInSwitch = false; + + llvm::SmallVector<DeclarationName,8> UnhandledNames; + + for (EnumValsTy::const_iterator EI = EnumVals.begin(); EI != EIend; EI++){ + // Drop unneeded case values + llvm::APSInt CIVal; + while (CI != CaseVals.end() && CI->first < EI->first) + CI++; + + if (CI != CaseVals.end() && CI->first == EI->first) + continue; + + // Drop unneeded case ranges + for (; RI != CaseRanges.end(); RI++) { + llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + AdjustAPSInt(Hi, CondWidth, CondIsSigned); + if (EI->first <= Hi) + break; + } + + if (RI == CaseRanges.end() || EI->first < RI->first) { + hasCasesNotInSwitch = true; + if (!TheDefaultStmt) + UnhandledNames.push_back(EI->second->getDeclName()); + } + } + + // Produce a nice diagnostic if multiple values aren't handled. + switch (UnhandledNames.size()) { + case 0: break; + case 1: + Diag(CondExpr->getExprLoc(), diag::warn_missing_case1) + << UnhandledNames[0]; + break; + case 2: + Diag(CondExpr->getExprLoc(), diag::warn_missing_case2) + << UnhandledNames[0] << UnhandledNames[1]; + break; + case 3: + Diag(CondExpr->getExprLoc(), diag::warn_missing_case3) + << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; + break; + default: + Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) + << (unsigned)UnhandledNames.size() + << UnhandledNames[0] << UnhandledNames[1] << UnhandledNames[2]; + break; + } + + if (!hasCasesNotInSwitch) + SS->setAllEnumCasesCovered(); + } + } + + // FIXME: If the case list was broken is some way, we don't have a good system + // to patch it up. Instead, just return the whole substmt as broken. + if (CaseListIsErroneous) + return StmtError(); + + return Owned(SS); +} + +StmtResult +Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, + Decl *CondVar, Stmt *Body) { + ExprResult CondResult(Cond.release()); + + VarDecl *ConditionVar = 0; + if (CondVar) { + ConditionVar = cast<VarDecl>(CondVar); + CondResult = CheckConditionVariable(ConditionVar, WhileLoc, true); + if (CondResult.isInvalid()) + return StmtError(); + } + Expr *ConditionExpr = CondResult.take(); + if (!ConditionExpr) + return StmtError(); + + DiagnoseUnusedExprResult(Body); + + return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr, + Body, WhileLoc)); +} + +StmtResult +Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, + SourceLocation WhileLoc, SourceLocation CondLParen, + Expr *Cond, SourceLocation CondRParen) { + assert(Cond && "ActOnDoStmt(): missing expression"); + + ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc); + if (CondResult.isInvalid() || CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.take(); + + CheckImplicitConversions(Cond, DoLoc); + CondResult = MaybeCreateExprWithCleanups(Cond); + if (CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.take(); + + DiagnoseUnusedExprResult(Body); + + return Owned(new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen)); +} + +StmtResult +Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *First, FullExprArg second, Decl *secondVar, + FullExprArg third, + SourceLocation RParenLoc, Stmt *Body) { + if (!getLangOptions().CPlusPlus) { + if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) { + // C99 6.8.5p3: The declaration part of a 'for' statement shall only + // declare identifiers for objects having storage class 'auto' or + // 'register'. + for (DeclStmt::decl_iterator DI=DS->decl_begin(), DE=DS->decl_end(); + DI!=DE; ++DI) { + VarDecl *VD = dyn_cast<VarDecl>(*DI); + if (VD && VD->isLocalVarDecl() && !VD->hasLocalStorage()) + VD = 0; + if (VD == 0) + Diag((*DI)->getLocation(), diag::err_non_variable_decl_in_for); + // FIXME: mark decl erroneous! + } + } + } + + ExprResult SecondResult(second.release()); + VarDecl *ConditionVar = 0; + if (secondVar) { + ConditionVar = cast<VarDecl>(secondVar); + SecondResult = CheckConditionVariable(ConditionVar, ForLoc, true); + if (SecondResult.isInvalid()) + return StmtError(); + } + + Expr *Third = third.release().takeAs<Expr>(); + + DiagnoseUnusedExprResult(First); + DiagnoseUnusedExprResult(Third); + DiagnoseUnusedExprResult(Body); + + return Owned(new (Context) ForStmt(Context, First, + SecondResult.take(), ConditionVar, + Third, Body, ForLoc, LParenLoc, + RParenLoc)); +} + +/// In an Objective C collection iteration statement: +/// for (x in y) +/// x can be an arbitrary l-value expression. Bind it up as a +/// full-expression. +StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { + CheckImplicitConversions(E); + ExprResult Result = MaybeCreateExprWithCleanups(E); + if (Result.isInvalid()) return StmtError(); + return Owned(static_cast<Stmt*>(Result.get())); +} + +StmtResult +Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, + Stmt *First, Expr *Second, + SourceLocation RParenLoc, Stmt *Body) { + if (First) { + QualType FirstType; + if (DeclStmt *DS = dyn_cast<DeclStmt>(First)) { + if (!DS->isSingleDecl()) + return StmtError(Diag((*DS->decl_begin())->getLocation(), + diag::err_toomany_element_decls)); + + Decl *D = DS->getSingleDecl(); + FirstType = cast<ValueDecl>(D)->getType(); + // C99 6.8.5p3: The declaration part of a 'for' statement shall only + // declare identifiers for objects having storage class 'auto' or + // 'register'. + VarDecl *VD = cast<VarDecl>(D); + if (VD->isLocalVarDecl() && !VD->hasLocalStorage()) + return StmtError(Diag(VD->getLocation(), + diag::err_non_variable_decl_in_for)); + } else { + Expr *FirstE = cast<Expr>(First); + if (!FirstE->isTypeDependent() && !FirstE->isLValue()) + return StmtError(Diag(First->getLocStart(), + diag::err_selector_element_not_lvalue) + << First->getSourceRange()); + + FirstType = static_cast<Expr*>(First)->getType(); + } + if (!FirstType->isDependentType() && + !FirstType->isObjCObjectPointerType() && + !FirstType->isBlockPointerType()) + Diag(ForLoc, diag::err_selector_element_type) + << FirstType << First->getSourceRange(); + } + if (Second && !Second->isTypeDependent()) { + ExprResult Result = DefaultFunctionArrayLvalueConversion(Second); + if (Result.isInvalid()) + return StmtError(); + Second = Result.take(); + QualType SecondType = Second->getType(); + if (!SecondType->isObjCObjectPointerType()) + Diag(ForLoc, diag::err_collection_expr_type) + << SecondType << Second->getSourceRange(); + else if (const ObjCObjectPointerType *OPT = + SecondType->getAsObjCInterfacePointerType()) { + llvm::SmallVector<IdentifierInfo *, 4> KeyIdents; + IdentifierInfo* selIdent = + &Context.Idents.get("countByEnumeratingWithState"); + KeyIdents.push_back(selIdent); + selIdent = &Context.Idents.get("objects"); + KeyIdents.push_back(selIdent); + selIdent = &Context.Idents.get("count"); + KeyIdents.push_back(selIdent); + Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]); + if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) { + if (!IDecl->isForwardDecl() && + !IDecl->lookupInstanceMethod(CSelector) && + !LookupMethodInQualifiedType(CSelector, OPT, true)) { + // Must further look into private implementation methods. + if (!LookupPrivateInstanceMethod(CSelector, IDecl)) + Diag(ForLoc, diag::warn_collection_expr_type) + << SecondType << CSelector << Second->getSourceRange(); + } + } + } + } + return Owned(new (Context) ObjCForCollectionStmt(First, Second, Body, + ForLoc, RParenLoc)); +} + +namespace { + +enum BeginEndFunction { + BEF_begin, + BEF_end +}; + +/// Build a variable declaration for a for-range statement. +static VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, + QualType Type, const char *Name) { + DeclContext *DC = SemaRef.CurContext; + IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); + TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); + VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, + TInfo, SC_Auto, SC_None); + Decl->setImplicit(); + return Decl; +} + +/// Finish building a variable declaration for a for-range statement. +/// \return true if an error occurs. +static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, + SourceLocation Loc, int diag) { + // Deduce the type for the iterator variable now rather than leaving it to + // AddInitializerToDecl, so we can produce a more suitable diagnostic. + TypeSourceInfo *InitTSI = 0; + if (Init->getType()->isVoidType() || + !SemaRef.DeduceAutoType(Decl->getTypeSourceInfo(), Init, InitTSI)) + SemaRef.Diag(Loc, diag) << Init->getType(); + if (!InitTSI) { + Decl->setInvalidDecl(); + return true; + } + Decl->setTypeSourceInfo(InitTSI); + Decl->setType(InitTSI->getType()); + + SemaRef.AddInitializerToDecl(Decl, Init, /*DirectInit=*/false, + /*TypeMayContainAuto=*/false); + SemaRef.FinalizeDeclaration(Decl); + SemaRef.CurContext->addHiddenDecl(Decl); + return false; +} + +/// Produce a note indicating which begin/end function was implicitly called +/// by a C++0x for-range statement. This is often not obvious from the code, +/// nor from the diagnostics produced when analysing the implicit expressions +/// required in a for-range statement. +void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, + BeginEndFunction BEF) { + CallExpr *CE = dyn_cast<CallExpr>(E); + if (!CE) + return; + FunctionDecl *D = dyn_cast<FunctionDecl>(CE->getCalleeDecl()); + if (!D) + return; + SourceLocation Loc = D->getLocation(); + + std::string Description; + bool IsTemplate = false; + if (FunctionTemplateDecl *FunTmpl = D->getPrimaryTemplate()) { + Description = SemaRef.getTemplateArgumentBindingsText( + FunTmpl->getTemplateParameters(), *D->getTemplateSpecializationArgs()); + IsTemplate = true; + } + + SemaRef.Diag(Loc, diag::note_for_range_begin_end) + << BEF << IsTemplate << Description << E->getType(); +} + +/// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the +/// given LookupResult is non-empty, it is assumed to describe a member which +/// will be invoked. Otherwise, the function will be found via argument +/// dependent lookup. +static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, + SourceLocation Loc, + VarDecl *Decl, + BeginEndFunction BEF, + const DeclarationNameInfo &NameInfo, + LookupResult &MemberLookup, + Expr *Range) { + ExprResult CallExpr; + if (!MemberLookup.empty()) { + ExprResult MemberRef = + SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc, + /*IsPtr=*/false, CXXScopeSpec(), + /*Qualifier=*/0, MemberLookup, + /*TemplateArgs=*/0); + if (MemberRef.isInvalid()) + return ExprError(); + CallExpr = SemaRef.ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(), + Loc, 0); + if (CallExpr.isInvalid()) + return ExprError(); + } else { + UnresolvedSet<0> FoundNames; + // C++0x [stmt.ranged]p1: For the purposes of this name lookup, namespace + // std is an associated namespace. + UnresolvedLookupExpr *Fn = + UnresolvedLookupExpr::Create(SemaRef.Context, /*NamingClass=*/0, + NestedNameSpecifierLoc(), NameInfo, + /*NeedsADL=*/true, /*Overloaded=*/false, + FoundNames.begin(), FoundNames.end(), + /*LookInStdNamespace=*/true); + CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, + 0); + if (CallExpr.isInvalid()) { + SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type) + << Range->getType(); + return ExprError(); + } + } + if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, CallExpr.get(), BEF); + return ExprError(); + } + return CallExpr; +} + +} + +/// ActOnCXXForRangeStmt - Check and build a C++0x for-range statement. +/// +/// C++0x [stmt.ranged]: +/// A range-based for statement is equivalent to +/// +/// { +/// auto && __range = range-init; +/// for ( auto __begin = begin-expr, +/// __end = end-expr; +/// __begin != __end; +/// ++__begin ) { +/// for-range-declaration = *__begin; +/// statement +/// } +/// } +/// +/// The body of the loop is not available yet, since it cannot be analysed until +/// we have determined the type of the for-range-declaration. +StmtResult +Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *First, SourceLocation ColonLoc, Expr *Range, + SourceLocation RParenLoc) { + if (!First || !Range) + return StmtError(); + + DeclStmt *DS = dyn_cast<DeclStmt>(First); + assert(DS && "first part of for range not a decl stmt"); + + if (!DS->isSingleDecl()) { + Diag(DS->getStartLoc(), diag::err_type_defined_in_for_range); + return StmtError(); + } + if (DS->getSingleDecl()->isInvalidDecl()) + return StmtError(); + + if (DiagnoseUnexpandedParameterPack(Range, UPPC_Expression)) + return StmtError(); + + // Build auto && __range = range-init + SourceLocation RangeLoc = Range->getLocStart(); + VarDecl *RangeVar = BuildForRangeVarDecl(*this, RangeLoc, + Context.getAutoRRefDeductType(), + "__range"); + if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc, + diag::err_for_range_deduction_failure)) + return StmtError(); + + // Claim the type doesn't contain auto: we've already done the checking. + DeclGroupPtrTy RangeGroup = + BuildDeclaratorGroup((Decl**)&RangeVar, 1, /*TypeMayContainAuto=*/false); + StmtResult RangeDecl = ActOnDeclStmt(RangeGroup, RangeLoc, RangeLoc); + if (RangeDecl.isInvalid()) + return StmtError(); + + return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(), + /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS, + RParenLoc); +} + +/// BuildCXXForRangeStmt - Build or instantiate a C++0x for-range statement. +StmtResult +Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, + Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond, + Expr *Inc, Stmt *LoopVarDecl, + SourceLocation RParenLoc) { + Scope *S = getCurScope(); + + DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl); + VarDecl *RangeVar = cast<VarDecl>(RangeDS->getSingleDecl()); + QualType RangeVarType = RangeVar->getType(); + + DeclStmt *LoopVarDS = cast<DeclStmt>(LoopVarDecl); + VarDecl *LoopVar = cast<VarDecl>(LoopVarDS->getSingleDecl()); + + StmtResult BeginEndDecl = BeginEnd; + ExprResult NotEqExpr = Cond, IncrExpr = Inc; + + if (!BeginEndDecl.get() && !RangeVarType->isDependentType()) { + SourceLocation RangeLoc = RangeVar->getLocation(); + + ExprResult RangeRef = BuildDeclRefExpr(RangeVar, + RangeVarType.getNonReferenceType(), + VK_LValue, ColonLoc); + if (RangeRef.isInvalid()) + return StmtError(); + + QualType AutoType = Context.getAutoDeductType(); + Expr *Range = RangeVar->getInit(); + if (!Range) + return StmtError(); + QualType RangeType = Range->getType(); + + if (RequireCompleteType(RangeLoc, RangeType, + PDiag(diag::err_for_range_incomplete_type))) + return StmtError(); + + // Build auto __begin = begin-expr, __end = end-expr. + VarDecl *BeginVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, + "__begin"); + VarDecl *EndVar = BuildForRangeVarDecl(*this, ColonLoc, AutoType, + "__end"); + + // Build begin-expr and end-expr and attach to __begin and __end variables. + ExprResult BeginExpr, EndExpr; + if (const ArrayType *UnqAT = RangeType->getAsArrayTypeUnsafe()) { + // - if _RangeT is an array type, begin-expr and end-expr are __range and + // __range + __bound, respectively, where __bound is the array bound. If + // _RangeT is an array of unknown size or an array of incomplete type, + // the program is ill-formed; + + // begin-expr is __range. + BeginExpr = RangeRef; + if (FinishForRangeVarDecl(*this, BeginVar, RangeRef.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Find the array bound. + ExprResult BoundExpr; + if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(UnqAT)) + BoundExpr = Owned(IntegerLiteral::Create(Context, CAT->getSize(), + Context.getPointerDiffType(), + RangeLoc)); + else if (const VariableArrayType *VAT = + dyn_cast<VariableArrayType>(UnqAT)) + BoundExpr = VAT->getSizeExpr(); + else { + // Can't be a DependentSizedArrayType or an IncompleteArrayType since + // UnqAT is not incomplete and Range is not type-dependent. + assert(0 && "Unexpected array type in for-range"); + return StmtError(); + } + + // end-expr is __range + __bound. + EndExpr = ActOnBinOp(S, ColonLoc, tok::plus, RangeRef.get(), + BoundExpr.get()); + if (EndExpr.isInvalid()) + return StmtError(); + if (FinishForRangeVarDecl(*this, EndVar, EndExpr.get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + return StmtError(); + } + } else { + DeclarationNameInfo BeginNameInfo(&PP.getIdentifierTable().get("begin"), + ColonLoc); + DeclarationNameInfo EndNameInfo(&PP.getIdentifierTable().get("end"), + ColonLoc); + + LookupResult BeginMemberLookup(*this, BeginNameInfo, LookupMemberName); + LookupResult EndMemberLookup(*this, EndNameInfo, LookupMemberName); + + if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { + // - if _RangeT is a class type, the unqualified-ids begin and end are + // looked up in the scope of class _RangeT as if by class member access + // lookup (3.4.5), and if either (or both) finds at least one + // declaration, begin-expr and end-expr are __range.begin() and + // __range.end(), respectively; + LookupQualifiedName(BeginMemberLookup, D); + LookupQualifiedName(EndMemberLookup, D); + + if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { + Diag(ColonLoc, diag::err_for_range_member_begin_end_mismatch) + << RangeType << BeginMemberLookup.empty(); + return StmtError(); + } + } else { + // - otherwise, begin-expr and end-expr are begin(__range) and + // end(__range), respectively, where begin and end are looked up with + // argument-dependent lookup (3.4.2). For the purposes of this name + // lookup, namespace std is an associated namespace. + } + + BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar, + BEF_begin, BeginNameInfo, + BeginMemberLookup, RangeRef.get()); + if (BeginExpr.isInvalid()) + return StmtError(); + + EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar, + BEF_end, EndNameInfo, + EndMemberLookup, RangeRef.get()); + if (EndExpr.isInvalid()) + return StmtError(); + } + + // C++0x [decl.spec.auto]p6: BeginType and EndType must be the same. + QualType BeginType = BeginVar->getType(), EndType = EndVar->getType(); + if (!Context.hasSameType(BeginType, EndType)) { + Diag(RangeLoc, diag::err_for_range_begin_end_types_differ) + << BeginType << EndType; + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + } + + Decl *BeginEndDecls[] = { BeginVar, EndVar }; + // Claim the type doesn't contain auto: we've already done the checking. + DeclGroupPtrTy BeginEndGroup = + BuildDeclaratorGroup(BeginEndDecls, 2, /*TypeMayContainAuto=*/false); + BeginEndDecl = ActOnDeclStmt(BeginEndGroup, ColonLoc, ColonLoc); + + ExprResult BeginRef = BuildDeclRefExpr(BeginVar, + BeginType.getNonReferenceType(), + VK_LValue, ColonLoc); + ExprResult EndRef = BuildDeclRefExpr(EndVar, EndType.getNonReferenceType(), + VK_LValue, ColonLoc); + + // Build and check __begin != __end expression. + NotEqExpr = ActOnBinOp(S, ColonLoc, tok::exclaimequal, + BeginRef.get(), EndRef.get()); + NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get()); + NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); + if (NotEqExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + if (!Context.hasSameType(BeginType, EndType)) + NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); + return StmtError(); + } + + // Build and check ++__begin expression. + IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); + IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); + if (IncrExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Build and check *__begin expression. + ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get()); + if (DerefExpr.isInvalid()) { + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + return StmtError(); + } + + // Attach *__begin as initializer for VD. + if (!LoopVar->isInvalidDecl()) { + AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false, + /*TypeMayContainAuto=*/true); + if (LoopVar->isInvalidDecl()) + NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); + } + } + + return Owned(new (Context) CXXForRangeStmt(RangeDS, + cast_or_null<DeclStmt>(BeginEndDecl.get()), + NotEqExpr.take(), IncrExpr.take(), + LoopVarDS, /*Body=*/0, ForLoc, + ColonLoc, RParenLoc)); +} + +/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. +/// This is a separate step from ActOnCXXForRangeStmt because analysis of the +/// body cannot be performed until after the type of the range variable is +/// determined. +StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { + if (!S || !B) + return StmtError(); + + cast<CXXForRangeStmt>(S)->setBody(B); + return S; +} + +StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + LabelDecl *TheDecl) { + getCurFunction()->setHasBranchIntoScope(); + TheDecl->setUsed(); + return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc)); +} + +StmtResult +Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, + Expr *E) { + // Convert operand to void* + if (!E->isTypeDependent()) { + QualType ETy = E->getType(); + QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); + ExprResult ExprRes = Owned(E); + AssignConvertType ConvTy = + CheckSingleAssignmentConstraints(DestTy, ExprRes); + if (ExprRes.isInvalid()) + return StmtError(); + E = ExprRes.take(); + if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) + return StmtError(); + } + + getCurFunction()->setHasIndirectGoto(); + + return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E)); +} + +StmtResult +Sema::ActOnContinueStmt(SourceLocation ContinueLoc, Scope *CurScope) { + Scope *S = CurScope->getContinueParent(); + if (!S) { + // C99 6.8.6.2p1: A break shall appear only in or as a loop body. + return StmtError(Diag(ContinueLoc, diag::err_continue_not_in_loop)); + } + + return Owned(new (Context) ContinueStmt(ContinueLoc)); +} + +StmtResult +Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { + Scope *S = CurScope->getBreakParent(); + if (!S) { + // C99 6.8.6.3p1: A break shall appear only in or as a switch/loop body. + return StmtError(Diag(BreakLoc, diag::err_break_not_in_loop_or_switch)); + } + + return Owned(new (Context) BreakStmt(BreakLoc)); +} + +/// \brief Determine whether the given expression is a candidate for +/// copy elision in either a return statement or a throw expression. +/// +/// \param ReturnType If we're determining the copy elision candidate for +/// a return statement, this is the return type of the function. If we're +/// determining the copy elision candidate for a throw expression, this will +/// be a NULL type. +/// +/// \param E The expression being returned from the function or block, or +/// being thrown. +/// +/// \param AllowFunctionParameter Whether we allow function parameters to +/// be considered NRVO candidates. C++ prohibits this for NRVO itself, but +/// we re-use this logic to determine whether we should try to move as part of +/// a return or throw (which does allow function parameters). +/// +/// \returns The NRVO candidate variable, if the return statement may use the +/// NRVO, or NULL if there is no such candidate. +const VarDecl *Sema::getCopyElisionCandidate(QualType ReturnType, + Expr *E, + bool AllowFunctionParameter) { + QualType ExprType = E->getType(); + // - in a return statement in a function with ... + // ... a class return type ... + if (!ReturnType.isNull()) { + if (!ReturnType->isRecordType()) + return 0; + // ... the same cv-unqualified type as the function return type ... + if (!Context.hasSameUnqualifiedType(ReturnType, ExprType)) + return 0; + } + + // ... the expression is the name of a non-volatile automatic object + // (other than a function or catch-clause parameter)) ... + const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E->IgnoreParens()); + if (!DR) + return 0; + const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); + if (!VD) + return 0; + + if (VD->hasLocalStorage() && !VD->isExceptionVariable() && + !VD->getType()->isReferenceType() && !VD->hasAttr<BlocksAttr>() && + !VD->getType().isVolatileQualified() && + ((VD->getKind() == Decl::Var) || + (AllowFunctionParameter && VD->getKind() == Decl::ParmVar))) + return VD; + + return 0; +} + +/// \brief Perform the initialization of a potentially-movable value, which +/// is the result of return value. +/// +/// This routine implements C++0x [class.copy]p33, which attempts to treat +/// returned lvalues as rvalues in certain cases (to prefer move construction), +/// then falls back to treating them as lvalues if that failed. +ExprResult +Sema::PerformMoveOrCopyInitialization(const InitializedEntity &Entity, + const VarDecl *NRVOCandidate, + QualType ResultType, + Expr *Value) { + // C++0x [class.copy]p33: + // When the criteria for elision of a copy operation are met or would + // be met save for the fact that the source object is a function + // parameter, and the object to be copied is designated by an lvalue, + // overload resolution to select the constructor for the copy is first + // performed as if the object were designated by an rvalue. + ExprResult Res = ExprError(); + if (NRVOCandidate || getCopyElisionCandidate(ResultType, Value, true)) { + ImplicitCastExpr AsRvalue(ImplicitCastExpr::OnStack, + Value->getType(), CK_LValueToRValue, + Value, VK_XValue); + + Expr *InitExpr = &AsRvalue; + InitializationKind Kind + = InitializationKind::CreateCopy(Value->getLocStart(), + Value->getLocStart()); + InitializationSequence Seq(*this, Entity, Kind, &InitExpr, 1); + + // [...] If overload resolution fails, or if the type of the first + // parameter of the selected constructor is not an rvalue reference + // to the object's type (possibly cv-qualified), overload resolution + // is performed again, considering the object as an lvalue. + if (Seq) { + for (InitializationSequence::step_iterator Step = Seq.step_begin(), + StepEnd = Seq.step_end(); + Step != StepEnd; ++Step) { + if (Step->Kind != InitializationSequence::SK_ConstructorInitialization) + continue; + + CXXConstructorDecl *Constructor + = cast<CXXConstructorDecl>(Step->Function.Function); + + const RValueReferenceType *RRefType + = Constructor->getParamDecl(0)->getType() + ->getAs<RValueReferenceType>(); + + // If we don't meet the criteria, break out now. + if (!RRefType || + !Context.hasSameUnqualifiedType(RRefType->getPointeeType(), + Context.getTypeDeclType(Constructor->getParent()))) + break; + + // Promote "AsRvalue" to the heap, since we now need this + // expression node to persist. + Value = ImplicitCastExpr::Create(Context, Value->getType(), + CK_LValueToRValue, Value, 0, + VK_XValue); + + // Complete type-checking the initialization of the return type + // using the constructor we found. + Res = Seq.Perform(*this, Entity, Kind, MultiExprArg(&Value, 1)); + } + } + } + + // Either we didn't meet the criteria for treating an lvalue as an rvalue, + // above, or overload resolution failed. Either way, we need to try + // (again) now with the return value expression as written. + if (Res.isInvalid()) + Res = PerformCopyInitialization(Entity, SourceLocation(), Value); + + return Res; +} + +/// ActOnBlockReturnStmt - Utility routine to figure out block's return type. +/// +StmtResult +Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { + // If this is the first return we've seen in the block, infer the type of + // the block from it. + BlockScopeInfo *CurBlock = getCurBlock(); + if (CurBlock->ReturnType.isNull()) { + if (RetValExp) { + // Don't call UsualUnaryConversions(), since we don't want to do + // integer promotions here. + ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); + + if (!RetValExp->isTypeDependent()) { + CurBlock->ReturnType = RetValExp->getType(); + if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { + // We have to remove a 'const' added to copied-in variable which was + // part of the implementation spec. and not the actual qualifier for + // the variable. + if (CDRE->isConstQualAdded()) + CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? + } + } else + CurBlock->ReturnType = Context.DependentTy; + } else + CurBlock->ReturnType = Context.VoidTy; + } + QualType FnRetType = CurBlock->ReturnType; + + if (CurBlock->FunctionType->getAs<FunctionType>()->getNoReturnAttr()) { + Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr) + << getCurFunctionOrMethodDecl()->getDeclName(); + return StmtError(); + } + + // Otherwise, verify that this result type matches the previous one. We are + // pickier with blocks than for normal functions because we don't have GCC + // compatibility to worry about here. + ReturnStmt *Result = 0; + if (CurBlock->ReturnType->isVoidType()) { + if (RetValExp && !RetValExp->isTypeDependent() && + (!getLangOptions().CPlusPlus || !RetValExp->getType()->isVoidType())) { + Diag(ReturnLoc, diag::err_return_block_has_expr); + RetValExp = 0; + } + Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0); + } else if (!RetValExp) { + if (!CurBlock->ReturnType->isDependentType()) + return StmtError(Diag(ReturnLoc, diag::err_block_return_missing_expr)); + + Result = new (Context) ReturnStmt(ReturnLoc, 0, 0); + } else { + const VarDecl *NRVOCandidate = 0; + + if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { + // we have a non-void block with an expression, continue checking + + // C99 6.8.6.4p3(136): The return statement is not an assignment. The + // overlap restriction of subclause 6.5.16.1 does not apply to the case of + // function return. + + // In C++ the return statement is handled via a copy initialization. + // the C version of which boils down to CheckSingleAssignmentConstraints. + NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); + InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, + FnRetType, + NRVOCandidate != 0); + ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, + FnRetType, RetValExp); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? + return StmtError(); + } + + if (RetValExp) { + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } + + RetValExp = Res.takeAs<Expr>(); + if (RetValExp) + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + } + + Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); + } + + // If we need to check for the named return value optimization, save the + // return statement in our scope for later processing. + if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && + !CurContext->isDependentContext()) + FunctionScopes.back()->Returns.push_back(Result); + + return Owned(Result); +} + +StmtResult +Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { + // Check for unexpanded parameter packs. + if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp)) + return StmtError(); + + if (getCurBlock()) + return ActOnBlockReturnStmt(ReturnLoc, RetValExp); + + QualType FnRetType; + QualType DeclaredRetType; + if (const FunctionDecl *FD = getCurFunctionDecl()) { + FnRetType = FD->getResultType(); + DeclaredRetType = FnRetType; + if (FD->hasAttr<NoReturnAttr>() || + FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) + Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) + << getCurFunctionOrMethodDecl()->getDeclName(); + } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { + DeclaredRetType = MD->getResultType(); + if (MD->hasRelatedResultType() && MD->getClassInterface()) { + // In the implementation of a method with a related return type, the + // type used to type-check the validity of return statements within the + // method body is a pointer to the type of the class being implemented. + FnRetType = Context.getObjCInterfaceType(MD->getClassInterface()); + FnRetType = Context.getObjCObjectPointerType(FnRetType); + } else { + FnRetType = DeclaredRetType; + } + } else // If we don't have a function/method context, bail. + return StmtError(); + + ReturnStmt *Result = 0; + if (FnRetType->isVoidType()) { + if (RetValExp) { + if (!RetValExp->isTypeDependent()) { + // C99 6.8.6.4p1 (ext_ since GCC warns) + unsigned D = diag::ext_return_has_expr; + if (RetValExp->getType()->isVoidType()) + D = diag::ext_return_has_void_expr; + else { + ExprResult Result = Owned(RetValExp); + Result = IgnoredValueConversions(Result.take()); + if (Result.isInvalid()) + return StmtError(); + RetValExp = Result.take(); + RetValExp = ImpCastExprToType(RetValExp, + Context.VoidTy, CK_ToVoid).take(); + } + + // return (some void expression); is legal in C++. + if (D != diag::ext_return_has_void_expr || + !getLangOptions().CPlusPlus) { + NamedDecl *CurDecl = getCurFunctionOrMethodDecl(); + Diag(ReturnLoc, D) + << CurDecl->getDeclName() << isa<ObjCMethodDecl>(CurDecl) + << RetValExp->getSourceRange(); + } + } + + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } + + Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, 0); + } else if (!RetValExp && !FnRetType->isDependentType()) { + unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4 + // C99 6.8.6.4p1 (ext_ since GCC warns) + if (getLangOptions().C99) DiagID = diag::ext_return_missing_expr; + + if (FunctionDecl *FD = getCurFunctionDecl()) + Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/; + else + Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; + Result = new (Context) ReturnStmt(ReturnLoc); + } else { + const VarDecl *NRVOCandidate = 0; + if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { + // we have a non-void function with an expression, continue checking + + // C99 6.8.6.4p3(136): The return statement is not an assignment. The + // overlap restriction of subclause 6.5.16.1 does not apply to the case of + // function return. + + // In C++ the return statement is handled via a copy initialization. + // the C version of which boils down to CheckSingleAssignmentConstraints. + NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); + InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, + FnRetType, + NRVOCandidate != 0); + ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, + FnRetType, RetValExp); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? + return StmtError(); + } + + RetValExp = Res.takeAs<Expr>(); + if (RetValExp) + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + } + + if (RetValExp) { + // If we type-checked an Objective-C method's return type based + // on a related return type, we may need to adjust the return + // type again. Do so now. + if (DeclaredRetType != FnRetType) { + ExprResult result = PerformImplicitConversion(RetValExp, + DeclaredRetType, + AA_Returning); + if (result.isInvalid()) return StmtError(); + RetValExp = result.take(); + } + + CheckImplicitConversions(RetValExp, ReturnLoc); + RetValExp = MaybeCreateExprWithCleanups(RetValExp); + } + Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); + } + + // If we need to check for the named return value optimization, save the + // return statement in our scope for later processing. + if (getLangOptions().CPlusPlus && FnRetType->isRecordType() && + !CurContext->isDependentContext()) + FunctionScopes.back()->Returns.push_back(Result); + + return Owned(Result); +} + +/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently +/// ignore "noop" casts in places where an lvalue is required by an inline asm. +/// We emulate this behavior when -fheinous-gnu-extensions is specified, but +/// provide a strong guidance to not use it. +/// +/// This method checks to see if the argument is an acceptable l-value and +/// returns false if it is a case we can handle. +static bool CheckAsmLValue(const Expr *E, Sema &S) { + // Type dependent expressions will be checked during instantiation. + if (E->isTypeDependent()) + return false; + + if (E->isLValue()) + return false; // Cool, this is an lvalue. + + // Okay, this is not an lvalue, but perhaps it is the result of a cast that we + // are supposed to allow. + const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); + if (E != E2 && E2->isLValue()) { + if (!S.getLangOptions().HeinousExtensions) + S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) + << E->getSourceRange(); + else + S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) + << E->getSourceRange(); + // Accept, even if we emitted an error diagnostic. + return false; + } + + // None of the above, just randomly invalid non-lvalue. + return true; +} + +/// isOperandMentioned - Return true if the specified operand # is mentioned +/// anywhere in the decomposed asm string. +static bool isOperandMentioned(unsigned OpNo, + llvm::ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { + for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { + const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; + if (!Piece.isOperand()) continue; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (Piece.getOperandNo() == OpNo) + return true; + } + + return false; +} + +StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg constraints, MultiExprArg exprs, + Expr *asmString, MultiExprArg clobbers, + SourceLocation RParenLoc, bool MSAsm) { + unsigned NumClobbers = clobbers.size(); + StringLiteral **Constraints = + reinterpret_cast<StringLiteral**>(constraints.get()); + Expr **Exprs = exprs.get(); + StringLiteral *AsmString = cast<StringLiteral>(asmString); + StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get()); + + llvm::SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; + + // The parser verifies that there is a string literal here. + if (AsmString->isWide()) + return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) + << AsmString->getSourceRange()); + + for (unsigned i = 0; i != NumOutputs; i++) { + StringLiteral *Literal = Constraints[i]; + if (Literal->isWide()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + llvm::StringRef OutputName; + if (Names[i]) + OutputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); + if (!Context.Target.validateOutputConstraint(Info)) + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_invalid_output_constraint) + << Info.getConstraintStr()); + + // Check that the output exprs are valid lvalues. + Expr *OutputExpr = Exprs[i]; + if (CheckAsmLValue(OutputExpr, *this)) { + return StmtError(Diag(OutputExpr->getLocStart(), + diag::err_asm_invalid_lvalue_in_output) + << OutputExpr->getSourceRange()); + } + + OutputConstraintInfos.push_back(Info); + } + + llvm::SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; + + for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { + StringLiteral *Literal = Constraints[i]; + if (Literal->isWide()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + llvm::StringRef InputName; + if (Names[i]) + InputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); + if (!Context.Target.validateInputConstraint(OutputConstraintInfos.data(), + NumOutputs, Info)) { + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_invalid_input_constraint) + << Info.getConstraintStr()); + } + + Expr *InputExpr = Exprs[i]; + + // Only allow void types for memory constraints. + if (Info.allowsMemory() && !Info.allowsRegister()) { + if (CheckAsmLValue(InputExpr, *this)) + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_lvalue_in_input) + << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } + + if (Info.allowsRegister()) { + if (InputExpr->getType()->isVoidType()) { + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_type_in_input) + << InputExpr->getType() << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } + } + + ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); + if (Result.isInvalid()) + return StmtError(); + + Exprs[i] = Result.take(); + InputConstraintInfos.push_back(Info); + } + + // Check that the clobbers are valid. + for (unsigned i = 0; i != NumClobbers; i++) { + StringLiteral *Literal = Clobbers[i]; + if (Literal->isWide()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + llvm::StringRef Clobber = Literal->getString(); + + if (!Context.Target.isValidGCCRegisterName(Clobber)) + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_unknown_register_name) << Clobber); + } + + AsmStmt *NS = + new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, + NumOutputs, NumInputs, Names, Constraints, Exprs, + AsmString, NumClobbers, Clobbers, RParenLoc); + // Validate the asm string, ensuring it makes sense given the operands we + // have. + llvm::SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; + unsigned DiagOffs; + if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { + Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) + << AsmString->getSourceRange(); + return StmtError(); + } + + // Validate tied input operands for type mismatches. + for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { + TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; + + // If this is a tied constraint, verify that the output and input have + // either exactly the same type, or that they are int/ptr operands with the + // same size (int/long, int*/long, are ok etc). + if (!Info.hasTiedOperand()) continue; + + unsigned TiedTo = Info.getTiedOperand(); + unsigned InputOpNo = i+NumOutputs; + Expr *OutputExpr = Exprs[TiedTo]; + Expr *InputExpr = Exprs[InputOpNo]; + QualType InTy = InputExpr->getType(); + QualType OutTy = OutputExpr->getType(); + if (Context.hasSameType(InTy, OutTy)) + continue; // All types can be tied to themselves. + + // Decide if the input and output are in the same domain (integer/ptr or + // floating point. + enum AsmDomain { + AD_Int, AD_FP, AD_Other + } InputDomain, OutputDomain; + + if (InTy->isIntegerType() || InTy->isPointerType()) + InputDomain = AD_Int; + else if (InTy->isRealFloatingType()) + InputDomain = AD_FP; + else + InputDomain = AD_Other; + + if (OutTy->isIntegerType() || OutTy->isPointerType()) + OutputDomain = AD_Int; + else if (OutTy->isRealFloatingType()) + OutputDomain = AD_FP; + else + OutputDomain = AD_Other; + + // They are ok if they are the same size and in the same domain. This + // allows tying things like: + // void* to int* + // void* to int if they are the same size. + // double to long double if they are the same size. + // + uint64_t OutSize = Context.getTypeSize(OutTy); + uint64_t InSize = Context.getTypeSize(InTy); + if (OutSize == InSize && InputDomain == OutputDomain && + InputDomain != AD_Other) + continue; + + // If the smaller input/output operand is not mentioned in the asm string, + // then we can promote the smaller one to a larger input and the asm string + // won't notice. + bool SmallerValueMentioned = false; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (isOperandMentioned(InputOpNo, Pieces)) { + // This is a use in the asm string of the smaller operand. Since we + // codegen this by promoting to a wider value, the asm will get printed + // "wrong". + SmallerValueMentioned |= InSize < OutSize; + } + if (isOperandMentioned(TiedTo, Pieces)) { + // If this is a reference to the output, and if the output is the larger + // value, then it's ok because we'll promote the input to the larger type. + SmallerValueMentioned |= OutSize < InSize; + } + + // If the smaller value wasn't mentioned in the asm string, and if the + // output was a register, just extend the shorter one to the size of the + // larger one. + if (!SmallerValueMentioned && InputDomain != AD_Other && + OutputConstraintInfos[TiedTo].allowsRegister()) + continue; + + // Either both of the operands were mentioned or the smaller one was + // mentioned. One more special case that we'll allow: if the tied input is + // integer, unmentioned, and is a constant, then we'll allow truncating it + // down to the size of the destination. + if (InputDomain == AD_Int && OutputDomain == AD_Int && + !isOperandMentioned(InputOpNo, Pieces) && + InputExpr->isEvaluatable(Context)) { + CastKind castKind = + (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); + InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); + Exprs[InputOpNo] = InputExpr; + NS->setInputExpr(i, InputExpr); + continue; + } + + Diag(InputExpr->getLocStart(), + diag::err_asm_tying_incompatible_types) + << InTy << OutTy << OutputExpr->getSourceRange() + << InputExpr->getSourceRange(); + return StmtError(); + } + + return Owned(NS); +} + +StmtResult +Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, + SourceLocation RParen, Decl *Parm, + Stmt *Body) { + VarDecl *Var = cast_or_null<VarDecl>(Parm); + if (Var && Var->isInvalidDecl()) + return StmtError(); + + return Owned(new (Context) ObjCAtCatchStmt(AtLoc, RParen, Var, Body)); +} + +StmtResult +Sema::ActOnObjCAtFinallyStmt(SourceLocation AtLoc, Stmt *Body) { + return Owned(new (Context) ObjCAtFinallyStmt(AtLoc, Body)); +} + +StmtResult +Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, + MultiStmtArg CatchStmts, Stmt *Finally) { + if (!getLangOptions().ObjCExceptions) + Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@try"; + + getCurFunction()->setHasBranchProtectedScope(); + unsigned NumCatchStmts = CatchStmts.size(); + return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try, + CatchStmts.release(), + NumCatchStmts, + Finally)); +} + +StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, + Expr *Throw) { + if (Throw) { + ExprResult Result = DefaultLvalueConversion(Throw); + if (Result.isInvalid()) + return StmtError(); + + Throw = Result.take(); + QualType ThrowType = Throw->getType(); + // Make sure the expression type is an ObjC pointer or "void *". + if (!ThrowType->isDependentType() && + !ThrowType->isObjCObjectPointerType()) { + const PointerType *PT = ThrowType->getAs<PointerType>(); + if (!PT || !PT->getPointeeType()->isVoidType()) + return StmtError(Diag(AtLoc, diag::error_objc_throw_expects_object) + << Throw->getType() << Throw->getSourceRange()); + } + } + + return Owned(new (Context) ObjCAtThrowStmt(AtLoc, Throw)); +} + +StmtResult +Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw, + Scope *CurScope) { + if (!getLangOptions().ObjCExceptions) + Diag(AtLoc, diag::err_objc_exceptions_disabled) << "@throw"; + + if (!Throw) { + // @throw without an expression designates a rethrow (which much occur + // in the context of an @catch clause). + Scope *AtCatchParent = CurScope; + while (AtCatchParent && !AtCatchParent->isAtCatchScope()) + AtCatchParent = AtCatchParent->getParent(); + if (!AtCatchParent) + return StmtError(Diag(AtLoc, diag::error_rethrow_used_outside_catch)); + } + + return BuildObjCAtThrowStmt(AtLoc, Throw); +} + +StmtResult +Sema::ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, Expr *SyncExpr, + Stmt *SyncBody) { + getCurFunction()->setHasBranchProtectedScope(); + + ExprResult Result = DefaultLvalueConversion(SyncExpr); + if (Result.isInvalid()) + return StmtError(); + + SyncExpr = Result.take(); + // Make sure the expression type is an ObjC pointer or "void *". + if (!SyncExpr->getType()->isDependentType() && + !SyncExpr->getType()->isObjCObjectPointerType()) { + const PointerType *PT = SyncExpr->getType()->getAs<PointerType>(); + if (!PT || !PT->getPointeeType()->isVoidType()) + return StmtError(Diag(AtLoc, diag::error_objc_synchronized_expects_object) + << SyncExpr->getType() << SyncExpr->getSourceRange()); + } + + return Owned(new (Context) ObjCAtSynchronizedStmt(AtLoc, SyncExpr, SyncBody)); +} + +/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block +/// and creates a proper catch handler from them. +StmtResult +Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, + Stmt *HandlerBlock) { + // There's nothing to test that ActOnExceptionDecl didn't already test. + return Owned(new (Context) CXXCatchStmt(CatchLoc, + cast_or_null<VarDecl>(ExDecl), + HandlerBlock)); +} + +namespace { + +class TypeWithHandler { + QualType t; + CXXCatchStmt *stmt; +public: + TypeWithHandler(const QualType &type, CXXCatchStmt *statement) + : t(type), stmt(statement) {} + + // An arbitrary order is fine as long as it places identical + // types next to each other. + bool operator<(const TypeWithHandler &y) const { + if (t.getAsOpaquePtr() < y.t.getAsOpaquePtr()) + return true; + if (t.getAsOpaquePtr() > y.t.getAsOpaquePtr()) + return false; + else + return getTypeSpecStartLoc() < y.getTypeSpecStartLoc(); + } + + bool operator==(const TypeWithHandler& other) const { + return t == other.t; + } + + CXXCatchStmt *getCatchStmt() const { return stmt; } + SourceLocation getTypeSpecStartLoc() const { + return stmt->getExceptionDecl()->getTypeSpecStartLoc(); + } +}; + +} + +/// ActOnCXXTryBlock - Takes a try compound-statement and a number of +/// handlers and creates a try statement from them. +StmtResult +Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, + MultiStmtArg RawHandlers) { + // Don't report an error if 'try' is used in system headers. + if (!getLangOptions().CXXExceptions && + !getSourceManager().isInSystemHeader(TryLoc)) + Diag(TryLoc, diag::err_exceptions_disabled) << "try"; + + unsigned NumHandlers = RawHandlers.size(); + assert(NumHandlers > 0 && + "The parser shouldn't call this if there are no handlers."); + Stmt **Handlers = RawHandlers.get(); + + llvm::SmallVector<TypeWithHandler, 8> TypesWithHandlers; + + for (unsigned i = 0; i < NumHandlers; ++i) { + CXXCatchStmt *Handler = llvm::cast<CXXCatchStmt>(Handlers[i]); + if (!Handler->getExceptionDecl()) { + if (i < NumHandlers - 1) + return StmtError(Diag(Handler->getLocStart(), + diag::err_early_catch_all)); + + continue; + } + + const QualType CaughtType = Handler->getCaughtType(); + const QualType CanonicalCaughtType = Context.getCanonicalType(CaughtType); + TypesWithHandlers.push_back(TypeWithHandler(CanonicalCaughtType, Handler)); + } + + // Detect handlers for the same type as an earlier one. + if (NumHandlers > 1) { + llvm::array_pod_sort(TypesWithHandlers.begin(), TypesWithHandlers.end()); + + TypeWithHandler prev = TypesWithHandlers[0]; + for (unsigned i = 1; i < TypesWithHandlers.size(); ++i) { + TypeWithHandler curr = TypesWithHandlers[i]; + + if (curr == prev) { + Diag(curr.getTypeSpecStartLoc(), + diag::warn_exception_caught_by_earlier_handler) + << curr.getCatchStmt()->getCaughtType().getAsString(); + Diag(prev.getTypeSpecStartLoc(), + diag::note_previous_exception_handler) + << prev.getCatchStmt()->getCaughtType().getAsString(); + } + + prev = curr; + } + } + + 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 + // quadratic for this. + // Neither of these are explicitly forbidden, but every compiler detects them + // and warns. + + return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, + Handlers, NumHandlers)); +} + +StmtResult +Sema::ActOnSEHTryBlock(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + assert(TryBlock && Handler); + + getCurFunction()->setHasBranchProtectedScope(); + + return Owned(SEHTryStmt::Create(Context,IsCXXTry,TryLoc,TryBlock,Handler)); +} + +StmtResult +Sema::ActOnSEHExceptBlock(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + assert(FilterExpr && Block); + + if(!FilterExpr->getType()->isIntegerType()) { + return StmtError(Diag(FilterExpr->getExprLoc(), + diag::err_filter_expression_integral) + << FilterExpr->getType()); + } + + return Owned(SEHExceptStmt::Create(Context,Loc,FilterExpr,Block)); +} + +StmtResult +Sema::ActOnSEHFinallyBlock(SourceLocation Loc, + Stmt *Block) { + assert(Block); + return Owned(SEHFinallyStmt::Create(Context,Loc,Block)); +} + diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp new file mode 100644 index 0000000..5d4caac --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -0,0 +1,6701 @@ +//===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements semantic analysis for C++ templates. +//===----------------------------------------------------------------------===/ + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" +#include "TreeTransform.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/TypeVisitor.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/StringExtras.h" +using namespace clang; +using namespace sema; + +// Exported for use by Parser. +SourceRange +clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, + unsigned N) { + if (!N) return SourceRange(); + return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc()); +} + +/// \brief Determine whether the declaration found is acceptable as the name +/// of a template and, if so, return that template declaration. Otherwise, +/// returns NULL. +static NamedDecl *isAcceptableTemplateName(ASTContext &Context, + NamedDecl *Orig) { + NamedDecl *D = Orig->getUnderlyingDecl(); + + if (isa<TemplateDecl>(D)) + return Orig; + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { + // C++ [temp.local]p1: + // Like normal (non-template) classes, class templates have an + // injected-class-name (Clause 9). The injected-class-name + // can be used with or without a template-argument-list. When + // it is used without a template-argument-list, it is + // equivalent to the injected-class-name followed by the + // template-parameters of the class template enclosed in + // <>. When it is used with a template-argument-list, it + // refers to the specified class template specialization, + // which could be the current specialization or another + // specialization. + if (Record->isInjectedClassName()) { + Record = cast<CXXRecordDecl>(Record->getDeclContext()); + if (Record->getDescribedClassTemplate()) + return Record->getDescribedClassTemplate(); + + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Record)) + return Spec->getSpecializedTemplate(); + } + + return 0; + } + + return 0; +} + +void Sema::FilterAcceptableTemplateNames(LookupResult &R) { + // The set of class templates we've already seen. + llvm::SmallPtrSet<ClassTemplateDecl *, 8> ClassTemplates; + LookupResult::Filter filter = R.makeFilter(); + while (filter.hasNext()) { + NamedDecl *Orig = filter.next(); + NamedDecl *Repl = isAcceptableTemplateName(Context, Orig); + if (!Repl) + filter.erase(); + else if (Repl != Orig) { + + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is used as a template-name, the reference refers to the class + // template itself and not a specialization thereof, and is not + // ambiguous. + if (ClassTemplateDecl *ClassTmpl = dyn_cast<ClassTemplateDecl>(Repl)) + if (!ClassTemplates.insert(ClassTmpl)) { + filter.erase(); + continue; + } + + // FIXME: we promote access to public here as a workaround to + // the fact that LookupResult doesn't let us remember that we + // found this template through a particular injected class name, + // which means we end up doing nasty things to the invariants. + // Pretending that access is public is *much* safer. + filter.replace(Repl, AS_public); + } + } + filter.done(); +} + +bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R) { + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) + if (isAcceptableTemplateName(Context, *I)) + return true; + + return false; +} + +TemplateNameKind Sema::isTemplateName(Scope *S, + CXXScopeSpec &SS, + bool hasTemplateKeyword, + UnqualifiedId &Name, + ParsedType ObjectTypePtr, + bool EnteringContext, + TemplateTy &TemplateResult, + bool &MemberOfUnknownSpecialization) { + assert(getLangOptions().CPlusPlus && "No template names in C!"); + + DeclarationName TName; + MemberOfUnknownSpecialization = false; + + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + TName = DeclarationName(Name.Identifier); + break; + + case UnqualifiedId::IK_OperatorFunctionId: + TName = Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator); + break; + + case UnqualifiedId::IK_LiteralOperatorId: + TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier); + break; + + default: + return TNK_Non_template; + } + + QualType ObjectType = ObjectTypePtr.get(); + + LookupResult R(*this, TName, Name.getSourceRange().getBegin(), + LookupOrdinaryName); + LookupTemplateName(R, S, SS, ObjectType, EnteringContext, + MemberOfUnknownSpecialization); + if (R.empty()) return TNK_Non_template; + if (R.isAmbiguous()) { + // Suppress diagnostics; we'll redo this lookup later. + R.suppressDiagnostics(); + + // FIXME: we might have ambiguous templates, in which case we + // should at least parse them properly! + return TNK_Non_template; + } + + TemplateName Template; + TemplateNameKind TemplateKind; + + unsigned ResultCount = R.end() - R.begin(); + if (ResultCount > 1) { + // We assume that we'll preserve the qualifier from a function + // template name in other ways. + Template = Context.getOverloadedTemplateName(R.begin(), R.end()); + TemplateKind = TNK_Function_template; + + // We'll do this lookup again later. + R.suppressDiagnostics(); + } else { + TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl()); + + if (SS.isSet() && !SS.isInvalid()) { + NestedNameSpecifier *Qualifier + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + Template = Context.getQualifiedTemplateName(Qualifier, + hasTemplateKeyword, TD); + } else { + Template = TemplateName(TD); + } + + if (isa<FunctionTemplateDecl>(TD)) { + TemplateKind = TNK_Function_template; + + // We'll do this lookup again later. + R.suppressDiagnostics(); + } else { + assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) || + isa<TypeAliasTemplateDecl>(TD)); + TemplateKind = TNK_Type_template; + } + } + + TemplateResult = TemplateTy::make(Template); + return TemplateKind; +} + +bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind) { + // We can't recover unless there's a dependent scope specifier preceding the + // template name. + // FIXME: Typo correction? + if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) || + computeDeclContext(*SS)) + return false; + + // The code is missing a 'template' keyword prior to the dependent template + // name. + NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep(); + Diag(IILoc, diag::err_template_kw_missing) + << Qualifier << II.getName() + << FixItHint::CreateInsertion(IILoc, "template "); + SuggestedTemplate + = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II)); + SuggestedKind = TNK_Dependent_template_name; + return true; +} + +void Sema::LookupTemplateName(LookupResult &Found, + Scope *S, CXXScopeSpec &SS, + QualType ObjectType, + bool EnteringContext, + bool &MemberOfUnknownSpecialization) { + // Determine where to perform name lookup + MemberOfUnknownSpecialization = false; + DeclContext *LookupCtx = 0; + bool isDependent = false; + if (!ObjectType.isNull()) { + // This nested-name-specifier occurs in a member access expression, e.g., + // x->B::f, and we are looking into the type of the object. + assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + assert((isDependent || !ObjectType->isIncompleteType()) && + "Caller should have completed object type"); + } else if (SS.isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so long into the context associated with the prior nested-name-specifier. + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = isDependentScopeSpecifier(SS); + + // The declaration context must be complete. + if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx)) + return; + } + + bool ObjectTypeSearchedInScope = false; + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + LookupQualifiedName(Found, LookupCtx); + + if (!ObjectType.isNull() && Found.empty()) { + // C++ [basic.lookup.classref]p1: + // In a class member access expression (5.2.5), if the . or -> token is + // immediately followed by an identifier followed by a <, the + // identifier must be looked up to determine whether the < is the + // beginning of a template argument list (14.2) or a less-than operator. + // The identifier is first looked up in the class of the object + // expression. If the identifier is not found, it is then looked up in + // the context of the entire postfix-expression and shall name a class + // or function template. + if (S) LookupName(Found, S); + ObjectTypeSearchedInScope = true; + } + } else if (isDependent && (!S || ObjectType.isNull())) { + // We cannot look into a dependent object type or nested nme + // specifier. + MemberOfUnknownSpecialization = true; + return; + } else { + // Perform unqualified name lookup in the current scope. + LookupName(Found, S); + } + + if (Found.empty() && !isDependent) { + // If we did not find any names, attempt to correct any typos. + DeclarationName Name = Found.getLookupName(); + if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx, + false, CTC_CXXCasts)) { + FilterAcceptableTemplateNames(Found); + if (!Found.empty()) { + if (LookupCtx) + Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) + << Name << LookupCtx << Found.getLookupName() << SS.getRange() + << FixItHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + else + Diag(Found.getNameLoc(), diag::err_no_template_suggest) + << Name << Found.getLookupName() + << FixItHint::CreateReplacement(Found.getNameLoc(), + Found.getLookupName().getAsString()); + if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>()) + Diag(Template->getLocation(), diag::note_previous_decl) + << Template->getDeclName(); + } + } else { + Found.clear(); + Found.setLookupName(Name); + } + } + + FilterAcceptableTemplateNames(Found); + if (Found.empty()) { + if (isDependent) + MemberOfUnknownSpecialization = true; + return; + } + + if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope) { + // C++ [basic.lookup.classref]p1: + // [...] If the lookup in the class of the object expression finds a + // template, the name is also looked up in the context of the entire + // postfix-expression and [...] + // + LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), + LookupOrdinaryName); + LookupName(FoundOuter, S); + FilterAcceptableTemplateNames(FoundOuter); + + if (FoundOuter.empty()) { + // - if the name is not found, the name found in the class of the + // object expression is used, otherwise + } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>()) { + // - if the name is found in the context of the entire + // postfix-expression and does not name a class template, the name + // found in the class of the object expression is used, otherwise + } else if (!Found.isSuppressingDiagnostics()) { + // - if the name found is a class template, it must refer to the same + // entity as the one found in the class of the object expression, + // otherwise the program is ill-formed. + if (!Found.isSingleResult() || + Found.getFoundDecl()->getCanonicalDecl() + != FoundOuter.getFoundDecl()->getCanonicalDecl()) { + Diag(Found.getNameLoc(), + diag::ext_nested_name_member_ref_lookup_ambiguous) + << Found.getLookupName() + << ObjectType; + Diag(Found.getRepresentativeDecl()->getLocation(), + diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(FoundOuter.getFoundDecl()->getLocation(), + diag::note_ambig_member_ref_scope); + + // Recover by taking the template that we found in the object + // expression's type. + } + } + } +} + +/// ActOnDependentIdExpression - Handle a dependent id-expression that +/// was just parsed. This is only possible with an explicit scope +/// specifier naming a dependent type. +ExprResult +Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + bool isAddressOfOperand, + const TemplateArgumentListInfo *TemplateArgs) { + DeclContext *DC = getFunctionLevelDeclContext(); + + if (!isAddressOfOperand && + isa<CXXMethodDecl>(DC) && + cast<CXXMethodDecl>(DC)->isInstance()) { + QualType ThisType = cast<CXXMethodDecl>(DC)->getThisType(Context); + + // Since the 'this' expression is synthesized, we don't need to + // perform the double-lookup check. + NamedDecl *FirstQualifierInScope = 0; + + return Owned(CXXDependentScopeMemberExpr::Create(Context, + /*This*/ 0, ThisType, + /*IsArrow*/ true, + /*Op*/ SourceLocation(), + SS.getWithLocInContext(Context), + FirstQualifierInScope, + NameInfo, + TemplateArgs)); + } + + return BuildDependentDeclRefExpr(SS, NameInfo, TemplateArgs); +} + +ExprResult +Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + return Owned(DependentScopeDeclRefExpr::Create(Context, + SS.getWithLocInContext(Context), + NameInfo, + TemplateArgs)); +} + +/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining +/// that the template parameter 'PrevDecl' is being shadowed by a new +/// declaration at location Loc. Returns true to indicate that this is +/// an error, and false otherwise. +bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { + assert(PrevDecl->isTemplateParameter() && "Not a template parameter"); + + // Microsoft Visual C++ permits template parameters to be shadowed. + if (getLangOptions().Microsoft) + return false; + + // C++ [temp.local]p4: + // A template-parameter shall not be redeclared within its + // scope (including nested scopes). + Diag(Loc, diag::err_template_param_shadow) + << cast<NamedDecl>(PrevDecl)->getDeclName(); + Diag(PrevDecl->getLocation(), diag::note_template_param_here); + return true; +} + +/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset +/// the parameter D to reference the templated declaration and return a pointer +/// to the template declaration. Otherwise, do nothing to D and return null. +TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) { + if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D)) { + D = Temp->getTemplatedDecl(); + return Temp; + } + return 0; +} + +ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion( + SourceLocation EllipsisLoc) const { + assert(Kind == Template && + "Only template template arguments can be pack expansions here"); + assert(getAsTemplate().get().containsUnexpandedParameterPack() && + "Template template argument pack expansion without packs"); + ParsedTemplateArgument Result(*this); + Result.EllipsisLoc = EllipsisLoc; + return Result; +} + +static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, + const ParsedTemplateArgument &Arg) { + + switch (Arg.getKind()) { + case ParsedTemplateArgument::Type: { + TypeSourceInfo *DI; + QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI); + if (!DI) + DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation()); + return TemplateArgumentLoc(TemplateArgument(T), DI); + } + + case ParsedTemplateArgument::NonType: { + Expr *E = static_cast<Expr *>(Arg.getAsExpr()); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case ParsedTemplateArgument::Template: { + TemplateName Template = Arg.getAsTemplate().get(); + TemplateArgument TArg; + if (Arg.getEllipsisLoc().isValid()) + TArg = TemplateArgument(Template, llvm::Optional<unsigned int>()); + else + TArg = Template; + return TemplateArgumentLoc(TArg, + Arg.getScopeSpec().getWithLocInContext( + SemaRef.Context), + Arg.getLocation(), + Arg.getEllipsisLoc()); + } + } + + llvm_unreachable("Unhandled parsed template argument"); + return TemplateArgumentLoc(); +} + +/// \brief Translates template arguments as provided by the parser +/// into template arguments used by semantic analysis. +void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, + TemplateArgumentListInfo &TemplateArgs) { + for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) + TemplateArgs.addArgument(translateTemplateArgument(*this, + TemplateArgsIn[I])); +} + +/// ActOnTypeParameter - Called when a C++ template type parameter +/// (e.g., "typename T") has been parsed. Typename specifies whether +/// the keyword "typename" was used to declare the type parameter +/// (otherwise, "class" was used), and KeyLoc is the location of the +/// "class" or "typename" keyword. ParamName is the name of the +/// parameter (NULL indicates an unnamed template parameter) and +/// ParamNameLoc is the location of the parameter name (if any). +/// If the type parameter has a default argument, it will be added +/// later via ActOnTypeParameterDefault. +Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, + SourceLocation EllipsisLoc, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + ParsedType DefaultArg) { + assert(S->isTemplateParamScope() && + "Template type parameter not in template parameter scope!"); + bool Invalid = false; + + if (ParamName) { + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc, + LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) + Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc, + PrevDecl); + } + + SourceLocation Loc = ParamNameLoc; + if (!ParamName) + Loc = KeyLoc; + + TemplateTypeParmDecl *Param + = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(), + KeyLoc, Loc, Depth, Position, ParamName, + Typename, Ellipsis); + Param->setAccess(AS_public); + if (Invalid) + Param->setInvalidDecl(); + + if (ParamName) { + // Add the template parameter into the current scope. + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (DefaultArg && Ellipsis) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + DefaultArg = ParsedType(); + } + + // Handle the default argument, if provided. + if (DefaultArg) { + TypeSourceInfo *DefaultTInfo; + GetTypeFromParser(DefaultArg, &DefaultTInfo); + + assert(DefaultTInfo && "expected source information for type"); + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo, + UPPC_DefaultArgument)) + return Param; + + // Check the template argument itself. + if (CheckTemplateArgument(Param, DefaultTInfo)) { + Param->setInvalidDecl(); + return Param; + } + + Param->setDefaultArgument(DefaultTInfo, false); + } + + return Param; +} + +/// \brief Check that the type of a non-type template parameter is +/// well-formed. +/// +/// \returns the (possibly-promoted) parameter type if valid; +/// otherwise, produces a diagnostic and returns a NULL type. +QualType +Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { + // We don't allow variably-modified types as the type of non-type template + // parameters. + if (T->isVariablyModifiedType()) { + Diag(Loc, diag::err_variably_modified_nontype_template_param) + << T; + return QualType(); + } + + // C++ [temp.param]p4: + // + // A non-type template-parameter shall have one of the following + // (optionally cv-qualified) types: + // + // -- integral or enumeration type, + if (T->isIntegralOrEnumerationType() || + // -- pointer to object or pointer to function, + T->isPointerType() || + // -- reference to object or reference to function, + T->isReferenceType() || + // -- pointer to member, + T->isMemberPointerType() || + // -- std::nullptr_t. + T->isNullPtrType() || + // If T is a dependent type, we can't do the check now, so we + // assume that it is well-formed. + T->isDependentType()) + return T; + // C++ [temp.param]p8: + // + // A non-type template-parameter of type "array of T" or + // "function returning T" is adjusted to be of type "pointer to + // T" or "pointer to function returning T", respectively. + else if (T->isArrayType()) + // FIXME: Keep the type prior to promotion? + return Context.getArrayDecayedType(T); + else if (T->isFunctionType()) + // FIXME: Keep the type prior to promotion? + return Context.getPointerType(T); + + Diag(Loc, diag::err_template_nontype_parm_bad_type) + << T; + + return QualType(); +} + +Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, + unsigned Position, + SourceLocation EqualLoc, + Expr *Default) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + + assert(S->isTemplateParamScope() && + "Non-type template parameter not in template parameter scope!"); + bool Invalid = false; + + IdentifierInfo *ParamName = D.getIdentifier(); + if (ParamName) { + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(), + LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) + Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), + PrevDecl); + } + + T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc()); + if (T.isNull()) { + T = Context.IntTy; // Recover with an 'int' type. + Invalid = true; + } + + bool IsParameterPack = D.hasEllipsis(); + NonTypeTemplateParmDecl *Param + = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), + D.getSourceRange().getBegin(), + D.getIdentifierLoc(), + Depth, Position, ParamName, T, + IsParameterPack, TInfo); + Param->setAccess(AS_public); + + if (Invalid) + Param->setInvalidDecl(); + + if (D.getIdentifier()) { + // Add the template parameter into the current scope. + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (Default && IsParameterPack) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + Default = 0; + } + + // Check the well-formedness of the default template argument, if provided. + if (Default) { + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument)) + return Param; + + TemplateArgument Converted; + ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted); + if (DefaultRes.isInvalid()) { + Param->setInvalidDecl(); + return Param; + } + Default = DefaultRes.take(); + + Param->setDefaultArgument(Default, false); + } + + return Param; +} + +/// ActOnTemplateTemplateParameter - Called when a C++ template template +/// parameter (e.g. T in template <template <typename> class T> class array) +/// has been parsed. S is the current scope. +Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + SourceLocation EllipsisLoc, + IdentifierInfo *Name, + SourceLocation NameLoc, + unsigned Depth, + unsigned Position, + SourceLocation EqualLoc, + ParsedTemplateArgument Default) { + assert(S->isTemplateParamScope() && + "Template template parameter not in template parameter scope!"); + + // Construct the parameter object. + bool IsParameterPack = EllipsisLoc.isValid(); + TemplateTemplateParmDecl *Param = + TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), + NameLoc.isInvalid()? TmpLoc : NameLoc, + Depth, Position, IsParameterPack, + Name, Params); + Param->setAccess(AS_public); + + // If the template template parameter has a name, then link the identifier + // into the scope and lookup mechanisms. + if (Name) { + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + if (Params->size() == 0) { + Diag(Param->getLocation(), diag::err_template_template_parm_no_parms) + << SourceRange(Params->getLAngleLoc(), Params->getRAngleLoc()); + Param->setInvalidDecl(); + } + + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (IsParameterPack && !Default.isInvalid()) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + Default = ParsedTemplateArgument(); + } + + if (!Default.isInvalid()) { + // Check only that we have a template template argument. We don't want to + // try to check well-formedness now, because our template template parameter + // might have dependent types in its template parameters, which we wouldn't + // be able to match now. + // + // If none of the template template parameter's template arguments mention + // other template parameters, we could actually perform more checking here. + // However, it isn't worth doing. + TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default); + if (DefaultArg.getArgument().getAsTemplate().isNull()) { + Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template) + << DefaultArg.getSourceRange(); + return Param; + } + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(DefaultArg.getLocation(), + DefaultArg.getArgument().getAsTemplate(), + UPPC_DefaultArgument)) + return Param; + + Param->setDefaultArgument(DefaultArg, false); + } + + return Param; +} + +/// ActOnTemplateParameterList - Builds a TemplateParameterList that +/// contains the template parameters in Params/NumParams. +Sema::TemplateParamsTy * +Sema::ActOnTemplateParameterList(unsigned Depth, + SourceLocation ExportLoc, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + Decl **Params, unsigned NumParams, + SourceLocation RAngleLoc) { + if (ExportLoc.isValid()) + Diag(ExportLoc, diag::warn_template_export_unsupported); + + return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, + (NamedDecl**)Params, NumParams, + RAngleLoc); +} + +static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { + if (SS.isSet()) + T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); +} + +DeclResult +Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, + TemplateParameterList *TemplateParams, + AccessSpecifier AS, + unsigned NumOuterTemplateParamLists, + TemplateParameterList** OuterTemplateParamLists) { + assert(TemplateParams && TemplateParams->size() > 0 && + "No template parameters"); + assert(TUK != TUK_Reference && "Can only declare or define class templates"); + bool Invalid = false; + + // Check that we can declare a template here. + if (CheckTemplateDeclScope(S, TemplateParams)) + return true; + + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + assert(Kind != TTK_Enum && "can't build template of enumerated type"); + + // There is no such thing as an unnamed class template. + if (!Name) { + Diag(KWLoc, diag::err_template_unnamed_class); + return true; + } + + // Find any previous declaration with this name. + DeclContext *SemanticContext; + LookupResult Previous(*this, Name, NameLoc, LookupOrdinaryName, + ForRedeclaration); + if (SS.isNotEmpty() && !SS.isInvalid()) { + SemanticContext = computeDeclContext(SS, true); + if (!SemanticContext) { + // FIXME: Produce a reasonable diagnostic here + return true; + } + + if (RequireCompleteDeclContext(SS, SemanticContext)) + return true; + + LookupQualifiedName(Previous, SemanticContext); + } else { + SemanticContext = CurContext; + LookupName(Previous, S); + } + + if (Previous.isAmbiguous()) + return true; + + NamedDecl *PrevDecl = 0; + if (Previous.begin() != Previous.end()) + PrevDecl = (*Previous.begin())->getUnderlyingDecl(); + + // If there is a previous declaration with the same name, check + // whether this is a valid redeclaration. + ClassTemplateDecl *PrevClassTemplate + = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl); + + // We may have found the injected-class-name of a class template, + // class template partial specialization, or class template specialization. + // In these cases, grab the template that is being defined or specialized. + if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && + cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) { + PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext()); + PrevClassTemplate + = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate(); + if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) { + PrevClassTemplate + = cast<ClassTemplateSpecializationDecl>(PrevDecl) + ->getSpecializedTemplate(); + } + } + + if (TUK == TUK_Friend) { + // C++ [namespace.memdef]p3: + // [...] When looking for a prior declaration of a class or a function + // declared as a friend, and when the name of the friend class or + // function is neither a qualified name nor a template-id, scopes outside + // the innermost enclosing namespace scope are not considered. + if (!SS.isSet()) { + DeclContext *OutermostContext = CurContext; + while (!OutermostContext->isFileContext()) + OutermostContext = OutermostContext->getLookupParent(); + + if (PrevDecl && + (OutermostContext->Equals(PrevDecl->getDeclContext()) || + OutermostContext->Encloses(PrevDecl->getDeclContext()))) { + SemanticContext = PrevDecl->getDeclContext(); + } else { + // Declarations in outer scopes don't matter. However, the outermost + // context we computed is the semantic context for our new + // declaration. + PrevDecl = PrevClassTemplate = 0; + SemanticContext = OutermostContext; + } + } + + if (CurContext->isDependentContext()) { + // If this is a dependent context, we don't want to link the friend + // class template to the template in scope, because that would perform + // checking of the template parameter lists that can't be performed + // until the outer context is instantiated. + PrevDecl = PrevClassTemplate = 0; + } + } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) + PrevDecl = PrevClassTemplate = 0; + + if (PrevClassTemplate) { + // Ensure that the template parameter lists are compatible. + if (!TemplateParameterListsAreEqual(TemplateParams, + PrevClassTemplate->getTemplateParameters(), + /*Complain=*/true, + TPL_TemplateMatch)) + return true; + + // C++ [temp.class]p4: + // In a redeclaration, partial specialization, explicit + // specialization or explicit instantiation of a class template, + // the class-key shall agree in kind with the original class + // template declaration (7.1.5.3). + RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl(); + if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, + TUK == TUK_Definition, KWLoc, *Name)) { + Diag(KWLoc, diag::err_use_with_wrong_tag) + << Name + << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName()); + Diag(PrevRecordDecl->getLocation(), diag::note_previous_use); + Kind = PrevRecordDecl->getTagKind(); + } + + // Check for redefinition of this class template. + if (TUK == TUK_Definition) { + if (TagDecl *Def = PrevRecordDecl->getDefinition()) { + Diag(NameLoc, diag::err_redefinition) << Name; + Diag(Def->getLocation(), diag::note_previous_definition); + // FIXME: Would it make sense to try to "forget" the previous + // definition, as part of error recovery? + return true; + } + } + } else if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(NameLoc, PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } else if (PrevDecl) { + // C++ [temp]p5: + // A class template shall not have the same name as any other + // template, class, function, object, enumeration, enumerator, + // namespace, or type in the same scope (3.3), except as specified + // in (14.5.4). + Diag(NameLoc, diag::err_redefinition_different_kind) << Name; + Diag(PrevDecl->getLocation(), diag::note_previous_definition); + return true; + } + + // Check the template parameter list of this declaration, possibly + // merging in the template parameter list from the previous class + // template declaration. + if (CheckTemplateParameterList(TemplateParams, + PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0, + (SS.isSet() && SemanticContext && + SemanticContext->isRecord() && + SemanticContext->isDependentContext()) + ? TPC_ClassTemplateMember + : TPC_ClassTemplate)) + Invalid = true; + + if (SS.isSet()) { + // If the name of the template was qualified, we must be defining the + // template out-of-line. + if (!SS.isInvalid() && !Invalid && !PrevClassTemplate && + !(TUK == TUK_Friend && CurContext->isDependentContext())) + Diag(NameLoc, diag::err_member_def_does_not_match) + << Name << SemanticContext << SS.getRange(); + } + + CXXRecordDecl *NewClass = + CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, + PrevClassTemplate? + PrevClassTemplate->getTemplatedDecl() : 0, + /*DelayTypeCreation=*/true); + SetNestedNameSpecifier(NewClass, SS); + if (NumOuterTemplateParamLists > 0) + NewClass->setTemplateParameterListsInfo(Context, + NumOuterTemplateParamLists, + OuterTemplateParamLists); + + ClassTemplateDecl *NewTemplate + = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, + DeclarationName(Name), TemplateParams, + NewClass, PrevClassTemplate); + NewClass->setDescribedClassTemplate(NewTemplate); + + // Build the type for the class template declaration now. + QualType T = NewTemplate->getInjectedClassNameSpecialization(); + T = Context.getInjectedClassNameType(NewClass, T); + assert(T->isDependentType() && "Class template type is not dependent?"); + (void)T; + + // If we are providing an explicit specialization of a member that is a + // class template, make a note of that. + if (PrevClassTemplate && + PrevClassTemplate->getInstantiatedFromMemberTemplate()) + PrevClassTemplate->setMemberSpecialization(); + + // Set the access specifier. + if (!Invalid && TUK != TUK_Friend) + SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); + + // Set the lexical context of these templates + NewClass->setLexicalDeclContext(CurContext); + NewTemplate->setLexicalDeclContext(CurContext); + + if (TUK == TUK_Definition) + NewClass->startDefinition(); + + if (Attr) + ProcessDeclAttributeList(S, NewClass, Attr); + + if (TUK != TUK_Friend) + PushOnScopeChains(NewTemplate, S); + else { + if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) { + NewTemplate->setAccess(PrevClassTemplate->getAccess()); + NewClass->setAccess(PrevClassTemplate->getAccess()); + } + + NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */ + PrevClassTemplate != NULL); + + // Friend templates are visible in fairly strange ways. + if (!CurContext->isDependentContext()) { + DeclContext *DC = SemanticContext->getRedeclContext(); + DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false); + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(NewTemplate, EnclosingScope, + /* AddToContext = */ false); + } + + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, + NewClass->getLocation(), + NewTemplate, + /*FIXME:*/NewClass->getLocation()); + Friend->setAccess(AS_public); + CurContext->addDecl(Friend); + } + + if (Invalid) { + NewTemplate->setInvalidDecl(); + NewClass->setInvalidDecl(); + } + return NewTemplate; +} + +/// \brief Diagnose the presence of a default template argument on a +/// template parameter, which is ill-formed in certain contexts. +/// +/// \returns true if the default template argument should be dropped. +static bool DiagnoseDefaultTemplateArgument(Sema &S, + Sema::TemplateParamListContext TPC, + SourceLocation ParamLoc, + SourceRange DefArgRange) { + switch (TPC) { + case Sema::TPC_ClassTemplate: + case Sema::TPC_TypeAliasTemplate: + return false; + + case Sema::TPC_FunctionTemplate: + case Sema::TPC_FriendFunctionTemplateDefinition: + // C++ [temp.param]p9: + // A default template-argument shall not be specified in a + // function template declaration or a function template + // definition [...] + // If a friend function template declaration specifies a default + // template-argument, that declaration shall be a definition and shall be + // the only declaration of the function template in the translation unit. + // (C++98/03 doesn't have this wording; see DR226). + if (!S.getLangOptions().CPlusPlus0x) + S.Diag(ParamLoc, + diag::ext_template_parameter_default_in_function_template) + << DefArgRange; + return false; + + case Sema::TPC_ClassTemplateMember: + // C++0x [temp.param]p9: + // A default template-argument shall not be specified in the + // template-parameter-lists of the definition of a member of a + // class template that appears outside of the member's class. + S.Diag(ParamLoc, diag::err_template_parameter_default_template_member) + << DefArgRange; + return true; + + case Sema::TPC_FriendFunctionTemplate: + // C++ [temp.param]p9: + // A default template-argument shall not be specified in a + // friend template declaration. + S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template) + << DefArgRange; + return true; + + // FIXME: C++0x [temp.param]p9 allows default template-arguments + // for friend function templates if there is only a single + // declaration (and it is a definition). Strange! + } + + return false; +} + +/// \brief Check for unexpanded parameter packs within the template parameters +/// of a template template parameter, recursively. +static bool DiagnoseUnexpandedParameterPacks(Sema &S, + TemplateTemplateParmDecl *TTP) { + TemplateParameterList *Params = TTP->getTemplateParameters(); + for (unsigned I = 0, N = Params->size(); I != N; ++I) { + NamedDecl *P = Params->getParam(I); + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { + if (S.DiagnoseUnexpandedParameterPack(NTTP->getLocation(), + NTTP->getTypeSourceInfo(), + Sema::UPPC_NonTypeTemplateParameterType)) + return true; + + continue; + } + + if (TemplateTemplateParmDecl *InnerTTP + = dyn_cast<TemplateTemplateParmDecl>(P)) + if (DiagnoseUnexpandedParameterPacks(S, InnerTTP)) + return true; + } + + return false; +} + +/// \brief Checks the validity of a template parameter list, possibly +/// considering the template parameter list from a previous +/// declaration. +/// +/// If an "old" template parameter list is provided, it must be +/// equivalent (per TemplateParameterListsAreEqual) to the "new" +/// template parameter list. +/// +/// \param NewParams Template parameter list for a new template +/// declaration. This template parameter list will be updated with any +/// default arguments that are carried through from the previous +/// template parameter list. +/// +/// \param OldParams If provided, template parameter list from a +/// previous declaration of the same template. Default template +/// arguments will be merged from the old template parameter list to +/// the new template parameter list. +/// +/// \param TPC Describes the context in which we are checking the given +/// template parameter list. +/// +/// \returns true if an error occurred, false otherwise. +bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, + TemplateParameterList *OldParams, + TemplateParamListContext TPC) { + bool Invalid = false; + + // C++ [temp.param]p10: + // The set of default template-arguments available for use with a + // template declaration or definition is obtained by merging the + // default arguments from the definition (if in scope) and all + // declarations in scope in the same way default function + // arguments are (8.3.6). + bool SawDefaultArgument = false; + SourceLocation PreviousDefaultArgLoc; + + bool SawParameterPack = false; + SourceLocation ParameterPackLoc; + + // Dummy initialization to avoid warnings. + TemplateParameterList::iterator OldParam = NewParams->end(); + if (OldParams) + OldParam = OldParams->begin(); + + bool RemoveDefaultArguments = false; + for (TemplateParameterList::iterator NewParam = NewParams->begin(), + NewParamEnd = NewParams->end(); + NewParam != NewParamEnd; ++NewParam) { + // Variables used to diagnose redundant default arguments + bool RedundantDefaultArg = false; + SourceLocation OldDefaultLoc; + SourceLocation NewDefaultLoc; + + // Variables used to diagnose missing default arguments + bool MissingDefaultArg = false; + + // C++0x [temp.param]p11: + // If a template parameter of a primary class template or alias template + // is a template parameter pack, it shall be the last template parameter. + if (SawParameterPack && + (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) { + Diag(ParameterPackLoc, + diag::err_template_param_pack_must_be_last_template_parameter); + Invalid = true; + } + + if (TemplateTypeParmDecl *NewTypeParm + = dyn_cast<TemplateTypeParmDecl>(*NewParam)) { + // Check the presence of a default argument here. + if (NewTypeParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewTypeParm->getLocation(), + NewTypeParm->getDefaultArgumentInfo()->getTypeLoc() + .getSourceRange())) + NewTypeParm->removeDefaultArgument(); + + // Merge default arguments for template type parameters. + TemplateTypeParmDecl *OldTypeParm + = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0; + + if (NewTypeParm->isParameterPack()) { + assert(!NewTypeParm->hasDefaultArgument() && + "Parameter packs can't have a default argument!"); + SawParameterPack = true; + ParameterPackLoc = NewTypeParm->getLocation(); + } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && + NewTypeParm->hasDefaultArgument()) { + OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); + NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc(); + SawDefaultArgument = true; + RedundantDefaultArg = true; + PreviousDefaultArgLoc = NewDefaultLoc; + } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) { + // Merge the default argument from the old declaration to the + // new declaration. + SawDefaultArgument = true; + NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(), + true); + PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc(); + } else if (NewTypeParm->hasDefaultArgument()) { + SawDefaultArgument = true; + PreviousDefaultArgLoc = NewTypeParm->getDefaultArgumentLoc(); + } else if (SawDefaultArgument) + MissingDefaultArg = true; + } else if (NonTypeTemplateParmDecl *NewNonTypeParm + = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) { + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(NewNonTypeParm->getLocation(), + NewNonTypeParm->getTypeSourceInfo(), + UPPC_NonTypeTemplateParameterType)) { + Invalid = true; + continue; + } + + // Check the presence of a default argument here. + if (NewNonTypeParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewNonTypeParm->getLocation(), + NewNonTypeParm->getDefaultArgument()->getSourceRange())) { + NewNonTypeParm->removeDefaultArgument(); + } + + // Merge default arguments for non-type template parameters + NonTypeTemplateParmDecl *OldNonTypeParm + = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0; + if (NewNonTypeParm->isParameterPack()) { + assert(!NewNonTypeParm->hasDefaultArgument() && + "Parameter packs can't have a default argument!"); + SawParameterPack = true; + ParameterPackLoc = NewNonTypeParm->getLocation(); + } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && + NewNonTypeParm->hasDefaultArgument()) { + OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); + NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc(); + SawDefaultArgument = true; + RedundantDefaultArg = true; + PreviousDefaultArgLoc = NewDefaultLoc; + } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) { + // Merge the default argument from the old declaration to the + // new declaration. + SawDefaultArgument = true; + // FIXME: We need to create a new kind of "default argument" + // expression that points to a previous non-type template + // parameter. + NewNonTypeParm->setDefaultArgument( + OldNonTypeParm->getDefaultArgument(), + /*Inherited=*/ true); + PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc(); + } else if (NewNonTypeParm->hasDefaultArgument()) { + SawDefaultArgument = true; + PreviousDefaultArgLoc = NewNonTypeParm->getDefaultArgumentLoc(); + } else if (SawDefaultArgument) + MissingDefaultArg = true; + } else { + // Check the presence of a default argument here. + TemplateTemplateParmDecl *NewTemplateParm + = cast<TemplateTemplateParmDecl>(*NewParam); + + // Check for unexpanded parameter packs, recursively. + if (DiagnoseUnexpandedParameterPacks(*this, NewTemplateParm)) { + Invalid = true; + continue; + } + + if (NewTemplateParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewTemplateParm->getLocation(), + NewTemplateParm->getDefaultArgument().getSourceRange())) + NewTemplateParm->removeDefaultArgument(); + + // Merge default arguments for template template parameters + TemplateTemplateParmDecl *OldTemplateParm + = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0; + if (NewTemplateParm->isParameterPack()) { + assert(!NewTemplateParm->hasDefaultArgument() && + "Parameter packs can't have a default argument!"); + SawParameterPack = true; + ParameterPackLoc = NewTemplateParm->getLocation(); + } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && + NewTemplateParm->hasDefaultArgument()) { + OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); + NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation(); + SawDefaultArgument = true; + RedundantDefaultArg = true; + PreviousDefaultArgLoc = NewDefaultLoc; + } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) { + // Merge the default argument from the old declaration to the + // new declaration. + SawDefaultArgument = true; + // FIXME: We need to create a new kind of "default argument" expression + // that points to a previous template template parameter. + NewTemplateParm->setDefaultArgument( + OldTemplateParm->getDefaultArgument(), + /*Inherited=*/ true); + PreviousDefaultArgLoc + = OldTemplateParm->getDefaultArgument().getLocation(); + } else if (NewTemplateParm->hasDefaultArgument()) { + SawDefaultArgument = true; + PreviousDefaultArgLoc + = NewTemplateParm->getDefaultArgument().getLocation(); + } else if (SawDefaultArgument) + MissingDefaultArg = true; + } + + if (RedundantDefaultArg) { + // C++ [temp.param]p12: + // A template-parameter shall not be given default arguments + // by two different declarations in the same scope. + Diag(NewDefaultLoc, diag::err_template_param_default_arg_redefinition); + Diag(OldDefaultLoc, diag::note_template_param_prev_default_arg); + Invalid = true; + } else if (MissingDefaultArg && TPC != TPC_FunctionTemplate) { + // C++ [temp.param]p11: + // If a template-parameter of a class template has a default + // template-argument, each subsequent template-parameter shall either + // have a default template-argument supplied or be a template parameter + // pack. + Diag((*NewParam)->getLocation(), + diag::err_template_param_default_arg_missing); + Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg); + Invalid = true; + RemoveDefaultArguments = true; + } + + // If we have an old template parameter list that we're merging + // in, move on to the next parameter. + if (OldParams) + ++OldParam; + } + + // We were missing some default arguments at the end of the list, so remove + // all of the default arguments. + if (RemoveDefaultArguments) { + for (TemplateParameterList::iterator NewParam = NewParams->begin(), + NewParamEnd = NewParams->end(); + NewParam != NewParamEnd; ++NewParam) { + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*NewParam)) + TTP->removeDefaultArgument(); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) + NTTP->removeDefaultArgument(); + else + cast<TemplateTemplateParmDecl>(*NewParam)->removeDefaultArgument(); + } + } + + return Invalid; +} + +namespace { + +/// A class which looks for a use of a certain level of template +/// parameter. +struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> { + typedef RecursiveASTVisitor<DependencyChecker> super; + + unsigned Depth; + bool Match; + + DependencyChecker(TemplateParameterList *Params) : Match(false) { + NamedDecl *ND = Params->getParam(0); + if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) { + Depth = PD->getDepth(); + } else if (NonTypeTemplateParmDecl *PD = + dyn_cast<NonTypeTemplateParmDecl>(ND)) { + Depth = PD->getDepth(); + } else { + Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth(); + } + } + + bool Matches(unsigned ParmDepth) { + if (ParmDepth >= Depth) { + Match = true; + return true; + } + return false; + } + + bool VisitTemplateTypeParmType(const TemplateTypeParmType *T) { + return !Matches(T->getDepth()); + } + + bool TraverseTemplateName(TemplateName N) { + if (TemplateTemplateParmDecl *PD = + dyn_cast_or_null<TemplateTemplateParmDecl>(N.getAsTemplateDecl())) + if (Matches(PD->getDepth())) return false; + return super::TraverseTemplateName(N); + } + + bool VisitDeclRefExpr(DeclRefExpr *E) { + if (NonTypeTemplateParmDecl *PD = + dyn_cast<NonTypeTemplateParmDecl>(E->getDecl())) { + if (PD->getDepth() == Depth) { + Match = true; + return false; + } + } + return super::VisitDeclRefExpr(E); + } + + bool TraverseInjectedClassNameType(const InjectedClassNameType *T) { + return TraverseType(T->getInjectedSpecializationType()); + } +}; +} + +/// Determines whether a given type depends on the given parameter +/// list. +static bool +DependsOnTemplateParameters(QualType T, TemplateParameterList *Params) { + DependencyChecker Checker(Params); + Checker.TraverseType(T); + return Checker.Match; +} + +// Find the source range corresponding to the named type in the given +// nested-name-specifier, if any. +static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, + QualType T, + const CXXScopeSpec &SS) { + NestedNameSpecifierLoc NNSLoc(SS.getScopeRep(), SS.location_data()); + while (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier()) { + if (const Type *CurType = NNS->getAsType()) { + if (Context.hasSameUnqualifiedType(T, QualType(CurType, 0))) + return NNSLoc.getTypeLoc().getSourceRange(); + } else + break; + + NNSLoc = NNSLoc.getPrefix(); + } + + return SourceRange(); +} + +/// \brief Match the given template parameter lists to the given scope +/// specifier, returning the template parameter list that applies to the +/// name. +/// +/// \param DeclStartLoc the start of the declaration that has a scope +/// specifier or a template parameter list. +/// +/// \param DeclLoc The location of the declaration itself. +/// +/// \param SS the scope specifier that will be matched to the given template +/// parameter lists. This scope specifier precedes a qualified name that is +/// being declared. +/// +/// \param ParamLists the template parameter lists, from the outermost to the +/// innermost template parameter lists. +/// +/// \param NumParamLists the number of template parameter lists in ParamLists. +/// +/// \param IsFriend Whether to apply the slightly different rules for +/// matching template parameters to scope specifiers in friend +/// declarations. +/// +/// \param IsExplicitSpecialization will be set true if the entity being +/// declared is an explicit specialization, false otherwise. +/// +/// \returns the template parameter list, if any, that corresponds to the +/// name that is preceded by the scope specifier @p SS. This template +/// parameter list may have template parameters (if we're declaring a +/// template) or may have no template parameters (if we're declaring a +/// template specialization), or may be NULL (if what we're declaring isn't +/// itself a template). +TemplateParameterList * +Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, + SourceLocation DeclLoc, + const CXXScopeSpec &SS, + TemplateParameterList **ParamLists, + unsigned NumParamLists, + bool IsFriend, + bool &IsExplicitSpecialization, + bool &Invalid) { + IsExplicitSpecialization = false; + Invalid = false; + + // The sequence of nested types to which we will match up the template + // parameter lists. We first build this list by starting with the type named + // by the nested-name-specifier and walking out until we run out of types. + llvm::SmallVector<QualType, 4> NestedTypes; + QualType T; + if (SS.getScopeRep()) { + if (CXXRecordDecl *Record + = dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS, true))) + T = Context.getTypeDeclType(Record); + else + T = QualType(SS.getScopeRep()->getAsType(), 0); + } + + // If we found an explicit specialization that prevents us from needing + // 'template<>' headers, this will be set to the location of that + // explicit specialization. + SourceLocation ExplicitSpecLoc; + + while (!T.isNull()) { + NestedTypes.push_back(T); + + // Retrieve the parent of a record type. + if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) { + // If this type is an explicit specialization, we're done. + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Record)) { + if (!isa<ClassTemplatePartialSpecializationDecl>(Spec) && + Spec->getSpecializationKind() == TSK_ExplicitSpecialization) { + ExplicitSpecLoc = Spec->getLocation(); + break; + } + } else if (Record->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) { + ExplicitSpecLoc = Record->getLocation(); + break; + } + + if (TypeDecl *Parent = dyn_cast<TypeDecl>(Record->getParent())) + T = Context.getTypeDeclType(Parent); + else + T = QualType(); + continue; + } + + if (const TemplateSpecializationType *TST + = T->getAs<TemplateSpecializationType>()) { + if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) { + if (TypeDecl *Parent = dyn_cast<TypeDecl>(Template->getDeclContext())) + T = Context.getTypeDeclType(Parent); + else + T = QualType(); + continue; + } + } + + // Look one step prior in a dependent template specialization type. + if (const DependentTemplateSpecializationType *DependentTST + = T->getAs<DependentTemplateSpecializationType>()) { + if (NestedNameSpecifier *NNS = DependentTST->getQualifier()) + T = QualType(NNS->getAsType(), 0); + else + T = QualType(); + continue; + } + + // Look one step prior in a dependent name type. + if (const DependentNameType *DependentName = T->getAs<DependentNameType>()){ + if (NestedNameSpecifier *NNS = DependentName->getQualifier()) + T = QualType(NNS->getAsType(), 0); + else + T = QualType(); + continue; + } + + // Retrieve the parent of an enumeration type. + if (const EnumType *EnumT = T->getAs<EnumType>()) { + // FIXME: Forward-declared enums require a TSK_ExplicitSpecialization + // check here. + EnumDecl *Enum = EnumT->getDecl(); + + // Get to the parent type. + if (TypeDecl *Parent = dyn_cast<TypeDecl>(Enum->getParent())) + T = Context.getTypeDeclType(Parent); + else + T = QualType(); + continue; + } + + T = QualType(); + } + // Reverse the nested types list, since we want to traverse from the outermost + // to the innermost while checking template-parameter-lists. + std::reverse(NestedTypes.begin(), NestedTypes.end()); + + // C++0x [temp.expl.spec]p17: + // A member or a member template may be nested within many + // enclosing class templates. In an explicit specialization for + // such a member, the member declaration shall be preceded by a + // template<> for each enclosing class template that is + // explicitly specialized. + bool SawNonEmptyTemplateParameterList = false; + unsigned ParamIdx = 0; + for (unsigned TypeIdx = 0, NumTypes = NestedTypes.size(); TypeIdx != NumTypes; + ++TypeIdx) { + T = NestedTypes[TypeIdx]; + + // Whether we expect a 'template<>' header. + bool NeedEmptyTemplateHeader = false; + + // Whether we expect a template header with parameters. + bool NeedNonemptyTemplateHeader = false; + + // For a dependent type, the set of template parameters that we + // expect to see. + TemplateParameterList *ExpectedTemplateParams = 0; + + // C++0x [temp.expl.spec]p15: + // A member or a member template may be nested within many enclosing + // class templates. In an explicit specialization for such a member, the + // member declaration shall be preceded by a template<> for each + // enclosing class template that is explicitly specialized. + if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) { + if (ClassTemplatePartialSpecializationDecl *Partial + = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { + ExpectedTemplateParams = Partial->getTemplateParameters(); + NeedNonemptyTemplateHeader = true; + } else if (Record->isDependentType()) { + if (Record->getDescribedClassTemplate()) { + ExpectedTemplateParams = Record->getDescribedClassTemplate() + ->getTemplateParameters(); + NeedNonemptyTemplateHeader = true; + } + } else if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Record)) { + // C++0x [temp.expl.spec]p4: + // Members of an explicitly specialized class template are defined + // in the same manner as members of normal classes, and not using + // the template<> syntax. + if (Spec->getSpecializationKind() != TSK_ExplicitSpecialization) + NeedEmptyTemplateHeader = true; + else + continue; + } else if (Record->getTemplateSpecializationKind()) { + if (Record->getTemplateSpecializationKind() + != TSK_ExplicitSpecialization && + TypeIdx == NumTypes - 1) + IsExplicitSpecialization = true; + + continue; + } + } else if (const TemplateSpecializationType *TST + = T->getAs<TemplateSpecializationType>()) { + if (TemplateDecl *Template = TST->getTemplateName().getAsTemplateDecl()) { + ExpectedTemplateParams = Template->getTemplateParameters(); + NeedNonemptyTemplateHeader = true; + } + } else if (T->getAs<DependentTemplateSpecializationType>()) { + // FIXME: We actually could/should check the template arguments here + // against the corresponding template parameter list. + NeedNonemptyTemplateHeader = false; + } + + // C++ [temp.expl.spec]p16: + // In an explicit specialization declaration for a member of a class + // template or a member template that ap- pears in namespace scope, the + // member template and some of its enclosing class templates may remain + // unspecialized, except that the declaration shall not explicitly + // specialize a class member template if its en- closing class templates + // are not explicitly specialized as well. + if (ParamIdx < NumParamLists) { + if (ParamLists[ParamIdx]->size() == 0) { + if (SawNonEmptyTemplateParameterList) { + Diag(DeclLoc, diag::err_specialize_member_of_template) + << ParamLists[ParamIdx]->getSourceRange(); + Invalid = true; + IsExplicitSpecialization = false; + return 0; + } + } else + SawNonEmptyTemplateParameterList = true; + } + + if (NeedEmptyTemplateHeader) { + // If we're on the last of the types, and we need a 'template<>' header + // here, then it's an explicit specialization. + if (TypeIdx == NumTypes - 1) + IsExplicitSpecialization = true; + + if (ParamIdx < NumParamLists) { + if (ParamLists[ParamIdx]->size() > 0) { + // The header has template parameters when it shouldn't. Complain. + Diag(ParamLists[ParamIdx]->getTemplateLoc(), + diag::err_template_param_list_matches_nontemplate) + << T + << SourceRange(ParamLists[ParamIdx]->getLAngleLoc(), + ParamLists[ParamIdx]->getRAngleLoc()) + << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); + Invalid = true; + return 0; + } + + // Consume this template header. + ++ParamIdx; + continue; + } + + if (!IsFriend) { + // We don't have a template header, but we should. + SourceLocation ExpectedTemplateLoc; + if (NumParamLists > 0) + ExpectedTemplateLoc = ParamLists[0]->getTemplateLoc(); + else + ExpectedTemplateLoc = DeclStartLoc; + + Diag(DeclLoc, diag::err_template_spec_needs_header) + << getRangeOfTypeInNestedNameSpecifier(Context, T, SS) + << FixItHint::CreateInsertion(ExpectedTemplateLoc, "template<> "); + } + + continue; + } + + if (NeedNonemptyTemplateHeader) { + // In friend declarations we can have template-ids which don't + // depend on the corresponding template parameter lists. But + // assume that empty parameter lists are supposed to match this + // template-id. + if (IsFriend && T->isDependentType()) { + if (ParamIdx < NumParamLists && + DependsOnTemplateParameters(T, ParamLists[ParamIdx])) + ExpectedTemplateParams = 0; + else + continue; + } + + if (ParamIdx < NumParamLists) { + // Check the template parameter list, if we can. + if (ExpectedTemplateParams && + !TemplateParameterListsAreEqual(ParamLists[ParamIdx], + ExpectedTemplateParams, + true, TPL_TemplateMatch)) + Invalid = true; + + if (!Invalid && + CheckTemplateParameterList(ParamLists[ParamIdx], 0, + TPC_ClassTemplateMember)) + Invalid = true; + + ++ParamIdx; + continue; + } + + Diag(DeclLoc, diag::err_template_spec_needs_template_parameters) + << T + << getRangeOfTypeInNestedNameSpecifier(Context, T, SS); + Invalid = true; + continue; + } + } + + // If there were at least as many template-ids as there were template + // parameter lists, then there are no template parameter lists remaining for + // the declaration itself. + if (ParamIdx >= NumParamLists) + return 0; + + // If there were too many template parameter lists, complain about that now. + if (ParamIdx < NumParamLists - 1) { + bool HasAnyExplicitSpecHeader = false; + bool AllExplicitSpecHeaders = true; + for (unsigned I = ParamIdx; I != NumParamLists - 1; ++I) { + if (ParamLists[I]->size() == 0) + HasAnyExplicitSpecHeader = true; + else + AllExplicitSpecHeaders = false; + } + + Diag(ParamLists[ParamIdx]->getTemplateLoc(), + AllExplicitSpecHeaders? diag::warn_template_spec_extra_headers + : diag::err_template_spec_extra_headers) + << SourceRange(ParamLists[ParamIdx]->getTemplateLoc(), + ParamLists[NumParamLists - 2]->getRAngleLoc()); + + // If there was a specialization somewhere, such that 'template<>' is + // not required, and there were any 'template<>' headers, note where the + // specialization occurred. + if (ExplicitSpecLoc.isValid() && HasAnyExplicitSpecHeader) + Diag(ExplicitSpecLoc, + diag::note_explicit_template_spec_does_not_need_header) + << NestedTypes.back(); + + // We have a template parameter list with no corresponding scope, which + // means that the resulting template declaration can't be instantiated + // properly (we'll end up with dependent nodes when we shouldn't). + if (!AllExplicitSpecHeaders) + Invalid = true; + } + + // C++ [temp.expl.spec]p16: + // In an explicit specialization declaration for a member of a class + // template or a member template that ap- pears in namespace scope, the + // member template and some of its enclosing class templates may remain + // unspecialized, except that the declaration shall not explicitly + // specialize a class member template if its en- closing class templates + // are not explicitly specialized as well. + if (ParamLists[NumParamLists - 1]->size() == 0 && + SawNonEmptyTemplateParameterList) { + Diag(DeclLoc, diag::err_specialize_member_of_template) + << ParamLists[ParamIdx]->getSourceRange(); + Invalid = true; + IsExplicitSpecialization = false; + return 0; + } + + // Return the last template parameter list, which corresponds to the + // entity being declared. + return ParamLists[NumParamLists - 1]; +} + +void Sema::NoteAllFoundTemplates(TemplateName Name) { + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + Diag(Template->getLocation(), diag::note_template_declared_here) + << (isa<FunctionTemplateDecl>(Template)? 0 + : isa<ClassTemplateDecl>(Template)? 1 + : isa<TypeAliasTemplateDecl>(Template)? 2 + : 3) + << Template->getDeclName(); + return; + } + + if (OverloadedTemplateStorage *OST = Name.getAsOverloadedTemplate()) { + for (OverloadedTemplateStorage::iterator I = OST->begin(), + IEnd = OST->end(); + I != IEnd; ++I) + Diag((*I)->getLocation(), diag::note_template_declared_here) + << 0 << (*I)->getDeclName(); + + return; + } +} + + +QualType Sema::CheckTemplateIdType(TemplateName Name, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs) { + DependentTemplateName *DTN = Name.getAsDependentTemplateName(); + if (DTN && DTN->isIdentifier()) + // When building a template-id where the template-name is dependent, + // assume the template is a type template. Either our assumption is + // correct, or the code is ill-formed and will be diagnosed when the + // dependent name is substituted. + return Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + TemplateDecl *Template = Name.getAsTemplateDecl(); + if (!Template || isa<FunctionTemplateDecl>(Template)) { + // We might have a substituted template template parameter pack. If so, + // build a template specialization type for it. + if (Name.getAsSubstTemplateTemplateParmPack()) + return Context.getTemplateSpecializationType(Name, TemplateArgs); + + Diag(TemplateLoc, diag::err_template_id_not_a_type) + << Name; + NoteAllFoundTemplates(Name); + return QualType(); + } + + // Check that the template argument list is well-formed for this + // template. + llvm::SmallVector<TemplateArgument, 4> Converted; + if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, + false, Converted)) + return QualType(); + + assert((Converted.size() == Template->getTemplateParameters()->size()) && + "Converted template argument list is too short!"); + + QualType CanonType; + + if (TypeAliasTemplateDecl *AliasTemplate + = dyn_cast<TypeAliasTemplateDecl>(Template)) { + // Find the canonical type for this type alias template specialization. + TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl(); + if (Pattern->isInvalidDecl()) + return QualType(); + + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + + // Only substitute for the innermost template argument list. + MultiLevelTemplateArgumentList TemplateArgLists; + TemplateArgLists.addOuterTemplateArguments(&TemplateArgs); + unsigned Depth = AliasTemplate->getTemplateParameters()->getDepth(); + for (unsigned I = 0; I < Depth; ++I) + TemplateArgLists.addOuterTemplateArguments(0, 0); + + InstantiatingTemplate Inst(*this, TemplateLoc, Template); + CanonType = SubstType(Pattern->getUnderlyingType(), + TemplateArgLists, AliasTemplate->getLocation(), + AliasTemplate->getDeclName()); + if (CanonType.isNull()) + return QualType(); + } else if (Name.isDependent() || + TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs)) { + // This class template specialization is a dependent + // type. Therefore, its canonical type is another class template + // specialization type that contains all of the converted + // arguments in canonical form. This ensures that, e.g., A<T> and + // A<T, T> have identical types when A is declared as: + // + // template<typename T, typename U = T> struct A; + TemplateName CanonName = Context.getCanonicalTemplateName(Name); + CanonType = Context.getTemplateSpecializationType(CanonName, + Converted.data(), + Converted.size()); + + // FIXME: CanonType is not actually the canonical type, and unfortunately + // it is a TemplateSpecializationType that we will never use again. + // In the future, we need to teach getTemplateSpecializationType to only + // build the canonical type and return that to us. + CanonType = Context.getCanonicalType(CanonType); + + // This might work out to be a current instantiation, in which + // case the canonical type needs to be the InjectedClassNameType. + // + // TODO: in theory this could be a simple hashtable lookup; most + // changes to CurContext don't change the set of current + // instantiations. + if (isa<ClassTemplateDecl>(Template)) { + for (DeclContext *Ctx = CurContext; Ctx; Ctx = Ctx->getLookupParent()) { + // If we get out to a namespace, we're done. + if (Ctx->isFileContext()) break; + + // If this isn't a record, keep looking. + CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx); + if (!Record) continue; + + // Look for one of the two cases with InjectedClassNameTypes + // and check whether it's the same template. + if (!isa<ClassTemplatePartialSpecializationDecl>(Record) && + !Record->getDescribedClassTemplate()) + continue; + + // Fetch the injected class name type and check whether its + // injected type is equal to the type we just built. + QualType ICNT = Context.getTypeDeclType(Record); + QualType Injected = cast<InjectedClassNameType>(ICNT) + ->getInjectedSpecializationType(); + + if (CanonType != Injected->getCanonicalTypeInternal()) + continue; + + // If so, the canonical type of this TST is the injected + // class name type of the record we just found. + assert(ICNT.isCanonical()); + CanonType = ICNT; + break; + } + } + } else if (ClassTemplateDecl *ClassTemplate + = dyn_cast<ClassTemplateDecl>(Template)) { + // Find the class template specialization declaration that + // corresponds to these arguments. + void *InsertPos = 0; + ClassTemplateSpecializationDecl *Decl + = ClassTemplate->findSpecialization(Converted.data(), Converted.size(), + InsertPos); + if (!Decl) { + // This is the first time we have referenced this class template + // specialization. Create the canonical declaration and add it to + // the set of specializations. + Decl = ClassTemplateSpecializationDecl::Create(Context, + ClassTemplate->getTemplatedDecl()->getTagKind(), + ClassTemplate->getDeclContext(), + ClassTemplate->getLocation(), + ClassTemplate->getLocation(), + ClassTemplate, + Converted.data(), + Converted.size(), 0); + ClassTemplate->AddSpecialization(Decl, InsertPos); + Decl->setLexicalDeclContext(CurContext); + } + + CanonType = Context.getTypeDeclType(Decl); + assert(isa<RecordType>(CanonType) && + "type of non-dependent specialization is not a RecordType"); + } + + // Build the fully-sugared type for this class template + // specialization, which refers back to the class template + // specialization we created or found. + return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); +} + +TypeResult +Sema::ActOnTemplateIdType(CXXScopeSpec &SS, + TemplateTy TemplateD, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { + if (SS.isInvalid()) + return true; + + TemplateName Template = TemplateD.getAsVal<TemplateName>(); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType T = Context.getDependentTemplateSpecializationType(ETK_None, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Build type-source information. + TypeLocBuilder TLB; + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setKeywordLoc(SourceLocation()); + SpecTL.setNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); + TemplateArgsIn.release(); + + if (Result.isNull()) + return true; + + // Build type-source information. + TypeLocBuilder TLB; + TemplateSpecializationTypeLoc SpecTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) + SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); + + if (SS.isNotEmpty()) { + // Create an elaborated-type-specifier containing the nested-name-specifier. + Result = Context.getElaboratedType(ETK_None, SS.getScopeRep(), Result); + ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); + ElabTL.setKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + } + + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); +} + +TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, + TypeSpecifierType TagSpec, + SourceLocation TagLoc, + CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { + TemplateName Template = TemplateD.getAsVal<TemplateName>(); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + // Determine the tag kind + TagTypeKind TagKind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTagTypeKind(TagKind); + + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType T = Context.getDependentTemplateSpecializationType(Keyword, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Build type-source information. + TypeLocBuilder TLB; + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setKeywordLoc(TagLoc); + SpecTL.setNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + for (unsigned I = 0, N = SpecTL.getNumArgs(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, TLB.getTypeSourceInfo(Context, T)); + } + + if (TypeAliasTemplateDecl *TAT = + dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) { + // C++0x [dcl.type.elab]p2: + // If the identifier resolves to a typedef-name or the simple-template-id + // resolves to an alias template specialization, the + // elaborated-type-specifier is ill-formed. + Diag(TemplateLoc, diag::err_tag_reference_non_tag) << 4; + Diag(TAT->getLocation(), diag::note_declared_at); + } + + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); + if (Result.isNull()) + return TypeResult(); + + // Check the tag kind + if (const RecordType *RT = Result->getAs<RecordType>()) { + RecordDecl *D = RT->getDecl(); + + IdentifierInfo *Id = D->getIdentifier(); + assert(Id && "templated class must have an identifier"); + + if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition, + TagLoc, *Id)) { + Diag(TagLoc, diag::err_use_with_wrong_tag) + << Result + << FixItHint::CreateReplacement(SourceRange(TagLoc), D->getKindName()); + Diag(D->getLocation(), diag::note_previous_use); + } + } + + // Provide source-location information for the template specialization. + TypeLocBuilder TLB; + TemplateSpecializationTypeLoc SpecTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateNameLoc(TemplateLoc); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + for (unsigned i = 0, e = SpecTL.getNumArgs(); i != e; ++i) + SpecTL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); + + // Construct an elaborated type containing the nested-name-specifier (if any) + // and keyword. + Result = Context.getElaboratedType(Keyword, SS.getScopeRep(), Result); + ElaboratedTypeLoc ElabTL = TLB.push<ElaboratedTypeLoc>(Result); + ElabTL.setKeywordLoc(TagLoc); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); +} + +ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs) { + // FIXME: Can we do any checking at this point? I guess we could check the + // template arguments that we have against the template name, if the template + // name refers to a single template. That's not a terribly common case, + // though. + // foo<int> could identify a single function unambiguously + // This approach does NOT work, since f<int>(1); + // gets resolved prior to resorting to overload resolution + // i.e., template<class T> void f(double); + // vs template<class T, class U> void f(U); + + // These should be filtered out by our callers. + assert(!R.empty() && "empty lookup results when building templateid"); + assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); + + // We don't want lookup warnings at this point. + R.suppressDiagnostics(); + + UnresolvedLookupExpr *ULE + = UnresolvedLookupExpr::Create(Context, R.getNamingClass(), + SS.getWithLocInContext(Context), + R.getLookupNameInfo(), + RequiresADL, TemplateArgs, + R.begin(), R.end()); + + return Owned(ULE); +} + +// We actually only call this from template instantiation. +ExprResult +Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo &TemplateArgs) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || + DC->isDependentContext() || + RequireCompleteDeclContext(SS, DC)) + return BuildDependentDeclRefExpr(SS, NameInfo, &TemplateArgs); + + bool MemberOfUnknownSpecialization; + LookupResult R(*this, NameInfo, LookupOrdinaryName); + LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false, + MemberOfUnknownSpecialization); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_non_template) + << NameInfo.getName() << SS.getRange(); + return ExprError(); + } + + if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) { + Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_class_template) + << (NestedNameSpecifier*) SS.getScopeRep() + << NameInfo.getName() << SS.getRange(); + Diag(Temp->getLocation(), diag::note_referenced_class_template); + return ExprError(); + } + + return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs); +} + +/// \brief Form a dependent template name. +/// +/// This action forms a dependent template name given the template +/// name and its (presumably dependent) scope specifier. For +/// example, given "MetaFun::template apply", the scope specifier \p +/// SS will be "MetaFun::", \p TemplateKWLoc contains the location +/// of the "template" keyword, and "apply" is the \p Name. +TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, + SourceLocation TemplateKWLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + ParsedType ObjectType, + bool EnteringContext, + TemplateTy &Result) { + if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() && + !getLangOptions().CPlusPlus0x) + Diag(TemplateKWLoc, diag::ext_template_outside_of_template) + << FixItHint::CreateRemoval(TemplateKWLoc); + + DeclContext *LookupCtx = 0; + if (SS.isSet()) + LookupCtx = computeDeclContext(SS, EnteringContext); + if (!LookupCtx && ObjectType) + LookupCtx = computeDeclContext(ObjectType.get()); + if (LookupCtx) { + // C++0x [temp.names]p5: + // If a name prefixed by the keyword template is not the name of + // a template, the program is ill-formed. [Note: the keyword + // template may not be applied to non-template members of class + // templates. -end note ] [ Note: as is the case with the + // typename prefix, the template prefix is allowed in cases + // where it is not strictly necessary; i.e., when the + // nested-name-specifier or the expression on the left of the -> + // or . is not dependent on a template-parameter, or the use + // does not appear in the scope of a template. -end note] + // + // Note: C++03 was more strict here, because it banned the use of + // the "template" keyword prior to a template-name that was not a + // dependent name. C++ DR468 relaxed this requirement (the + // "template" keyword is now permitted). We follow the C++0x + // rules, even in C++03 mode with a warning, retroactively applying the DR. + bool MemberOfUnknownSpecialization; + TemplateNameKind TNK = isTemplateName(0, SS, TemplateKWLoc.isValid(), Name, + ObjectType, EnteringContext, Result, + MemberOfUnknownSpecialization); + if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && + isa<CXXRecordDecl>(LookupCtx) && + (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() || + cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) { + // This is a dependent template. Handle it below. + } else if (TNK == TNK_Non_template) { + Diag(Name.getSourceRange().getBegin(), + diag::err_template_kw_refers_to_non_template) + << GetNameFromUnqualifiedId(Name).getName() + << Name.getSourceRange() + << TemplateKWLoc; + return TNK_Non_template; + } else { + // We found something; return it. + return TNK; + } + } + + NestedNameSpecifier *Qualifier + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Name.Identifier)); + return TNK_Dependent_template_name; + + case UnqualifiedId::IK_OperatorFunctionId: + Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Name.OperatorFunctionId.Operator)); + return TNK_Dependent_template_name; + + case UnqualifiedId::IK_LiteralOperatorId: + assert(false && "We don't support these; Parse shouldn't have allowed propagation"); + + default: + break; + } + + Diag(Name.getSourceRange().getBegin(), + diag::err_template_kw_refers_to_non_template) + << GetNameFromUnqualifiedId(Name).getName() + << Name.getSourceRange() + << TemplateKWLoc; + return TNK_Non_template; +} + +bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, + const TemplateArgumentLoc &AL, + llvm::SmallVectorImpl<TemplateArgument> &Converted) { + const TemplateArgument &Arg = AL.getArgument(); + + // Check template type parameter. + switch(Arg.getKind()) { + case TemplateArgument::Type: + // C++ [temp.arg.type]p1: + // A template-argument for a template-parameter which is a + // type shall be a type-id. + break; + case TemplateArgument::Template: { + // We have a template type parameter but the template argument + // is a template without any arguments. + SourceRange SR = AL.getSourceRange(); + TemplateName Name = Arg.getAsTemplate(); + Diag(SR.getBegin(), diag::err_template_missing_args) + << Name << SR; + if (TemplateDecl *Decl = Name.getAsTemplateDecl()) + Diag(Decl->getLocation(), diag::note_template_decl_here); + + return true; + } + default: { + // We have a template type parameter but the template argument + // is not a type. + SourceRange SR = AL.getSourceRange(); + Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR; + Diag(Param->getLocation(), diag::note_template_param_here); + + return true; + } + } + + if (CheckTemplateArgument(Param, AL.getTypeSourceInfo())) + return true; + + // Add the converted template type argument. + Converted.push_back( + TemplateArgument(Context.getCanonicalType(Arg.getAsType()))); + return false; +} + +/// \brief Substitute template arguments into the default template argument for +/// the given template type parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the template template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// \returns the substituted template argument, or NULL if an error occurred. +static TypeSourceInfo * +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateTypeParmDecl *Param, + llvm::SmallVectorImpl<TemplateArgument> &Converted) { + TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo(); + + // If the argument type is dependent, instantiate it now based + // on the previously-computed template arguments. + if (ArgType->getType()->isDependentType()) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.data(), + Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); + + ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs, + Param->getDefaultArgumentLoc(), + Param->getDeclName()); + } + + return ArgType; +} + +/// \brief Substitute template arguments into the default template argument for +/// the given non-type template parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the non-type template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static ExprResult +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + NonTypeTemplateParmDecl *Param, + llvm::SmallVectorImpl<TemplateArgument> &Converted) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.data(), + Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); + + return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs); +} + +/// \brief Substitute template arguments into the default template argument for +/// the given template template parameter. +/// +/// \param SemaRef the semantic analysis object for which we are performing +/// the substitution. +/// +/// \param Template the template that we are synthesizing template arguments +/// for. +/// +/// \param TemplateLoc the location of the template name that started the +/// template-id we are checking. +/// +/// \param RAngleLoc the location of the right angle bracket ('>') that +/// terminates the template-id. +/// +/// \param Param the template template parameter whose default we are +/// substituting into. +/// +/// \param Converted the list of template arguments provided for template +/// parameters that precede \p Param in the template parameter list. +/// +/// \param QualifierLoc Will be set to the nested-name-specifier (with +/// source-location information) that precedes the template name. +/// +/// \returns the substituted template argument, or NULL if an error occurred. +static TemplateName +SubstDefaultTemplateArgument(Sema &SemaRef, + TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + TemplateTemplateParmDecl *Param, + llvm::SmallVectorImpl<TemplateArgument> &Converted, + NestedNameSpecifierLoc &QualifierLoc) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + + MultiLevelTemplateArgumentList AllTemplateArgs + = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs); + + Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, + Template, Converted.data(), + Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); + + // Substitute into the nested-name-specifier first, + QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + AllTemplateArgs); + if (!QualifierLoc) + return TemplateName(); + } + + return SemaRef.SubstTemplateName(QualifierLoc, + Param->getDefaultArgument().getArgument().getAsTemplate(), + Param->getDefaultArgument().getTemplateNameLoc(), + AllTemplateArgs); +} + +/// \brief If the given template parameter has a default template +/// argument, substitute into that default template argument and +/// return the corresponding template argument. +TemplateArgumentLoc +Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + Decl *Param, + llvm::SmallVectorImpl<TemplateArgument> &Converted) { + if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (!TypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + TypeSourceInfo *DI = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TypeParm, + Converted); + if (DI) + return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); + + return TemplateArgumentLoc(); + } + + if (NonTypeTemplateParmDecl *NonTypeParm + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (!NonTypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + ExprResult Arg = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NonTypeParm, + Converted); + if (Arg.isInvalid()) + return TemplateArgumentLoc(); + + Expr *ArgE = Arg.takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE); + } + + TemplateTemplateParmDecl *TempTempParm + = cast<TemplateTemplateParmDecl>(Param); + if (!TempTempParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + + NestedNameSpecifierLoc QualifierLoc; + TemplateName TName = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempTempParm, + Converted, + QualifierLoc); + if (TName.isNull()) + return TemplateArgumentLoc(); + + return TemplateArgumentLoc(TemplateArgument(TName), + TempTempParm->getDefaultArgument().getTemplateQualifierLoc(), + TempTempParm->getDefaultArgument().getTemplateNameLoc()); +} + +/// \brief Check that the given template argument corresponds to the given +/// template parameter. +/// +/// \param Param The template parameter against which the argument will be +/// checked. +/// +/// \param Arg The template argument. +/// +/// \param Template The template in which the template argument resides. +/// +/// \param TemplateLoc The location of the template name for the template +/// whose argument list we're matching. +/// +/// \param RAngleLoc The location of the right angle bracket ('>') that closes +/// the template argument list. +/// +/// \param ArgumentPackIndex The index into the argument pack where this +/// argument will be placed. Only valid if the parameter is a parameter pack. +/// +/// \param Converted The checked, converted argument will be added to the +/// end of this small vector. +/// +/// \param CTAK Describes how we arrived at this particular template argument: +/// explicitly written, deduced, etc. +/// +/// \returns true on error, false otherwise. +bool Sema::CheckTemplateArgument(NamedDecl *Param, + const TemplateArgumentLoc &Arg, + NamedDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + unsigned ArgumentPackIndex, + llvm::SmallVectorImpl<TemplateArgument> &Converted, + CheckTemplateArgumentKind CTAK) { + // Check template type parameters. + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) + return CheckTemplateTypeArgument(TTP, Arg, Converted); + + // Check non-type template parameters. + if (NonTypeTemplateParmDecl *NTTP =dyn_cast<NonTypeTemplateParmDecl>(Param)) { + // Do substitution on the type of the non-type template parameter + // with the template arguments we've seen thus far. But if the + // template has a dependent context then we cannot substitute yet. + QualType NTTPType = NTTP->getType(); + if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack()) + NTTPType = NTTP->getExpansionType(ArgumentPackIndex); + + if (NTTPType->isDependentType() && + !isa<TemplateTemplateParmDecl>(Template) && + !Template->getDeclContext()->isDependentContext()) { + // Do substitution on the type of the non-type template parameter. + InstantiatingTemplate Inst(*this, TemplateLoc, Template, + NTTP, Converted.data(), Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); + + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + NTTPType = SubstType(NTTPType, + MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), + NTTP->getDeclName()); + // If that worked, check the non-type template parameter type + // for validity. + if (!NTTPType.isNull()) + NTTPType = CheckNonTypeTemplateParameterType(NTTPType, + NTTP->getLocation()); + if (NTTPType.isNull()) + return true; + } + + switch (Arg.getArgument().getKind()) { + case TemplateArgument::Null: + assert(false && "Should never see a NULL template argument here"); + return true; + + case TemplateArgument::Expression: { + TemplateArgument Result; + ExprResult Res = + CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(), + Result, CTAK); + if (Res.isInvalid()) + return true; + + Converted.push_back(Result); + break; + } + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + // We've already checked this template argument, so just copy + // it to the list of converted arguments. + Converted.push_back(Arg.getArgument()); + break; + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + // We were given a template template argument. It may not be ill-formed; + // see below. + if (DependentTemplateName *DTN + = Arg.getArgument().getAsTemplateOrTemplatePattern() + .getAsDependentTemplateName()) { + // We have a template argument such as \c T::template X, which we + // parsed as a template template argument. However, since we now + // know that we need a non-type template argument, convert this + // template name into an expression. + + DeclarationNameInfo NameInfo(DTN->getIdentifier(), + Arg.getTemplateNameLoc()); + + CXXScopeSpec SS; + SS.Adopt(Arg.getTemplateQualifierLoc()); + ExprResult E = Owned(DependentScopeDeclRefExpr::Create(Context, + SS.getWithLocInContext(Context), + NameInfo)); + + // If we parsed the template argument as a pack expansion, create a + // pack expansion expression. + if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){ + E = ActOnPackExpansion(E.take(), Arg.getTemplateEllipsisLoc()); + if (E.isInvalid()) + return true; + } + + TemplateArgument Result; + E = CheckTemplateArgument(NTTP, NTTPType, E.take(), Result); + if (E.isInvalid()) + return true; + + Converted.push_back(Result); + break; + } + + // We have a template argument that actually does refer to a class + // template, alias template, or template template parameter, and + // therefore cannot be a non-type template argument. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr) + << Arg.getSourceRange(); + + Diag(Param->getLocation(), diag::note_template_param_here); + return true; + + case TemplateArgument::Type: { + // We have a non-type template parameter but the template + // argument is a type. + + // C++ [temp.arg]p2: + // In a template-argument, an ambiguity between a type-id and + // an expression is resolved to a type-id, regardless of the + // form of the corresponding template-parameter. + // + // We warn specifically about this case, since it can be rather + // confusing for users. + QualType T = Arg.getArgument().getAsType(); + SourceRange SR = Arg.getSourceRange(); + if (T->isFunctionType()) + Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) << SR << T; + else + Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR; + Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + case TemplateArgument::Pack: + llvm_unreachable("Caller must expand template argument packs"); + break; + } + + return false; + } + + + // Check template template parameters. + TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param); + + // Substitute into the template parameter list of the template + // template parameter, since previously-supplied template arguments + // may appear within the template template parameter. + { + // Set up a template instantiation context. + LocalInstantiationScope Scope(*this); + InstantiatingTemplate Inst(*this, TemplateLoc, Template, + TempParm, Converted.data(), Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); + + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Converted.data(), Converted.size()); + TempParm = cast_or_null<TemplateTemplateParmDecl>( + SubstDecl(TempParm, CurContext, + MultiLevelTemplateArgumentList(TemplateArgs))); + if (!TempParm) + return true; + } + + switch (Arg.getArgument().getKind()) { + case TemplateArgument::Null: + assert(false && "Should never see a NULL template argument here"); + return true; + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + if (CheckTemplateArgument(TempParm, Arg)) + return true; + + Converted.push_back(Arg.getArgument()); + break; + + case TemplateArgument::Expression: + case TemplateArgument::Type: + // We have a template template parameter but the template + // argument does not refer to a template. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_template) + << getLangOptions().CPlusPlus0x; + return true; + + case TemplateArgument::Declaration: + llvm_unreachable( + "Declaration argument with template template parameter"); + break; + case TemplateArgument::Integral: + llvm_unreachable( + "Integral argument with template template parameter"); + break; + + case TemplateArgument::Pack: + llvm_unreachable("Caller must expand template argument packs"); + break; + } + + return false; +} + +/// \brief Check that the given template argument list is well-formed +/// for specializing the given template. +bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs, + bool PartialTemplateArgs, + llvm::SmallVectorImpl<TemplateArgument> &Converted) { + TemplateParameterList *Params = Template->getTemplateParameters(); + unsigned NumParams = Params->size(); + unsigned NumArgs = TemplateArgs.size(); + bool Invalid = false; + + SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc(); + + bool HasParameterPack = + NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); + + if ((NumArgs > NumParams && !HasParameterPack) || + (NumArgs < Params->getMinRequiredArguments() && + !PartialTemplateArgs)) { + // FIXME: point at either the first arg beyond what we can handle, + // or the '>', depending on whether we have too many or too few + // arguments. + SourceRange Range; + if (NumArgs > NumParams) + Range = SourceRange(TemplateArgs[NumParams].getLocation(), RAngleLoc); + Diag(TemplateLoc, diag::err_template_arg_list_different_arity) + << (NumArgs > NumParams) + << (isa<ClassTemplateDecl>(Template)? 0 : + isa<FunctionTemplateDecl>(Template)? 1 : + isa<TemplateTemplateParmDecl>(Template)? 2 : 3) + << Template << Range; + Diag(Template->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + Invalid = true; + } + + // C++ [temp.arg]p1: + // [...] The type and form of each template-argument specified in + // a template-id shall match the type and form specified for the + // corresponding parameter declared by the template in its + // template-parameter-list. + bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template); + llvm::SmallVector<TemplateArgument, 2> ArgumentPack; + TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + unsigned ArgIdx = 0; + LocalInstantiationScope InstScope(*this, true); + while (Param != ParamEnd) { + if (ArgIdx < NumArgs) { + // If we have an expanded parameter pack, make sure we don't have too + // many arguments. + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { + if (NTTP->isExpandedParameterPack() && + ArgumentPack.size() >= NTTP->getNumExpansionTypes()) { + Diag(TemplateLoc, diag::err_template_arg_list_different_arity) + << true + << (isa<ClassTemplateDecl>(Template)? 0 : + isa<FunctionTemplateDecl>(Template)? 1 : + isa<TemplateTemplateParmDecl>(Template)? 2 : 3) + << Template; + Diag(Template->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; + } + } + + // Check the template argument we were given. + if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template, + TemplateLoc, RAngleLoc, + ArgumentPack.size(), Converted)) + return true; + + if ((*Param)->isTemplateParameterPack()) { + // The template parameter was a template parameter pack, so take the + // deduced argument and place it on the argument pack. Note that we + // stay on the same template parameter so that we can deduce more + // arguments. + ArgumentPack.push_back(Converted.back()); + Converted.pop_back(); + } else { + // Move to the next template parameter. + ++Param; + } + ++ArgIdx; + continue; + } + + // If we're checking a partial template argument list, we're done. + if (PartialTemplateArgs) { + if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty()) + Converted.push_back(TemplateArgument::CreatePackCopy(Context, + ArgumentPack.data(), + ArgumentPack.size())); + + return Invalid; + } + + // If we have a template parameter pack with no more corresponding + // arguments, just break out now and we'll fill in the argument pack below. + if ((*Param)->isTemplateParameterPack()) + break; + + // If our template is a template template parameter that hasn't acquired + // its proper context yet (e.g., because we're using the template template + // parameter in the signature of a function template, before we've built + // the function template itself), don't attempt substitution of default + // template arguments at this point: we don't have enough context to + // do it properly. + if (isTemplateTemplateParameter && + Template->getDeclContext()->isTranslationUnit()) + break; + + // We have a default template argument that we will use. + TemplateArgumentLoc Arg; + + // Retrieve the default template argument from the template + // parameter. For each kind of template parameter, we substitute the + // template arguments provided thus far and any "outer" template arguments + // (when the template parameter was part of a nested template) into + // the default argument. + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { + if (!TTP->hasDefaultArgument()) { + assert(Invalid && "Missing default argument"); + break; + } + + TypeSourceInfo *ArgType = SubstDefaultTemplateArgument(*this, + Template, + TemplateLoc, + RAngleLoc, + TTP, + Converted); + if (!ArgType) + return true; + + Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), + ArgType); + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { + if (!NTTP->hasDefaultArgument()) { + assert(Invalid && "Missing default argument"); + break; + } + + ExprResult E = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NTTP, + Converted); + if (E.isInvalid()) + return true; + + Expr *Ex = E.takeAs<Expr>(); + Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); + } else { + TemplateTemplateParmDecl *TempParm + = cast<TemplateTemplateParmDecl>(*Param); + + if (!TempParm->hasDefaultArgument()) { + assert(Invalid && "Missing default argument"); + break; + } + + NestedNameSpecifierLoc QualifierLoc; + TemplateName Name = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempParm, + Converted, + QualifierLoc); + if (Name.isNull()) + return true; + + Arg = TemplateArgumentLoc(TemplateArgument(Name), QualifierLoc, + TempParm->getDefaultArgument().getTemplateNameLoc()); + } + + // Introduce an instantiation record that describes where we are using + // the default template argument. + InstantiatingTemplate Instantiating(*this, RAngleLoc, Template, *Param, + Converted.data(), Converted.size(), + SourceRange(TemplateLoc, RAngleLoc)); + + // Check the default template argument. + if (CheckTemplateArgument(*Param, Arg, Template, TemplateLoc, + RAngleLoc, 0, Converted)) + return true; + + // Core issue 150 (assumed resolution): if this is a template template + // parameter, keep track of the default template arguments from the + // template definition. + if (isTemplateTemplateParameter) + TemplateArgs.addArgument(Arg); + + // Move to the next template parameter and argument. + ++Param; + ++ArgIdx; + } + + // Form argument packs for each of the parameter packs remaining. + while (Param != ParamEnd) { + // If we're checking a partial list of template arguments, don't fill + // in arguments for non-template parameter packs. + + if ((*Param)->isTemplateParameterPack()) { + if (ArgumentPack.empty()) + Converted.push_back(TemplateArgument(0, 0)); + else { + Converted.push_back(TemplateArgument::CreatePackCopy(Context, + ArgumentPack.data(), + ArgumentPack.size())); + ArgumentPack.clear(); + } + } + + ++Param; + } + + return Invalid; +} + +namespace { + class UnnamedLocalNoLinkageFinder + : public TypeVisitor<UnnamedLocalNoLinkageFinder, bool> + { + Sema &S; + SourceRange SR; + + typedef TypeVisitor<UnnamedLocalNoLinkageFinder, bool> inherited; + + public: + UnnamedLocalNoLinkageFinder(Sema &S, SourceRange SR) : S(S), SR(SR) { } + + bool Visit(QualType T) { + return inherited::Visit(T.getTypePtr()); + } + +#define TYPE(Class, Parent) \ + bool Visit##Class##Type(const Class##Type *); +#define ABSTRACT_TYPE(Class, Parent) \ + bool Visit##Class##Type(const Class##Type *) { return false; } +#define NON_CANONICAL_TYPE(Class, Parent) \ + bool Visit##Class##Type(const Class##Type *) { return false; } +#include "clang/AST/TypeNodes.def" + + bool VisitTagDecl(const TagDecl *Tag); + bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + }; +} + +bool UnnamedLocalNoLinkageFinder::VisitBuiltinType(const BuiltinType*) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitComplexType(const ComplexType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitPointerType(const PointerType* T) { + return Visit(T->getPointeeType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitBlockPointerType( + const BlockPointerType* T) { + return Visit(T->getPointeeType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitLValueReferenceType( + const LValueReferenceType* T) { + return Visit(T->getPointeeType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitRValueReferenceType( + const RValueReferenceType* T) { + return Visit(T->getPointeeType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitMemberPointerType( + const MemberPointerType* T) { + return Visit(T->getPointeeType()) || Visit(QualType(T->getClass(), 0)); +} + +bool UnnamedLocalNoLinkageFinder::VisitConstantArrayType( + const ConstantArrayType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitIncompleteArrayType( + const IncompleteArrayType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitVariableArrayType( + const VariableArrayType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitDependentSizedArrayType( + const DependentSizedArrayType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType( + const DependentSizedExtVectorType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) { + return Visit(T->getElementType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitFunctionProtoType( + const FunctionProtoType* T) { + for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), + AEnd = T->arg_type_end(); + A != AEnd; ++A) { + if (Visit(*A)) + return true; + } + + return Visit(T->getResultType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitFunctionNoProtoType( + const FunctionNoProtoType* T) { + return Visit(T->getResultType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitUnresolvedUsingType( + const UnresolvedUsingType*) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitTypeOfExprType(const TypeOfExprType*) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitTypeOfType(const TypeOfType* T) { + return Visit(T->getUnderlyingType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitDecltypeType(const DecltypeType*) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitUnaryTransformType( + const UnaryTransformType*) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitAutoType(const AutoType *T) { + return Visit(T->getDeducedType()); +} + +bool UnnamedLocalNoLinkageFinder::VisitRecordType(const RecordType* T) { + return VisitTagDecl(T->getDecl()); +} + +bool UnnamedLocalNoLinkageFinder::VisitEnumType(const EnumType* T) { + return VisitTagDecl(T->getDecl()); +} + +bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType( + const TemplateTypeParmType*) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType( + const SubstTemplateTypeParmPackType *) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType( + const TemplateSpecializationType*) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitInjectedClassNameType( + const InjectedClassNameType* T) { + return VisitTagDecl(T->getDecl()); +} + +bool UnnamedLocalNoLinkageFinder::VisitDependentNameType( + const DependentNameType* T) { + return VisitNestedNameSpecifier(T->getQualifier()); +} + +bool UnnamedLocalNoLinkageFinder::VisitDependentTemplateSpecializationType( + const DependentTemplateSpecializationType* T) { + return VisitNestedNameSpecifier(T->getQualifier()); +} + +bool UnnamedLocalNoLinkageFinder::VisitPackExpansionType( + const PackExpansionType* T) { + return Visit(T->getPattern()); +} + +bool UnnamedLocalNoLinkageFinder::VisitObjCObjectType(const ObjCObjectType *) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitObjCInterfaceType( + const ObjCInterfaceType *) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitObjCObjectPointerType( + const ObjCObjectPointerType *) { + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { + if (Tag->getDeclContext()->isFunctionOrMethod()) { + S.Diag(SR.getBegin(), diag::ext_template_arg_local_type) + << S.Context.getTypeDeclType(Tag) << SR; + return true; + } + + if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) { + S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR; + S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here); + return true; + } + + return false; +} + +bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( + NestedNameSpecifier *NNS) { + if (NNS->getPrefix() && VisitNestedNameSpecifier(NNS->getPrefix())) + return true; + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + return false; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + return Visit(QualType(NNS->getAsType(), 0)); + } + return false; +} + + +/// \brief Check a template argument against its corresponding +/// template type parameter. +/// +/// This routine implements the semantics of C++ [temp.arg.type]. It +/// returns true if an error occurred, and false otherwise. +bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, + TypeSourceInfo *ArgInfo) { + assert(ArgInfo && "invalid TypeSourceInfo"); + QualType Arg = ArgInfo->getType(); + SourceRange SR = ArgInfo->getTypeLoc().getSourceRange(); + + if (Arg->isVariablyModifiedType()) { + return Diag(SR.getBegin(), diag::err_variably_modified_template_arg) << Arg; + } else if (Context.hasSameUnqualifiedType(Arg, Context.OverloadTy)) { + return Diag(SR.getBegin(), diag::err_template_arg_overload_type) << SR; + } + + // C++03 [temp.arg.type]p2: + // A local type, a type with no linkage, an unnamed type or a type + // compounded from any of these types shall not be used as a + // template-argument for a template type-parameter. + // + // C++0x allows these, and even in C++03 we allow them as an extension with + // a warning. + if (!LangOpts.CPlusPlus0x && Arg->hasUnnamedOrLocalType()) { + UnnamedLocalNoLinkageFinder Finder(*this, SR); + (void)Finder.Visit(Context.getCanonicalType(Arg)); + } + + return false; +} + +/// \brief Checks whether the given template argument is the address +/// of an object or function according to C++ [temp.arg.nontype]p1. +static bool +CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, + NonTypeTemplateParmDecl *Param, + QualType ParamType, + Expr *ArgIn, + TemplateArgument &Converted) { + bool Invalid = false; + Expr *Arg = ArgIn; + QualType ArgType = Arg->getType(); + + // See through any implicit casts we added to fix the type. + while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) + Arg = Cast->getSubExpr(); + + // C++ [temp.arg.nontype]p1: + // + // A template-argument for a non-type, non-template + // template-parameter shall be one of: [...] + // + // -- the address of an object or function with external + // linkage, including function templates and function + // template-ids but excluding non-static class members, + // expressed as & id-expression where the & is optional if + // the name refers to a function or array, or if the + // corresponding template-parameter is a reference; or + DeclRefExpr *DRE = 0; + + // In C++98/03 mode, give an extension warning on any extra parentheses. + // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773 + bool ExtraParens = false; + while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { + if (!Invalid && !ExtraParens && !S.getLangOptions().CPlusPlus0x) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::ext_template_arg_extra_parens) + << Arg->getSourceRange(); + ExtraParens = true; + } + + Arg = Parens->getSubExpr(); + } + + bool AddressTaken = false; + SourceLocation AddrOpLoc; + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { + if (UnOp->getOpcode() == UO_AddrOf) { + // Support &__uuidof(class_with_uuid) as a non-type template argument. + // Very common in Microsoft COM headers. + if (S.getLangOptions().Microsoft && + isa<CXXUuidofExpr>(UnOp->getSubExpr())) { + Converted = TemplateArgument(ArgIn); + return false; + } + + DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr()); + AddressTaken = true; + AddrOpLoc = UnOp->getOperatorLoc(); + } + } else { + if (S.getLangOptions().Microsoft && isa<CXXUuidofExpr>(Arg)) { + Converted = TemplateArgument(ArgIn); + return false; + } + DRE = dyn_cast<DeclRefExpr>(Arg); + } + if (!DRE) { + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + // Stop checking the precise nature of the argument if it is value dependent, + // it should be checked when instantiated. + if (Arg->isValueDependent()) { + Converted = TemplateArgument(ArgIn); + return false; + } + + if (!isa<ValueDecl>(DRE->getDecl())) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_object_or_func_form) + << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + NamedDecl *Entity = 0; + + // Cannot refer to non-static data members + if (FieldDecl *Field = dyn_cast<FieldDecl>(DRE->getDecl())) { + S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_field) + << Field << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + // Cannot refer to non-static member functions + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl())) + if (!Method->isStatic()) { + S.Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_method) + << Method << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + // Functions must have external linkage. + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) { + if (!isExternalLinkage(Func->getLinkage())) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_function_not_extern) + << Func << Arg->getSourceRange(); + S.Diag(Func->getLocation(), diag::note_template_arg_internal_object) + << true; + return true; + } + + // Okay: we've named a function with external linkage. + Entity = Func; + + // If the template parameter has pointer type, the function decays. + if (ParamType->isPointerType() && !AddressTaken) + ArgType = S.Context.getPointerType(Func->getType()); + else if (AddressTaken && ParamType->isReferenceType()) { + // If we originally had an address-of operator, but the + // parameter has reference type, complain and (if things look + // like they will work) drop the address-of operator. + if (!S.Context.hasSameUnqualifiedType(Func->getType(), + ParamType.getNonReferenceType())) { + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType; + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType + << FixItHint::CreateRemoval(AddrOpLoc); + S.Diag(Param->getLocation(), diag::note_template_param_here); + + ArgType = Func->getType(); + } + } else if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { + if (!isExternalLinkage(Var->getLinkage())) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_object_not_extern) + << Var << Arg->getSourceRange(); + S.Diag(Var->getLocation(), diag::note_template_arg_internal_object) + << true; + return true; + } + + // A value of reference type is not an object. + if (Var->getType()->isReferenceType()) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_reference_var) + << Var->getType() << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + // Okay: we've named an object with external linkage + Entity = Var; + + // If the template parameter has pointer type, we must have taken + // the address of this object. + if (ParamType->isReferenceType()) { + if (AddressTaken) { + // If we originally had an address-of operator, but the + // parameter has reference type, complain and (if things look + // like they will work) drop the address-of operator. + if (!S.Context.hasSameUnqualifiedType(Var->getType(), + ParamType.getNonReferenceType())) { + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType; + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + S.Diag(AddrOpLoc, diag::err_template_arg_address_of_non_pointer) + << ParamType + << FixItHint::CreateRemoval(AddrOpLoc); + S.Diag(Param->getLocation(), diag::note_template_param_here); + + ArgType = Var->getType(); + } + } else if (!AddressTaken && ParamType->isPointerType()) { + if (Var->getType()->isArrayType()) { + // Array-to-pointer decay. + ArgType = S.Context.getArrayDecayedType(Var->getType()); + } else { + // If the template parameter has pointer type but the address of + // this object was not taken, complain and (possibly) recover by + // taking the address of the entity. + ArgType = S.Context.getPointerType(Var->getType()); + if (!S.Context.hasSameUnqualifiedType(ArgType, ParamType)) { + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of) + << ParamType; + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_address_of) + << ParamType + << FixItHint::CreateInsertion(Arg->getLocStart(), "&"); + + S.Diag(Param->getLocation(), diag::note_template_param_here); + } + } + } else { + // We found something else, but we don't know specifically what it is. + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_object_or_func) + << Arg->getSourceRange(); + S.Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); + return true; + } + + if (ParamType->isPointerType() && + !ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType() && + S.IsQualificationConversion(ArgType, ParamType, false)) { + // For pointer-to-object types, qualification conversions are + // permitted. + } else { + if (const ReferenceType *ParamRef = ParamType->getAs<ReferenceType>()) { + if (!ParamRef->getPointeeType()->isFunctionType()) { + // C++ [temp.arg.nontype]p5b3: + // For a non-type template-parameter of type reference to + // object, no conversions apply. The type referred to by the + // reference may be more cv-qualified than the (otherwise + // identical) type of the template- argument. The + // template-parameter is bound directly to the + // template-argument, which shall be an lvalue. + + // FIXME: Other qualifiers? + unsigned ParamQuals = ParamRef->getPointeeType().getCVRQualifiers(); + unsigned ArgQuals = ArgType.getCVRQualifiers(); + + if ((ParamQuals | ArgQuals) != ParamQuals) { + S.Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_ref_bind_ignores_quals) + << ParamType << Arg->getType() + << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + } + + // At this point, the template argument refers to an object or + // function with external linkage. We now need to check whether the + // argument and parameter types are compatible. + if (!S.Context.hasSameUnqualifiedType(ArgType, + ParamType.getNonReferenceType())) { + // We can't perform this conversion or binding. + if (ParamType->isReferenceType()) + S.Diag(Arg->getLocStart(), diag::err_template_arg_no_ref_bind) + << ParamType << Arg->getType() << Arg->getSourceRange(); + else + S.Diag(Arg->getLocStart(), diag::err_template_arg_not_convertible) + << Arg->getType() << ParamType << Arg->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + + // Create the template argument. + Converted = TemplateArgument(Entity->getCanonicalDecl()); + S.MarkDeclarationReferenced(Arg->getLocStart(), Entity); + return false; +} + +/// \brief Checks whether the given template argument is a pointer to +/// member constant according to C++ [temp.arg.nontype]p1. +bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, + TemplateArgument &Converted) { + bool Invalid = false; + + // See through any implicit casts we added to fix the type. + while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) + Arg = Cast->getSubExpr(); + + // C++ [temp.arg.nontype]p1: + // + // A template-argument for a non-type, non-template + // template-parameter shall be one of: [...] + // + // -- a pointer to member expressed as described in 5.3.1. + DeclRefExpr *DRE = 0; + + // In C++98/03 mode, give an extension warning on any extra parentheses. + // See http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#773 + bool ExtraParens = false; + while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { + if (!Invalid && !ExtraParens && !getLangOptions().CPlusPlus0x) { + Diag(Arg->getSourceRange().getBegin(), + diag::ext_template_arg_extra_parens) + << Arg->getSourceRange(); + ExtraParens = true; + } + + Arg = Parens->getSubExpr(); + } + + // A pointer-to-member constant written &Class::member. + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) { + if (UnOp->getOpcode() == UO_AddrOf) { + DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr()); + if (DRE && !DRE->getQualifier()) + DRE = 0; + } + } + // A constant of pointer-to-member type. + else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) { + if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) { + if (VD->getType()->isMemberPointerType()) { + if (isa<NonTypeTemplateParmDecl>(VD) || + (isa<VarDecl>(VD) && + Context.getCanonicalType(VD->getType()).isConstQualified())) { + if (Arg->isTypeDependent() || Arg->isValueDependent()) + Converted = TemplateArgument(Arg); + else + Converted = TemplateArgument(VD->getCanonicalDecl()); + return Invalid; + } + } + } + + DRE = 0; + } + + if (!DRE) + return Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_pointer_to_member_form) + << Arg->getSourceRange(); + + if (isa<FieldDecl>(DRE->getDecl()) || isa<CXXMethodDecl>(DRE->getDecl())) { + assert((isa<FieldDecl>(DRE->getDecl()) || + !cast<CXXMethodDecl>(DRE->getDecl())->isStatic()) && + "Only non-static member pointers can make it here"); + + // Okay: this is the address of a non-static member, and therefore + // a member pointer constant. + if (Arg->isTypeDependent() || Arg->isValueDependent()) + Converted = TemplateArgument(Arg); + else + Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl()); + return Invalid; + } + + // We found something else, but we don't know specifically what it is. + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_pointer_to_member_form) + << Arg->getSourceRange(); + Diag(DRE->getDecl()->getLocation(), + diag::note_template_arg_refers_here); + return true; +} + +/// \brief Check a template argument against its corresponding +/// non-type template parameter. +/// +/// This routine implements the semantics of C++ [temp.arg.nontype]. +/// If an error occurred, it returns ExprError(); otherwise, it +/// returns the converted template argument. \p +/// InstantiatedParamType is the type of the non-type template +/// parameter after it has been instantiated. +ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, + QualType InstantiatedParamType, Expr *Arg, + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK) { + SourceLocation StartLoc = Arg->getSourceRange().getBegin(); + + // If either the parameter has a dependent type or the argument is + // type-dependent, there's nothing we can check now. + if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) { + // FIXME: Produce a cloned, canonical expression? + Converted = TemplateArgument(Arg); + return Owned(Arg); + } + + // C++ [temp.arg.nontype]p5: + // The following conversions are performed on each expression used + // as a non-type template-argument. If a non-type + // template-argument cannot be converted to the type of the + // corresponding template-parameter then the program is + // ill-formed. + // + // -- for a non-type template-parameter of integral or + // enumeration type, integral promotions (4.5) and integral + // conversions (4.7) are applied. + QualType ParamType = InstantiatedParamType; + QualType ArgType = Arg->getType(); + if (ParamType->isIntegralOrEnumerationType()) { + // C++ [temp.arg.nontype]p1: + // A template-argument for a non-type, non-template + // template-parameter shall be one of: + // + // -- an integral constant-expression of integral or enumeration + // type; or + // -- the name of a non-type template-parameter; or + SourceLocation NonConstantLoc; + llvm::APSInt Value; + if (!ArgType->isIntegralOrEnumerationType()) { + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_integral_or_enumeral) + << ArgType << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + } else if (!Arg->isValueDependent() && + !Arg->isIntegerConstantExpr(Value, Context, &NonConstantLoc)) { + Diag(NonConstantLoc, diag::err_template_arg_not_ice) + << ArgType << Arg->getSourceRange(); + return ExprError(); + } + + // From here on out, all we care about are the unqualified forms + // of the parameter and argument types. + ParamType = ParamType.getUnqualifiedType(); + ArgType = ArgType.getUnqualifiedType(); + + // Try to convert the argument to the parameter's type. + if (Context.hasSameType(ParamType, ArgType)) { + // Okay: no conversion necessary + } else if (CTAK == CTAK_Deduced) { + // C++ [temp.deduct.type]p17: + // If, in the declaration of a function template with a non-type + // template-parameter, the non-type template- parameter is used + // in an expression in the function parameter-list and, if the + // corresponding template-argument is deduced, the + // template-argument type shall match the type of the + // template-parameter exactly, except that a template-argument + // deduced from an array bound may be of any integral type. + Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch) + << ArgType << ParamType; + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + } else if (ParamType->isBooleanType()) { + // This is an integral-to-boolean conversion. + Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean).take(); + } else if (IsIntegralPromotion(Arg, ArgType, ParamType) || + !ParamType->isEnumeralType()) { + // This is an integral promotion or conversion. + Arg = ImpCastExprToType(Arg, ParamType, CK_IntegralCast).take(); + } else { + // We can't perform this conversion. + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_convertible) + << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + } + + // Add the value of this argument to the list of converted + // arguments. We use the bitwidth and signedness of the template + // parameter. + if (Arg->isValueDependent()) { + // The argument is value-dependent. Create a new + // TemplateArgument with the converted expression. + Converted = TemplateArgument(Arg); + return Owned(Arg); + } + + QualType IntegerType = Context.getCanonicalType(ParamType); + if (const EnumType *Enum = IntegerType->getAs<EnumType>()) + IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType()); + + if (ParamType->isBooleanType()) { + // Value must be zero or one. + Value = Value != 0; + unsigned AllowedBits = Context.getTypeSize(IntegerType); + if (Value.getBitWidth() != AllowedBits) + Value = Value.extOrTrunc(AllowedBits); + Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType()); + } else { + llvm::APSInt OldValue = Value; + + // Coerce the template argument's value to the value it will have + // based on the template parameter's type. + unsigned AllowedBits = Context.getTypeSize(IntegerType); + if (Value.getBitWidth() != AllowedBits) + Value = Value.extOrTrunc(AllowedBits); + Value.setIsSigned(IntegerType->isSignedIntegerOrEnumerationType()); + + // Complain if an unsigned parameter received a negative value. + if (IntegerType->isUnsignedIntegerOrEnumerationType() + && (OldValue.isSigned() && OldValue.isNegative())) { + Diag(Arg->getSourceRange().getBegin(), diag::warn_template_arg_negative) + << OldValue.toString(10) << Value.toString(10) << Param->getType() + << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + } + + // Complain if we overflowed the template parameter's type. + unsigned RequiredBits; + if (IntegerType->isUnsignedIntegerOrEnumerationType()) + RequiredBits = OldValue.getActiveBits(); + else if (OldValue.isUnsigned()) + RequiredBits = OldValue.getActiveBits() + 1; + else + RequiredBits = OldValue.getMinSignedBits(); + if (RequiredBits > AllowedBits) { + Diag(Arg->getSourceRange().getBegin(), + diag::warn_template_arg_too_large) + << OldValue.toString(10) << Value.toString(10) << Param->getType() + << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + } + } + + Converted = TemplateArgument(Value, + ParamType->isEnumeralType() ? ParamType + : IntegerType); + return Owned(Arg); + } + + DeclAccessPair FoundResult; // temporary for ResolveOverloadedFunction + + // C++0x [temp.arg.nontype]p5 bullets 2, 4 and 6 permit conversion + // from a template argument of type std::nullptr_t to a non-type + // template parameter of type pointer to object, pointer to + // function, or pointer-to-member, respectively. + if (ArgType->isNullPtrType()) { + if (ParamType->isPointerType() || ParamType->isMemberPointerType()) { + Converted = TemplateArgument((NamedDecl *)0); + return Owned(Arg); + } + + if (ParamType->isNullPtrType()) { + llvm::APSInt Zero(Context.getTypeSize(Context.NullPtrTy), true); + Converted = TemplateArgument(Zero, Context.NullPtrTy); + return Owned(Arg); + } + } + + // Handle pointer-to-function, reference-to-function, and + // pointer-to-member-function all in (roughly) the same way. + if (// -- For a non-type template-parameter of type pointer to + // function, only the function-to-pointer conversion (4.3) is + // applied. If the template-argument represents a set of + // overloaded functions (or a pointer to such), the matching + // function is selected from the set (13.4). + (ParamType->isPointerType() && + ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType()) || + // -- For a non-type template-parameter of type reference to + // function, no conversions apply. If the template-argument + // represents a set of overloaded functions, the matching + // function is selected from the set (13.4). + (ParamType->isReferenceType() && + ParamType->getAs<ReferenceType>()->getPointeeType()->isFunctionType()) || + // -- For a non-type template-parameter of type pointer to + // member function, no conversions apply. If the + // template-argument represents a set of overloaded member + // functions, the matching member function is selected from + // the set (13.4). + (ParamType->isMemberPointerType() && + ParamType->getAs<MemberPointerType>()->getPointeeType() + ->isFunctionType())) { + + if (Arg->getType() == Context.OverloadTy) { + if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, + true, + FoundResult)) { + if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + return ExprError(); + + Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + ArgType = Arg->getType(); + } else + return ExprError(); + } + + if (!ParamType->isMemberPointerType()) { + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); + } + + if (IsQualificationConversion(ArgType, ParamType.getNonReferenceType(), + false)) { + Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take(); + } else if (!Context.hasSameUnqualifiedType(ArgType, + ParamType.getNonReferenceType())) { + // We can't perform this conversion. + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_convertible) + << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + } + + if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + return ExprError(); + return Owned(Arg); + } + + if (ParamType->isPointerType()) { + // -- for a non-type template-parameter of type pointer to + // object, qualification conversions (4.4) and the + // array-to-pointer conversion (4.2) are applied. + // C++0x also allows a value of std::nullptr_t. + assert(ParamType->getPointeeType()->isIncompleteOrObjectType() && + "Only object pointers allowed here"); + + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); + } + + if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) { + // -- For a non-type template-parameter of type reference to + // object, no conversions apply. The type referred to by the + // reference may be more cv-qualified than the (otherwise + // identical) type of the template-argument. The + // template-parameter is bound directly to the + // template-argument, which must be an lvalue. + assert(ParamRefType->getPointeeType()->isIncompleteOrObjectType() && + "Only object references allowed here"); + + if (Arg->getType() == Context.OverloadTy) { + if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, + ParamRefType->getPointeeType(), + true, + FoundResult)) { + if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + return ExprError(); + + Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn); + ArgType = Arg->getType(); + } else + return ExprError(); + } + + if (CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, + ParamType, + Arg, Converted)) + return ExprError(); + return Owned(Arg); + } + + // -- For a non-type template-parameter of type pointer to data + // member, qualification conversions (4.4) are applied. + assert(ParamType->isMemberPointerType() && "Only pointers to members remain"); + + if (Context.hasSameUnqualifiedType(ParamType, ArgType)) { + // Types match exactly: nothing more to do here. + } else if (IsQualificationConversion(ArgType, ParamType, false)) { + Arg = ImpCastExprToType(Arg, ParamType, CK_NoOp, CastCategory(Arg)).take(); + } else { + // We can't perform this conversion. + Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_convertible) + << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); + Diag(Param->getLocation(), diag::note_template_param_here); + return ExprError(); + } + + if (CheckTemplateArgumentPointerToMember(Arg, Converted)) + return ExprError(); + return Owned(Arg); +} + +/// \brief Check a template argument against its corresponding +/// template template parameter. +/// +/// This routine implements the semantics of C++ [temp.arg.template]. +/// It returns true if an error occurred, and false otherwise. +bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, + const TemplateArgumentLoc &Arg) { + TemplateName Name = Arg.getArgument().getAsTemplate(); + TemplateDecl *Template = Name.getAsTemplateDecl(); + if (!Template) { + // Any dependent template name is fine. + assert(Name.isDependent() && "Non-dependent template isn't a declaration?"); + return false; + } + + // C++0x [temp.arg.template]p1: + // A template-argument for a template template-parameter shall be + // the name of a class template or an alias template, expressed as an + // id-expression. When the template-argument names a class template, only + // primary class templates are considered when matching the + // template template argument with the corresponding parameter; + // partial specializations are not considered even if their + // parameter lists match that of the template template parameter. + // + // Note that we also allow template template parameters here, which + // will happen when we are dealing with, e.g., class template + // partial specializations. + if (!isa<ClassTemplateDecl>(Template) && + !isa<TemplateTemplateParmDecl>(Template) && + !isa<TypeAliasTemplateDecl>(Template)) { + assert(isa<FunctionTemplateDecl>(Template) && + "Only function templates are possible here"); + Diag(Arg.getLocation(), diag::err_template_arg_not_class_template); + Diag(Template->getLocation(), diag::note_template_arg_refers_here_func) + << Template; + } + + return !TemplateParameterListsAreEqual(Template->getTemplateParameters(), + Param->getTemplateParameters(), + true, + TPL_TemplateTemplateArgumentMatch, + Arg.getLocation()); +} + +/// \brief Given a non-type template argument that refers to a +/// declaration and the type of its corresponding non-type template +/// parameter, produce an expression that properly refers to that +/// declaration. +ExprResult +Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, + QualType ParamType, + SourceLocation Loc) { + assert(Arg.getKind() == TemplateArgument::Declaration && + "Only declaration template arguments permitted here"); + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); + + if (VD->getDeclContext()->isRecord() && + (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) { + // If the value is a class member, we might have a pointer-to-member. + // Determine whether the non-type template template parameter is of + // pointer-to-member type. If so, we need to build an appropriate + // expression for a pointer-to-member, since a "normal" DeclRefExpr + // would refer to the member itself. + if (ParamType->isMemberPointerType()) { + QualType ClassType + = Context.getTypeDeclType(cast<RecordDecl>(VD->getDeclContext())); + NestedNameSpecifier *Qualifier + = NestedNameSpecifier::Create(Context, 0, false, + ClassType.getTypePtr()); + CXXScopeSpec SS; + SS.MakeTrivial(Context, Qualifier, Loc); + + // The actual value-ness of this is unimportant, but for + // internal consistency's sake, references to instance methods + // are r-values. + ExprValueKind VK = VK_LValue; + if (isa<CXXMethodDecl>(VD) && cast<CXXMethodDecl>(VD)->isInstance()) + VK = VK_RValue; + + ExprResult RefExpr = BuildDeclRefExpr(VD, + VD->getType().getNonReferenceType(), + VK, + Loc, + &SS); + if (RefExpr.isInvalid()) + return ExprError(); + + RefExpr = CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get()); + + // We might need to perform a trailing qualification conversion, since + // the element type on the parameter could be more qualified than the + // element type in the expression we constructed. + if (IsQualificationConversion(((Expr*) RefExpr.get())->getType(), + ParamType.getUnqualifiedType(), false)) + RefExpr = ImpCastExprToType(RefExpr.take(), ParamType.getUnqualifiedType(), CK_NoOp); + + assert(!RefExpr.isInvalid() && + Context.hasSameType(((Expr*) RefExpr.get())->getType(), + ParamType.getUnqualifiedType())); + return move(RefExpr); + } + } + + QualType T = VD->getType().getNonReferenceType(); + if (ParamType->isPointerType()) { + // When the non-type template parameter is a pointer, take the + // address of the declaration. + ExprResult RefExpr = BuildDeclRefExpr(VD, T, VK_LValue, Loc); + if (RefExpr.isInvalid()) + return ExprError(); + + if (T->isFunctionType() || T->isArrayType()) { + // Decay functions and arrays. + RefExpr = DefaultFunctionArrayConversion(RefExpr.take()); + if (RefExpr.isInvalid()) + return ExprError(); + + return move(RefExpr); + } + + // Take the address of everything else + return CreateBuiltinUnaryOp(Loc, UO_AddrOf, RefExpr.get()); + } + + ExprValueKind VK = VK_RValue; + + // If the non-type template parameter has reference type, qualify the + // resulting declaration reference with the extra qualifiers on the + // type that the reference refers to. + if (const ReferenceType *TargetRef = ParamType->getAs<ReferenceType>()) { + VK = VK_LValue; + T = Context.getQualifiedType(T, + TargetRef->getPointeeType().getQualifiers()); + } + + return BuildDeclRefExpr(VD, T, VK, Loc); +} + +/// \brief Construct a new expression that refers to the given +/// integral template argument with the given source-location +/// information. +/// +/// This routine takes care of the mapping from an integral template +/// argument (which may have any integral type) to the appropriate +/// literal value. +ExprResult +Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, + SourceLocation Loc) { + assert(Arg.getKind() == TemplateArgument::Integral && + "Operation is only valid for integral template arguments"); + QualType T = Arg.getIntegralType(); + if (T->isCharType() || T->isWideCharType()) + return Owned(new (Context) CharacterLiteral( + Arg.getAsIntegral()->getZExtValue(), + T->isWideCharType(), T, Loc)); + if (T->isBooleanType()) + return Owned(new (Context) CXXBoolLiteralExpr( + Arg.getAsIntegral()->getBoolValue(), + T, Loc)); + + if (T->isNullPtrType()) + return Owned(new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc)); + + // If this is an enum type that we're instantiating, we need to use an integer + // type the same size as the enumerator. We don't want to build an + // IntegerLiteral with enum type. + QualType BT; + if (const EnumType *ET = T->getAs<EnumType>()) + BT = ET->getDecl()->getIntegerType(); + else + BT = T; + + Expr *E = IntegerLiteral::Create(Context, *Arg.getAsIntegral(), BT, Loc); + if (T->isEnumeralType()) { + // FIXME: This is a hack. We need a better way to handle substituted + // non-type template parameters. + E = CStyleCastExpr::Create(Context, T, VK_RValue, CK_IntegralCast, E, 0, + Context.getTrivialTypeSourceInfo(T, Loc), + Loc, Loc); + } + + return Owned(E); +} + +/// \brief Match two template parameters within template parameter lists. +static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, + bool Complain, + Sema::TemplateParameterListEqualKind Kind, + SourceLocation TemplateArgLoc) { + // Check the actual kind (type, non-type, template). + if (Old->getKind() != New->getKind()) { + if (Complain) { + unsigned NextDiag = diag::err_template_param_different_kind; + if (TemplateArgLoc.isValid()) { + S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_param_different_kind; + } + S.Diag(New->getLocation(), NextDiag) + << (Kind != Sema::TPL_TemplateMatch); + S.Diag(Old->getLocation(), diag::note_template_prev_declaration) + << (Kind != Sema::TPL_TemplateMatch); + } + + return false; + } + + // Check that both are parameter packs are neither are parameter packs. + // However, if we are matching a template template argument to a + // template template parameter, the template template parameter can have + // a parameter pack where the template template argument does not. + if (Old->isTemplateParameterPack() != New->isTemplateParameterPack() && + !(Kind == Sema::TPL_TemplateTemplateArgumentMatch && + Old->isTemplateParameterPack())) { + if (Complain) { + unsigned NextDiag = diag::err_template_parameter_pack_non_pack; + if (TemplateArgLoc.isValid()) { + S.Diag(TemplateArgLoc, + diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_parameter_pack_non_pack; + } + + unsigned ParamKind = isa<TemplateTypeParmDecl>(New)? 0 + : isa<NonTypeTemplateParmDecl>(New)? 1 + : 2; + S.Diag(New->getLocation(), NextDiag) + << ParamKind << New->isParameterPack(); + S.Diag(Old->getLocation(), diag::note_template_parameter_pack_here) + << ParamKind << Old->isParameterPack(); + } + + return false; + } + + // For non-type template parameters, check the type of the parameter. + if (NonTypeTemplateParmDecl *OldNTTP + = dyn_cast<NonTypeTemplateParmDecl>(Old)) { + NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New); + + // If we are matching a template template argument to a template + // template parameter and one of the non-type template parameter types + // is dependent, then we must wait until template instantiation time + // to actually compare the arguments. + if (Kind == Sema::TPL_TemplateTemplateArgumentMatch && + (OldNTTP->getType()->isDependentType() || + NewNTTP->getType()->isDependentType())) + return true; + + if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) { + if (Complain) { + unsigned NextDiag = diag::err_template_nontype_parm_different_type; + if (TemplateArgLoc.isValid()) { + S.Diag(TemplateArgLoc, + diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_nontype_parm_different_type; + } + S.Diag(NewNTTP->getLocation(), NextDiag) + << NewNTTP->getType() + << (Kind != Sema::TPL_TemplateMatch); + S.Diag(OldNTTP->getLocation(), + diag::note_template_nontype_parm_prev_declaration) + << OldNTTP->getType(); + } + + return false; + } + + return true; + } + + // For template template parameters, check the template parameter types. + // The template parameter lists of template template + // parameters must agree. + if (TemplateTemplateParmDecl *OldTTP + = dyn_cast<TemplateTemplateParmDecl>(Old)) { + TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(New); + return S.TemplateParameterListsAreEqual(NewTTP->getTemplateParameters(), + OldTTP->getTemplateParameters(), + Complain, + (Kind == Sema::TPL_TemplateMatch + ? Sema::TPL_TemplateTemplateParmMatch + : Kind), + TemplateArgLoc); + } + + return true; +} + +/// \brief Diagnose a known arity mismatch when comparing template argument +/// lists. +static +void DiagnoseTemplateParameterListArityMismatch(Sema &S, + TemplateParameterList *New, + TemplateParameterList *Old, + Sema::TemplateParameterListEqualKind Kind, + SourceLocation TemplateArgLoc) { + unsigned NextDiag = diag::err_template_param_list_different_arity; + if (TemplateArgLoc.isValid()) { + S.Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_param_list_different_arity; + } + S.Diag(New->getTemplateLoc(), NextDiag) + << (New->size() > Old->size()) + << (Kind != Sema::TPL_TemplateMatch) + << SourceRange(New->getTemplateLoc(), New->getRAngleLoc()); + S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration) + << (Kind != Sema::TPL_TemplateMatch) + << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc()); +} + +/// \brief Determine whether the given template parameter lists are +/// equivalent. +/// +/// \param New The new template parameter list, typically written in the +/// source code as part of a new template declaration. +/// +/// \param Old The old template parameter list, typically found via +/// name lookup of the template declared with this template parameter +/// list. +/// +/// \param Complain If true, this routine will produce a diagnostic if +/// the template parameter lists are not equivalent. +/// +/// \param Kind describes how we are to match the template parameter lists. +/// +/// \param TemplateArgLoc If this source location is valid, then we +/// are actually checking the template parameter list of a template +/// argument (New) against the template parameter list of its +/// corresponding template template parameter (Old). We produce +/// slightly different diagnostics in this scenario. +/// +/// \returns True if the template parameter lists are equal, false +/// otherwise. +bool +Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, + TemplateParameterList *Old, + bool Complain, + TemplateParameterListEqualKind Kind, + SourceLocation TemplateArgLoc) { + if (Old->size() != New->size() && Kind != TPL_TemplateTemplateArgumentMatch) { + if (Complain) + DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, + TemplateArgLoc); + + return false; + } + + // C++0x [temp.arg.template]p3: + // A template-argument matches a template template-parameter (call it P) + // when each of the template parameters in the template-parameter-list of + // the template-argument's corresponding class template or alias template + // (call it A) matches the corresponding template parameter in the + // template-parameter-list of P. [...] + TemplateParameterList::iterator NewParm = New->begin(); + TemplateParameterList::iterator NewParmEnd = New->end(); + for (TemplateParameterList::iterator OldParm = Old->begin(), + OldParmEnd = Old->end(); + OldParm != OldParmEnd; ++OldParm) { + if (Kind != TPL_TemplateTemplateArgumentMatch || + !(*OldParm)->isTemplateParameterPack()) { + if (NewParm == NewParmEnd) { + if (Complain) + DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, + TemplateArgLoc); + + return false; + } + + if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain, + Kind, TemplateArgLoc)) + return false; + + ++NewParm; + continue; + } + + // C++0x [temp.arg.template]p3: + // [...] When P's template- parameter-list contains a template parameter + // pack (14.5.3), the template parameter pack will match zero or more + // template parameters or template parameter packs in the + // template-parameter-list of A with the same type and form as the + // template parameter pack in P (ignoring whether those template + // parameters are template parameter packs). + for (; NewParm != NewParmEnd; ++NewParm) { + if (!MatchTemplateParameterKind(*this, *NewParm, *OldParm, Complain, + Kind, TemplateArgLoc)) + return false; + } + } + + // Make sure we exhausted all of the arguments. + if (NewParm != NewParmEnd) { + if (Complain) + DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, + TemplateArgLoc); + + return false; + } + + return true; +} + +/// \brief Check whether a template can be declared within this scope. +/// +/// If the template declaration is valid in this scope, returns +/// false. Otherwise, issues a diagnostic and returns true. +bool +Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { + // Find the nearest enclosing declaration scope. + while ((S->getFlags() & Scope::DeclScope) == 0 || + (S->getFlags() & Scope::TemplateParamScope) != 0) + S = S->getParent(); + + // C++ [temp]p2: + // A template-declaration can appear only as a namespace scope or + // class scope declaration. + DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); + if (Ctx && isa<LinkageSpecDecl>(Ctx) && + cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx) + return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) + << TemplateParams->getSourceRange(); + + while (Ctx && isa<LinkageSpecDecl>(Ctx)) + Ctx = Ctx->getParent(); + + if (Ctx && (Ctx->isFileContext() || Ctx->isRecord())) + return false; + + return Diag(TemplateParams->getTemplateLoc(), + diag::err_template_outside_namespace_or_class_scope) + << TemplateParams->getSourceRange(); +} + +/// \brief Determine what kind of template specialization the given declaration +/// is. +static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) { + if (!D) + return TSK_Undeclared; + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) + return Record->getTemplateSpecializationKind(); + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) + return Function->getTemplateSpecializationKind(); + if (VarDecl *Var = dyn_cast<VarDecl>(D)) + return Var->getTemplateSpecializationKind(); + + return TSK_Undeclared; +} + +/// \brief Check whether a specialization is well-formed in the current +/// context. +/// +/// This routine determines whether a template specialization can be declared +/// in the current context (C++ [temp.expl.spec]p2). +/// +/// \param S the semantic analysis object for which this check is being +/// performed. +/// +/// \param Specialized the entity being specialized or instantiated, which +/// may be a kind of template (class template, function template, etc.) or +/// a member of a class template (member function, static data member, +/// member class). +/// +/// \param PrevDecl the previous declaration of this entity, if any. +/// +/// \param Loc the location of the explicit specialization or instantiation of +/// this entity. +/// +/// \param IsPartialSpecialization whether this is a partial specialization of +/// a class template. +/// +/// \returns true if there was an error that we cannot recover from, false +/// otherwise. +static bool CheckTemplateSpecializationScope(Sema &S, + NamedDecl *Specialized, + NamedDecl *PrevDecl, + SourceLocation Loc, + bool IsPartialSpecialization) { + // Keep these "kind" numbers in sync with the %select statements in the + // various diagnostics emitted by this routine. + int EntityKind = 0; + if (isa<ClassTemplateDecl>(Specialized)) + EntityKind = IsPartialSpecialization? 1 : 0; + else if (isa<FunctionTemplateDecl>(Specialized)) + EntityKind = 2; + else if (isa<CXXMethodDecl>(Specialized)) + EntityKind = 3; + else if (isa<VarDecl>(Specialized)) + EntityKind = 4; + else if (isa<RecordDecl>(Specialized)) + EntityKind = 5; + else { + S.Diag(Loc, diag::err_template_spec_unknown_kind); + S.Diag(Specialized->getLocation(), diag::note_specialized_entity); + return true; + } + + // C++ [temp.expl.spec]p2: + // An explicit specialization shall be declared in the namespace + // of which the template is a member, or, for member templates, in + // the namespace of which the enclosing class or enclosing class + // template is a member. An explicit specialization of a member + // function, member class or static data member of a class + // template shall be declared in the namespace of which the class + // template is a member. Such a declaration may also be a + // definition. If the declaration is not a definition, the + // specialization may be defined later in the name- space in which + // the explicit specialization was declared, or in a namespace + // that encloses the one in which the explicit specialization was + // declared. + if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) { + S.Diag(Loc, diag::err_template_spec_decl_function_scope) + << Specialized; + return true; + } + + if (S.CurContext->isRecord() && !IsPartialSpecialization) { + S.Diag(Loc, diag::err_template_spec_decl_class_scope) + << Specialized; + return true; + } + + // C++ [temp.class.spec]p6: + // A class template partial specialization may be declared or redeclared + // in any namespace scope in which its definition may be defined (14.5.1 + // and 14.5.2). + bool ComplainedAboutScope = false; + DeclContext *SpecializedContext + = Specialized->getDeclContext()->getEnclosingNamespaceContext(); + DeclContext *DC = S.CurContext->getEnclosingNamespaceContext(); + if ((!PrevDecl || + getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared || + getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){ + // C++ [temp.exp.spec]p2: + // An explicit specialization shall be declared in the namespace of which + // the template is a member, or, for member templates, in the namespace + // of which the enclosing class or enclosing class template is a member. + // An explicit specialization of a member function, member class or + // static data member of a class template shall be declared in the + // namespace of which the class template is a member. + // + // C++0x [temp.expl.spec]p2: + // An explicit specialization shall be declared in a namespace enclosing + // the specialized template. + if (!DC->InEnclosingNamespaceSetOf(SpecializedContext) && + !(S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext))) { + bool IsCPlusPlus0xExtension + = !S.getLangOptions().CPlusPlus0x && DC->Encloses(SpecializedContext); + if (isa<TranslationUnitDecl>(SpecializedContext)) + S.Diag(Loc, IsCPlusPlus0xExtension + ? diag::ext_template_spec_decl_out_of_scope_global + : diag::err_template_spec_decl_out_of_scope_global) + << EntityKind << Specialized; + else if (isa<NamespaceDecl>(SpecializedContext)) + S.Diag(Loc, IsCPlusPlus0xExtension + ? diag::ext_template_spec_decl_out_of_scope + : diag::err_template_spec_decl_out_of_scope) + << EntityKind << Specialized + << cast<NamedDecl>(SpecializedContext); + + S.Diag(Specialized->getLocation(), diag::note_specialized_entity); + ComplainedAboutScope = true; + } + } + + // Make sure that this redeclaration (or definition) occurs in an enclosing + // namespace. + // Note that HandleDeclarator() performs this check for explicit + // specializations of function templates, static data members, and member + // functions, so we skip the check here for those kinds of entities. + // FIXME: HandleDeclarator's diagnostics aren't quite as good, though. + // Should we refactor that check, so that it occurs later? + if (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) && + !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) || + isa<FunctionDecl>(Specialized))) { + if (isa<TranslationUnitDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_redecl_global_scope) + << EntityKind << Specialized; + else if (isa<NamespaceDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope) + << EntityKind << Specialized + << cast<NamedDecl>(SpecializedContext); + + S.Diag(Specialized->getLocation(), diag::note_specialized_entity); + } + + // FIXME: check for specialization-after-instantiation errors and such. + + return false; +} + +/// \brief Subroutine of Sema::CheckClassTemplatePartialSpecializationArgs +/// that checks non-type template partial specialization arguments. +static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S, + NonTypeTemplateParmDecl *Param, + const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) { + if (Args[I].getKind() == TemplateArgument::Pack) { + if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param, + Args[I].pack_begin(), + Args[I].pack_size())) + return true; + + continue; + } + + Expr *ArgExpr = Args[I].getAsExpr(); + if (!ArgExpr) { + continue; + } + + // We can have a pack expansion of any of the bullets below. + if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr)) + ArgExpr = Expansion->getPattern(); + + // Strip off any implicit casts we added as part of type checking. + while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr)) + ArgExpr = ICE->getSubExpr(); + + // C++ [temp.class.spec]p8: + // A non-type argument is non-specialized if it is the name of a + // non-type parameter. All other non-type arguments are + // specialized. + // + // Below, we check the two conditions that only apply to + // specialized non-type arguments, so skip any non-specialized + // arguments. + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr)) + if (isa<NonTypeTemplateParmDecl>(DRE->getDecl())) + continue; + + // C++ [temp.class.spec]p9: + // Within the argument list of a class template partial + // specialization, the following restrictions apply: + // -- A partially specialized non-type argument expression + // shall not involve a template parameter of the partial + // specialization except when the argument expression is a + // simple identifier. + if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) { + S.Diag(ArgExpr->getLocStart(), + diag::err_dependent_non_type_arg_in_partial_spec) + << ArgExpr->getSourceRange(); + return true; + } + + // -- The type of a template parameter corresponding to a + // specialized non-type argument shall not be dependent on a + // parameter of the specialization. + if (Param->getType()->isDependentType()) { + S.Diag(ArgExpr->getLocStart(), + diag::err_dependent_typed_non_type_arg_in_partial_spec) + << Param->getType() + << ArgExpr->getSourceRange(); + S.Diag(Param->getLocation(), diag::note_template_param_here); + return true; + } + } + + return false; +} + +/// \brief Check the non-type template arguments of a class template +/// partial specialization according to C++ [temp.class.spec]p9. +/// +/// \param TemplateParams the template parameters of the primary class +/// template. +/// +/// \param TemplateArg the template arguments of the class template +/// partial specialization. +/// +/// \returns true if there was an error, false otherwise. +static bool CheckClassTemplatePartialSpecializationArgs(Sema &S, + TemplateParameterList *TemplateParams, + llvm::SmallVectorImpl<TemplateArgument> &TemplateArgs) { + const TemplateArgument *ArgList = TemplateArgs.data(); + + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + NonTypeTemplateParmDecl *Param + = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I)); + if (!Param) + continue; + + if (CheckNonTypeClassTemplatePartialSpecializationArgs(S, Param, + &ArgList[I], 1)) + return true; + } + + return false; +} + +/// \brief Retrieve the previous declaration of the given declaration. +static NamedDecl *getPreviousDecl(NamedDecl *ND) { + if (VarDecl *VD = dyn_cast<VarDecl>(ND)) + return VD->getPreviousDeclaration(); + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) + return FD->getPreviousDeclaration(); + if (TagDecl *TD = dyn_cast<TagDecl>(ND)) + return TD->getPreviousDeclaration(); + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND)) + return TD->getPreviousDeclaration(); + if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + return FTD->getPreviousDeclaration(); + if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND)) + return CTD->getPreviousDeclaration(); + return 0; +} + +DeclResult +Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, + TagUseKind TUK, + SourceLocation KWLoc, + CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, + AttributeList *Attr, + MultiTemplateParamsArg TemplateParameterLists) { + assert(TUK != TUK_Reference && "References are not specializations"); + + // NOTE: KWLoc is the location of the tag keyword. This will instead + // store the location of the outermost template keyword in the declaration. + SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0 + ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation(); + + // Find the class template we're specializing + TemplateName Name = TemplateD.getAsVal<TemplateName>(); + ClassTemplateDecl *ClassTemplate + = dyn_cast_or_null<ClassTemplateDecl>(Name.getAsTemplateDecl()); + + if (!ClassTemplate) { + Diag(TemplateNameLoc, diag::err_not_class_template_specialization) + << (Name.getAsTemplateDecl() && + isa<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())); + return true; + } + + bool isExplicitSpecialization = false; + bool isPartialSpecialization = false; + + // Check the validity of the template headers that introduce this + // template. + // FIXME: We probably shouldn't complain about these headers for + // friend declarations. + bool Invalid = false; + TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, + TemplateNameLoc, + SS, + (TemplateParameterList**)TemplateParameterLists.get(), + TemplateParameterLists.size(), + TUK == TUK_Friend, + isExplicitSpecialization, + Invalid); + if (Invalid) + return true; + + if (TemplateParams && TemplateParams->size() > 0) { + isPartialSpecialization = true; + + if (TUK == TUK_Friend) { + Diag(KWLoc, diag::err_partial_specialization_friend) + << SourceRange(LAngleLoc, RAngleLoc); + return true; + } + + // C++ [temp.class.spec]p10: + // The template parameter list of a specialization shall not + // contain default template argument values. + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + Decl *Param = TemplateParams->getParam(I); + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (TTP->hasDefaultArgument()) { + Diag(TTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec); + TTP->removeDefaultArgument(); + } + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (Expr *DefArg = NTTP->getDefaultArgument()) { + Diag(NTTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec) + << DefArg->getSourceRange(); + NTTP->removeDefaultArgument(); + } + } else { + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); + if (TTP->hasDefaultArgument()) { + Diag(TTP->getDefaultArgument().getLocation(), + diag::err_default_arg_in_partial_spec) + << TTP->getDefaultArgument().getSourceRange(); + TTP->removeDefaultArgument(); + } + } + } + } else if (TemplateParams) { + if (TUK == TUK_Friend) + Diag(KWLoc, diag::err_template_spec_friend) + << FixItHint::CreateRemoval( + SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc())) + << SourceRange(LAngleLoc, RAngleLoc); + else + isExplicitSpecialization = true; + } else if (TUK != TUK_Friend) { + Diag(KWLoc, diag::err_template_spec_needs_header) + << FixItHint::CreateInsertion(KWLoc, "template<> "); + isExplicitSpecialization = true; + } + + // Check that the specialization uses the same tag kind as the + // original template. + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + assert(Kind != TTK_Enum && "Invalid enum tag in class template spec!"); + if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), + Kind, TUK == TUK_Definition, KWLoc, + *ClassTemplate->getIdentifier())) { + Diag(KWLoc, diag::err_use_with_wrong_tag) + << ClassTemplate + << FixItHint::CreateReplacement(KWLoc, + ClassTemplate->getTemplatedDecl()->getKindName()); + Diag(ClassTemplate->getTemplatedDecl()->getLocation(), + diag::note_previous_use); + Kind = ClassTemplate->getTemplatedDecl()->getTagKind(); + } + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs; + TemplateArgs.setLAngleLoc(LAngleLoc); + TemplateArgs.setRAngleLoc(RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + // Check for unexpanded parameter packs in any of the template arguments. + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + if (DiagnoseUnexpandedParameterPack(TemplateArgs[I], + UPPC_PartialSpecialization)) + return true; + + // Check that the template argument list is well-formed for this + // template. + llvm::SmallVector<TemplateArgument, 4> Converted; + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, + TemplateArgs, false, Converted)) + return true; + + assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) && + "Converted template argument list is too short!"); + + // Find the class template (partial) specialization declaration that + // corresponds to these arguments. + if (isPartialSpecialization) { + if (CheckClassTemplatePartialSpecializationArgs(*this, + ClassTemplate->getTemplateParameters(), + Converted)) + return true; + + if (!Name.isDependent() && + !TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs.getArgumentArray(), + TemplateArgs.size())) { + Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) + << ClassTemplate->getDeclName(); + isPartialSpecialization = false; + } + } + + void *InsertPos = 0; + ClassTemplateSpecializationDecl *PrevDecl = 0; + + if (isPartialSpecialization) + // FIXME: Template parameter list matters, too + PrevDecl + = ClassTemplate->findPartialSpecialization(Converted.data(), + Converted.size(), + InsertPos); + else + PrevDecl + = ClassTemplate->findSpecialization(Converted.data(), + Converted.size(), InsertPos); + + ClassTemplateSpecializationDecl *Specialization = 0; + + // Check whether we can declare a class template specialization in + // the current scope. + if (TUK != TUK_Friend && + CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl, + TemplateNameLoc, + isPartialSpecialization)) + return true; + + // The canonical type + QualType CanonType; + if (PrevDecl && + (PrevDecl->getSpecializationKind() == TSK_Undeclared || + TUK == TUK_Friend)) { + // Since the only prior class template specialization with these + // arguments was referenced but not declared, or we're only + // referencing this specialization as a friend, reuse that + // declaration node as our own, updating its source location and + // the list of outer template parameters to reflect our new declaration. + Specialization = PrevDecl; + Specialization->setLocation(TemplateNameLoc); + if (TemplateParameterLists.size() > 0) { + Specialization->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size(), + (TemplateParameterList**) TemplateParameterLists.release()); + } + PrevDecl = 0; + CanonType = Context.getTypeDeclType(Specialization); + } else if (isPartialSpecialization) { + // Build the canonical type that describes the converted template + // arguments of the class template partial specialization. + TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); + CanonType = Context.getTemplateSpecializationType(CanonTemplate, + Converted.data(), + Converted.size()); + + if (Context.hasSameType(CanonType, + ClassTemplate->getInjectedClassNameSpecialization())) { + // C++ [temp.class.spec]p9b3: + // + // -- The argument list of the specialization shall not be identical + // to the implicit argument list of the primary template. + Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) + << (TUK == TUK_Definition) + << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); + return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, + ClassTemplate->getIdentifier(), + TemplateNameLoc, + Attr, + TemplateParams, + AS_none, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); + } + + // Create a new class template partial specialization declaration node. + ClassTemplatePartialSpecializationDecl *PrevPartial + = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl); + unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber() + : ClassTemplate->getNextPartialSpecSequenceNumber(); + ClassTemplatePartialSpecializationDecl *Partial + = ClassTemplatePartialSpecializationDecl::Create(Context, Kind, + ClassTemplate->getDeclContext(), + KWLoc, TemplateNameLoc, + TemplateParams, + ClassTemplate, + Converted.data(), + Converted.size(), + TemplateArgs, + CanonType, + PrevPartial, + SequenceNumber); + SetNestedNameSpecifier(Partial, SS); + if (TemplateParameterLists.size() > 1 && SS.isSet()) { + Partial->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size() - 1, + (TemplateParameterList**) TemplateParameterLists.release()); + } + + if (!PrevPartial) + ClassTemplate->AddPartialSpecialization(Partial, InsertPos); + Specialization = Partial; + + // If we are providing an explicit specialization of a member class + // template specialization, make a note of that. + if (PrevPartial && PrevPartial->getInstantiatedFromMember()) + PrevPartial->setMemberSpecialization(); + + // Check that all of the template parameters of the class template + // partial specialization are deducible from the template + // arguments. If not, this class template partial specialization + // will never be used. + llvm::SmallVector<bool, 8> DeducibleParams; + DeducibleParams.resize(TemplateParams->size()); + MarkUsedTemplateParameters(Partial->getTemplateArgs(), true, + TemplateParams->getDepth(), + DeducibleParams); + unsigned NumNonDeducible = 0; + for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) + if (!DeducibleParams[I]) + ++NumNonDeducible; + + if (NumNonDeducible) { + Diag(TemplateNameLoc, diag::warn_partial_specs_not_deducible) + << (NumNonDeducible > 1) + << SourceRange(TemplateNameLoc, RAngleLoc); + for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) { + if (!DeducibleParams[I]) { + NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I)); + if (Param->getDeclName()) + Diag(Param->getLocation(), + diag::note_partial_spec_unused_parameter) + << Param->getDeclName(); + else + Diag(Param->getLocation(), + diag::note_partial_spec_unused_parameter) + << "<anonymous>"; + } + } + } + } else { + // Create a new class template specialization declaration node for + // this explicit specialization or friend declaration. + Specialization + = ClassTemplateSpecializationDecl::Create(Context, Kind, + ClassTemplate->getDeclContext(), + KWLoc, TemplateNameLoc, + ClassTemplate, + Converted.data(), + Converted.size(), + PrevDecl); + SetNestedNameSpecifier(Specialization, SS); + if (TemplateParameterLists.size() > 0) { + Specialization->setTemplateParameterListsInfo(Context, + TemplateParameterLists.size(), + (TemplateParameterList**) TemplateParameterLists.release()); + } + + if (!PrevDecl) + ClassTemplate->AddSpecialization(Specialization, InsertPos); + + CanonType = Context.getTypeDeclType(Specialization); + } + + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template is + // explicitly specialized then that specialization shall be declared + // before the first use of that specialization that would cause an implicit + // instantiation to take place, in every translation unit in which such a + // use occurs; no diagnostic is required. + if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) { + bool Okay = false; + for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) { + // Is there any previous explicit specialization declaration? + if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) { + Okay = true; + break; + } + } + + if (!Okay) { + SourceRange Range(TemplateNameLoc, RAngleLoc); + Diag(TemplateNameLoc, diag::err_specialization_after_instantiation) + << Context.getTypeDeclType(Specialization) << Range; + + Diag(PrevDecl->getPointOfInstantiation(), + diag::note_instantiation_required_here) + << (PrevDecl->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation); + return true; + } + } + + // If this is not a friend, note that this is an explicit specialization. + if (TUK != TUK_Friend) + Specialization->setSpecializationKind(TSK_ExplicitSpecialization); + + // Check that this isn't a redefinition of this specialization. + if (TUK == TUK_Definition) { + if (RecordDecl *Def = Specialization->getDefinition()) { + SourceRange Range(TemplateNameLoc, RAngleLoc); + Diag(TemplateNameLoc, diag::err_redefinition) + << Context.getTypeDeclType(Specialization) << Range; + Diag(Def->getLocation(), diag::note_previous_definition); + Specialization->setInvalidDecl(); + return true; + } + } + + if (Attr) + ProcessDeclAttributeList(S, Specialization, Attr); + + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy + = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, + TemplateArgs, CanonType); + if (TUK != TUK_Friend) { + Specialization->setTypeAsWritten(WrittenTy); + Specialization->setTemplateKeywordLoc(TemplateKWLoc); + } + TemplateArgsIn.release(); + + // C++ [temp.expl.spec]p9: + // A template explicit specialization is in the scope of the + // namespace in which the template was defined. + // + // We actually implement this paragraph where we set the semantic + // context (in the creation of the ClassTemplateSpecializationDecl), + // but we also maintain the lexical context where the actual + // definition occurs. + Specialization->setLexicalDeclContext(CurContext); + + // We may be starting the definition of this specialization. + if (TUK == TUK_Definition) + Specialization->startDefinition(); + + if (TUK == TUK_Friend) { + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, + TemplateNameLoc, + WrittenTy, + /*FIXME:*/KWLoc); + Friend->setAccess(AS_public); + CurContext->addDecl(Friend); + } else { + // Add the specialization into its lexical context, so that it can + // be seen when iterating through the list of declarations in that + // context. However, specializations are not found by name lookup. + CurContext->addDecl(Specialization); + } + return Specialization; +} + +Decl *Sema::ActOnTemplateDeclarator(Scope *S, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D) { + return HandleDeclarator(S, D, move(TemplateParameterLists), false); +} + +Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D) { + assert(getCurFunctionDecl() == 0 && "Function parsing confused"); + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + + if (FTI.hasPrototype) { + // FIXME: Diagnose arguments without names in C. + } + + Scope *ParentScope = FnBodyScope->getParent(); + + Decl *DP = HandleDeclarator(ParentScope, D, + move(TemplateParameterLists), + /*IsFunctionDefinition=*/true); + if (FunctionTemplateDecl *FunctionTemplate + = dyn_cast_or_null<FunctionTemplateDecl>(DP)) + return ActOnStartOfFunctionDef(FnBodyScope, + FunctionTemplate->getTemplatedDecl()); + if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP)) + return ActOnStartOfFunctionDef(FnBodyScope, Function); + return 0; +} + +/// \brief Strips various properties off an implicit instantiation +/// that has just been explicitly specialized. +static void StripImplicitInstantiation(NamedDecl *D) { + D->dropAttrs(); + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + FD->setInlineSpecified(false); + } +} + +/// \brief Diagnose cases where we have an explicit template specialization +/// before/after an explicit template instantiation, producing diagnostics +/// for those cases where they are required and determining whether the +/// new specialization/instantiation will have any effect. +/// +/// \param NewLoc the location of the new explicit specialization or +/// instantiation. +/// +/// \param NewTSK the kind of the new explicit specialization or instantiation. +/// +/// \param PrevDecl the previous declaration of the entity. +/// +/// \param PrevTSK the kind of the old explicit specialization or instantiatin. +/// +/// \param PrevPointOfInstantiation if valid, indicates where the previus +/// declaration was instantiated (either implicitly or explicitly). +/// +/// \param HasNoEffect will be set to true to indicate that the new +/// specialization or instantiation has no effect and should be ignored. +/// +/// \returns true if there was an error that should prevent the introduction of +/// the new declaration into the AST, false otherwise. +bool +Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, + TemplateSpecializationKind NewTSK, + NamedDecl *PrevDecl, + TemplateSpecializationKind PrevTSK, + SourceLocation PrevPointOfInstantiation, + bool &HasNoEffect) { + HasNoEffect = false; + + switch (NewTSK) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + assert(false && "Don't check implicit instantiations here"); + return false; + + case TSK_ExplicitSpecialization: + switch (PrevTSK) { + case TSK_Undeclared: + case TSK_ExplicitSpecialization: + // Okay, we're just specializing something that is either already + // explicitly specialized or has merely been mentioned without any + // instantiation. + return false; + + case TSK_ImplicitInstantiation: + if (PrevPointOfInstantiation.isInvalid()) { + // The declaration itself has not actually been instantiated, so it is + // still okay to specialize it. + StripImplicitInstantiation(PrevDecl); + return false; + } + // Fall through + + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + assert((PrevTSK == TSK_ImplicitInstantiation || + PrevPointOfInstantiation.isValid()) && + "Explicit instantiation without point of instantiation?"); + + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template + // is explicitly specialized then that specialization shall be declared + // before the first use of that specialization that would cause an + // implicit instantiation to take place, in every translation unit in + // which such a use occurs; no diagnostic is required. + for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) { + // Is there any previous explicit specialization declaration? + if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) + return false; + } + + Diag(NewLoc, diag::err_specialization_after_instantiation) + << PrevDecl; + Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here) + << (PrevTSK != TSK_ImplicitInstantiation); + + return true; + } + break; + + case TSK_ExplicitInstantiationDeclaration: + switch (PrevTSK) { + case TSK_ExplicitInstantiationDeclaration: + // This explicit instantiation declaration is redundant (that's okay). + HasNoEffect = true; + return false; + + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + // We're explicitly instantiating something that may have already been + // implicitly instantiated; that's fine. + return false; + + case TSK_ExplicitSpecialization: + // C++0x [temp.explicit]p4: + // For a given set of template parameters, if an explicit instantiation + // of a template appears after a declaration of an explicit + // specialization for that template, the explicit instantiation has no + // effect. + HasNoEffect = true; + return false; + + case TSK_ExplicitInstantiationDefinition: + // C++0x [temp.explicit]p10: + // If an entity is the subject of both an explicit instantiation + // declaration and an explicit instantiation definition in the same + // translation unit, the definition shall follow the declaration. + Diag(NewLoc, + diag::err_explicit_instantiation_declaration_after_definition); + Diag(PrevPointOfInstantiation, + diag::note_explicit_instantiation_definition_here); + assert(PrevPointOfInstantiation.isValid() && + "Explicit instantiation without point of instantiation?"); + HasNoEffect = true; + return false; + } + break; + + case TSK_ExplicitInstantiationDefinition: + switch (PrevTSK) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + // We're explicitly instantiating something that may have already been + // implicitly instantiated; that's fine. + return false; + + case TSK_ExplicitSpecialization: + // C++ DR 259, C++0x [temp.explicit]p4: + // For a given set of template parameters, if an explicit + // instantiation of a template appears after a declaration of + // an explicit specialization for that template, the explicit + // instantiation has no effect. + // + // In C++98/03 mode, we only give an extension warning here, because it + // is not harmful to try to explicitly instantiate something that + // has been explicitly specialized. + if (!getLangOptions().CPlusPlus0x) { + Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization) + << PrevDecl; + Diag(PrevDecl->getLocation(), + diag::note_previous_template_specialization); + } + HasNoEffect = true; + return false; + + case TSK_ExplicitInstantiationDeclaration: + // We're explicity instantiating a definition for something for which we + // were previously asked to suppress instantiations. That's fine. + return false; + + case TSK_ExplicitInstantiationDefinition: + // C++0x [temp.spec]p5: + // For a given template and a given set of template-arguments, + // - an explicit instantiation definition shall appear at most once + // in a program, + Diag(NewLoc, diag::err_explicit_instantiation_duplicate) + << PrevDecl; + Diag(PrevPointOfInstantiation, + diag::note_previous_explicit_instantiation); + HasNoEffect = true; + return false; + } + break; + } + + assert(false && "Missing specialization/instantiation case?"); + + return false; +} + +/// \brief Perform semantic analysis for the given dependent function +/// template specialization. The only possible way to get a dependent +/// function template specialization is with a friend declaration, +/// like so: +/// +/// template <class T> void foo(T); +/// template <class T> class A { +/// friend void foo<>(T); +/// }; +/// +/// There really isn't any useful analysis we can do here, so we +/// just store the information. +bool +Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, + const TemplateArgumentListInfo &ExplicitTemplateArgs, + LookupResult &Previous) { + // Remove anything from Previous that isn't a function template in + // the correct context. + DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next()->getUnderlyingDecl(); + if (!isa<FunctionTemplateDecl>(D) || + !FDLookupContext->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) + F.erase(); + } + F.done(); + + // Should this be diagnosed here? + if (Previous.empty()) return true; + + FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(), + ExplicitTemplateArgs); + return false; +} + +/// \brief Perform semantic analysis for the given function template +/// specialization. +/// +/// This routine performs all of the semantic analysis required for an +/// explicit function template specialization. On successful completion, +/// the function declaration \p FD will become a function template +/// specialization. +/// +/// \param FD the function declaration, which will be updated to become a +/// function template specialization. +/// +/// \param ExplicitTemplateArgs the explicitly-provided template arguments, +/// if any. Note that this may be valid info even when 0 arguments are +/// explicitly provided as in, e.g., \c void sort<>(char*, char*); +/// as it anyway contains info on the angle brackets locations. +/// +/// \param PrevDecl the set of declarations that may be specialized by +/// this function specialization. +bool +Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, + TemplateArgumentListInfo *ExplicitTemplateArgs, + LookupResult &Previous) { + // The set of function template specializations that could match this + // explicit function template specialization. + UnresolvedSet<8> Candidates; + + DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + NamedDecl *Ovl = (*I)->getUnderlyingDecl(); + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) { + // Only consider templates found within the same semantic lookup scope as + // FD. + if (!FDLookupContext->InEnclosingNamespaceSetOf( + Ovl->getDeclContext()->getRedeclContext())) + continue; + + // C++ [temp.expl.spec]p11: + // A trailing template-argument can be left unspecified in the + // template-id naming an explicit function template specialization + // provided it can be deduced from the function argument type. + // Perform template argument deduction to determine whether we may be + // specializing this template. + // FIXME: It is somewhat wasteful to build + TemplateDeductionInfo Info(Context, FD->getLocation()); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult TDK + = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, + FD->getType(), + Specialization, + Info)) { + // FIXME: Template argument deduction failed; record why it failed, so + // that we can provide nifty diagnostics. + (void)TDK; + continue; + } + + // Record this candidate. + Candidates.addDecl(Specialization, I.getAccess()); + } + } + + // Find the most specialized function template. + UnresolvedSetIterator Result + = getMostSpecialized(Candidates.begin(), Candidates.end(), + TPOC_Other, 0, FD->getLocation(), + PDiag(diag::err_function_template_spec_no_match) + << FD->getDeclName(), + PDiag(diag::err_function_template_spec_ambiguous) + << FD->getDeclName() << (ExplicitTemplateArgs != 0), + PDiag(diag::note_function_template_spec_matched)); + if (Result == Candidates.end()) + return true; + + // Ignore access information; it doesn't figure into redeclaration checking. + FunctionDecl *Specialization = cast<FunctionDecl>(*Result); + + FunctionTemplateSpecializationInfo *SpecInfo + = Specialization->getTemplateSpecializationInfo(); + assert(SpecInfo && "Function template specialization info missing?"); + { + // Note: do not overwrite location info if previous template + // specialization kind was explicit. + TemplateSpecializationKind TSK = SpecInfo->getTemplateSpecializationKind(); + if (TSK == TSK_Undeclared || TSK == TSK_ImplicitInstantiation) + Specialization->setLocation(FD->getLocation()); + } + + // FIXME: Check if the prior specialization has a point of instantiation. + // If so, we have run afoul of . + + // If this is a friend declaration, then we're not really declaring + // an explicit specialization. + bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None); + + // Check the scope of this explicit specialization. + if (!isFriend && + CheckTemplateSpecializationScope(*this, + Specialization->getPrimaryTemplate(), + Specialization, FD->getLocation(), + false)) + return true; + + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template is + // explicitly specialized then that specialization shall be declared + // before the first use of that specialization that would cause an implicit + // instantiation to take place, in every translation unit in which such a + // use occurs; no diagnostic is required. + bool HasNoEffect = false; + if (!isFriend && + CheckSpecializationInstantiationRedecl(FD->getLocation(), + TSK_ExplicitSpecialization, + Specialization, + SpecInfo->getTemplateSpecializationKind(), + SpecInfo->getPointOfInstantiation(), + HasNoEffect)) + return true; + + // Mark the prior declaration as an explicit specialization, so that later + // clients know that this is an explicit specialization. + if (!isFriend) { + SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization); + MarkUnusedFileScopedDecl(Specialization); + } + + // Turn the given function declaration into a function template + // specialization, with the template arguments from the previous + // specialization. + // Take copies of (semantic and syntactic) template argument lists. + const TemplateArgumentList* TemplArgs = new (Context) + TemplateArgumentList(Specialization->getTemplateSpecializationArgs()); + const TemplateArgumentListInfo* TemplArgsAsWritten = ExplicitTemplateArgs + ? new (Context) TemplateArgumentListInfo(*ExplicitTemplateArgs) : 0; + FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(), + TemplArgs, /*InsertPos=*/0, + SpecInfo->getTemplateSpecializationKind(), + TemplArgsAsWritten); + FD->setStorageClass(Specialization->getStorageClass()); + + // The "previous declaration" for this function template specialization is + // the prior function template specialization. + Previous.clear(); + Previous.addDecl(Specialization); + return false; +} + +/// \brief Perform semantic analysis for the given non-template member +/// specialization. +/// +/// This routine performs all of the semantic analysis required for an +/// explicit member function specialization. On successful completion, +/// the function declaration \p FD will become a member function +/// specialization. +/// +/// \param Member the member declaration, which will be updated to become a +/// specialization. +/// +/// \param Previous the set of declarations, one of which may be specialized +/// by this function specialization; the set will be modified to contain the +/// redeclared member. +bool +Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { + assert(!isa<TemplateDecl>(Member) && "Only for non-template members"); + + // Try to find the member we are instantiating. + NamedDecl *Instantiation = 0; + NamedDecl *InstantiatedFrom = 0; + MemberSpecializationInfo *MSInfo = 0; + + if (Previous.empty()) { + // Nowhere to look anyway. + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) { + for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); + I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { + if (Context.hasSameType(Function->getType(), Method->getType())) { + Instantiation = Method; + InstantiatedFrom = Method->getInstantiatedFromMemberFunction(); + MSInfo = Method->getMemberSpecializationInfo(); + break; + } + } + } + } else if (isa<VarDecl>(Member)) { + VarDecl *PrevVar; + if (Previous.isSingleResult() && + (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl()))) + if (PrevVar->isStaticDataMember()) { + Instantiation = PrevVar; + InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember(); + MSInfo = PrevVar->getMemberSpecializationInfo(); + } + } else if (isa<RecordDecl>(Member)) { + CXXRecordDecl *PrevRecord; + if (Previous.isSingleResult() && + (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) { + Instantiation = PrevRecord; + InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass(); + MSInfo = PrevRecord->getMemberSpecializationInfo(); + } + } + + if (!Instantiation) { + // There is no previous declaration that matches. Since member + // specializations are always out-of-line, the caller will complain about + // this mismatch later. + return false; + } + + // If this is a friend, just bail out here before we start turning + // things into explicit specializations. + if (Member->getFriendObjectKind() != Decl::FOK_None) { + // Preserve instantiation information. + if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) { + cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction( + cast<CXXMethodDecl>(InstantiatedFrom), + cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind()); + } else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) { + cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( + cast<CXXRecordDecl>(InstantiatedFrom), + cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind()); + } + + Previous.clear(); + Previous.addDecl(Instantiation); + return false; + } + + // Make sure that this is a specialization of a member. + if (!InstantiatedFrom) { + Diag(Member->getLocation(), diag::err_spec_member_not_instantiated) + << Member; + Diag(Instantiation->getLocation(), diag::note_specialized_decl); + return true; + } + + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template is + // explicitly specialized then that spe- cialization shall be declared + // before the first use of that specialization that would cause an implicit + // instantiation to take place, in every translation unit in which such a + // use occurs; no diagnostic is required. + assert(MSInfo && "Member specialization info missing?"); + + bool HasNoEffect = false; + if (CheckSpecializationInstantiationRedecl(Member->getLocation(), + TSK_ExplicitSpecialization, + Instantiation, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + HasNoEffect)) + return true; + + // Check the scope of this explicit specialization. + if (CheckTemplateSpecializationScope(*this, + InstantiatedFrom, + Instantiation, Member->getLocation(), + false)) + return true; + + // Note that this is an explicit instantiation of a member. + // the original declaration to note that it is an explicit specialization + // (if it was previously an implicit instantiation). This latter step + // makes bookkeeping easier. + if (isa<FunctionDecl>(Member)) { + FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation); + if (InstantiationFunction->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationFunction->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationFunction->setLocation(Member->getLocation()); + } + + cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction( + cast<CXXMethodDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + MarkUnusedFileScopedDecl(InstantiationFunction); + } else if (isa<VarDecl>(Member)) { + VarDecl *InstantiationVar = cast<VarDecl>(Instantiation); + if (InstantiationVar->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationVar->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationVar->setLocation(Member->getLocation()); + } + + Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member), + cast<VarDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + MarkUnusedFileScopedDecl(InstantiationVar); + } else { + assert(isa<CXXRecordDecl>(Member) && "Only member classes remain"); + CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation); + if (InstantiationClass->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationClass->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationClass->setLocation(Member->getLocation()); + } + + cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( + cast<CXXRecordDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + } + + // Save the caller the trouble of having to figure out which declaration + // this specialization matches. + Previous.clear(); + Previous.addDecl(Instantiation); + return false; +} + +/// \brief Check the scope of an explicit instantiation. +/// +/// \returns true if a serious error occurs, false otherwise. +static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, + SourceLocation InstLoc, + bool WasQualifiedName) { + DeclContext *OrigContext= D->getDeclContext()->getEnclosingNamespaceContext(); + DeclContext *CurContext = S.CurContext->getRedeclContext(); + + if (CurContext->isRecord()) { + S.Diag(InstLoc, diag::err_explicit_instantiation_in_class) + << D; + return true; + } + + // C++0x [temp.explicit]p2: + // An explicit instantiation shall appear in an enclosing namespace of its + // template. + // + // This is DR275, which we do not retroactively apply to C++98/03. + if (S.getLangOptions().CPlusPlus0x && + !CurContext->Encloses(OrigContext)) { + if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) + S.Diag(InstLoc, + S.getLangOptions().CPlusPlus0x? + diag::err_explicit_instantiation_out_of_scope + : diag::warn_explicit_instantiation_out_of_scope_0x) + << D << NS; + else + S.Diag(InstLoc, + S.getLangOptions().CPlusPlus0x? + diag::err_explicit_instantiation_must_be_global + : diag::warn_explicit_instantiation_out_of_scope_0x) + << D; + S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); + return false; + } + + // C++0x [temp.explicit]p2: + // If the name declared in the explicit instantiation is an unqualified + // name, the explicit instantiation shall appear in the namespace where + // its template is declared or, if that namespace is inline (7.3.1), any + // namespace from its enclosing namespace set. + if (WasQualifiedName) + return false; + + if (CurContext->InEnclosingNamespaceSetOf(OrigContext)) + return false; + + S.Diag(InstLoc, + S.getLangOptions().CPlusPlus0x? + diag::err_explicit_instantiation_unqualified_wrong_namespace + : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x) + << D << OrigContext; + S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); + return false; +} + +/// \brief Determine whether the given scope specifier has a template-id in it. +static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) { + if (!SS.isSet()) + return false; + + // C++0x [temp.explicit]p2: + // If the explicit instantiation is for a member function, a member class + // or a static data member of a class template specialization, the name of + // the class template specialization in the qualified-id for the member + // name shall be a simple-template-id. + // + // C++98 has the same restriction, just worded differently. + for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); + NNS; NNS = NNS->getPrefix()) + if (const Type *T = NNS->getAsType()) + if (isa<TemplateSpecializationType>(T)) + return true; + + return false; +} + +// Explicit instantiation of a class template specialization +DeclResult +Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, + AttributeList *Attr) { + // Find the class template we're specializing + TemplateName Name = TemplateD.getAsVal<TemplateName>(); + ClassTemplateDecl *ClassTemplate + = cast<ClassTemplateDecl>(Name.getAsTemplateDecl()); + + // Check that the specialization uses the same tag kind as the + // original template. + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + assert(Kind != TTK_Enum && + "Invalid enum tag in class template explicit instantiation!"); + if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), + Kind, /*isDefinition*/false, KWLoc, + *ClassTemplate->getIdentifier())) { + Diag(KWLoc, diag::err_use_with_wrong_tag) + << ClassTemplate + << FixItHint::CreateReplacement(KWLoc, + ClassTemplate->getTemplatedDecl()->getKindName()); + Diag(ClassTemplate->getTemplatedDecl()->getLocation(), + diag::note_previous_use); + Kind = ClassTemplate->getTemplatedDecl()->getTagKind(); + } + + // C++0x [temp.explicit]p2: + // There are two forms of explicit instantiation: an explicit instantiation + // definition and an explicit instantiation declaration. An explicit + // instantiation declaration begins with the extern keyword. [...] + TemplateSpecializationKind TSK + = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition + : TSK_ExplicitInstantiationDeclaration; + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + // Check that the template argument list is well-formed for this + // template. + llvm::SmallVector<TemplateArgument, 4> Converted; + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, + TemplateArgs, false, Converted)) + return true; + + assert((Converted.size() == ClassTemplate->getTemplateParameters()->size()) && + "Converted template argument list is too short!"); + + // Find the class template specialization declaration that + // corresponds to these arguments. + void *InsertPos = 0; + ClassTemplateSpecializationDecl *PrevDecl + = ClassTemplate->findSpecialization(Converted.data(), + Converted.size(), InsertPos); + + TemplateSpecializationKind PrevDecl_TSK + = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; + + // C++0x [temp.explicit]p2: + // [...] An explicit instantiation shall appear in an enclosing + // namespace of its template. [...] + // + // This is C++ DR 275. + if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc, + SS.isSet())) + return true; + + ClassTemplateSpecializationDecl *Specialization = 0; + + bool HasNoEffect = false; + if (PrevDecl) { + if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK, + PrevDecl, PrevDecl_TSK, + PrevDecl->getPointOfInstantiation(), + HasNoEffect)) + return PrevDecl; + + // Even though HasNoEffect == true means that this explicit instantiation + // has no effect on semantics, we go on to put its syntax in the AST. + + if (PrevDecl_TSK == TSK_ImplicitInstantiation || + PrevDecl_TSK == TSK_Undeclared) { + // Since the only prior class template specialization with these + // arguments was referenced but not declared, reuse that + // declaration node as our own, updating the source location + // for the template name to reflect our new declaration. + // (Other source locations will be updated later.) + Specialization = PrevDecl; + Specialization->setLocation(TemplateNameLoc); + PrevDecl = 0; + } + } + + if (!Specialization) { + // Create a new class template specialization declaration node for + // this explicit specialization. + Specialization + = ClassTemplateSpecializationDecl::Create(Context, Kind, + ClassTemplate->getDeclContext(), + KWLoc, TemplateNameLoc, + ClassTemplate, + Converted.data(), + Converted.size(), + PrevDecl); + SetNestedNameSpecifier(Specialization, SS); + + if (!HasNoEffect && !PrevDecl) { + // Insert the new specialization. + ClassTemplate->AddSpecialization(Specialization, InsertPos); + } + } + + // Build the fully-sugared type for this explicit instantiation as + // the user wrote in the explicit instantiation itself. This means + // that we'll pretty-print the type retrieved from the + // specialization's declaration the way that the user actually wrote + // the explicit instantiation, rather than formatting the name based + // on the "canonical" representation used to store the template + // arguments in the specialization. + TypeSourceInfo *WrittenTy + = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, + TemplateArgs, + Context.getTypeDeclType(Specialization)); + Specialization->setTypeAsWritten(WrittenTy); + TemplateArgsIn.release(); + + // Set source locations for keywords. + Specialization->setExternLoc(ExternLoc); + Specialization->setTemplateKeywordLoc(TemplateLoc); + + // Add the explicit instantiation into its lexical context. However, + // since explicit instantiations are never found by name lookup, we + // just put it into the declaration context directly. + Specialization->setLexicalDeclContext(CurContext); + CurContext->addDecl(Specialization); + + // Syntax is now OK, so return if it has no other effect on semantics. + if (HasNoEffect) { + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); + return Specialization; + } + + // C++ [temp.explicit]p3: + // A definition of a class template or class member template + // shall be in scope at the point of the explicit instantiation of + // the class template or class member template. + // + // This check comes when we actually try to perform the + // instantiation. + ClassTemplateSpecializationDecl *Def + = cast_or_null<ClassTemplateSpecializationDecl>( + Specialization->getDefinition()); + if (!Def) + InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK); + else if (TSK == TSK_ExplicitInstantiationDefinition) { + MarkVTableUsed(TemplateNameLoc, Specialization, true); + Specialization->setPointOfInstantiation(Def->getPointOfInstantiation()); + } + + // Instantiate the members of this class template specialization. + Def = cast_or_null<ClassTemplateSpecializationDecl>( + Specialization->getDefinition()); + if (Def) { + TemplateSpecializationKind Old_TSK = Def->getTemplateSpecializationKind(); + + // Fix a TSK_ExplicitInstantiationDeclaration followed by a + // TSK_ExplicitInstantiationDefinition + if (Old_TSK == TSK_ExplicitInstantiationDeclaration && + TSK == TSK_ExplicitInstantiationDefinition) + Def->setTemplateSpecializationKind(TSK); + + InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); + } + + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); + return Specialization; +} + +// Explicit instantiation of a member class of a class template. +DeclResult +Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + AttributeList *Attr) { + + bool Owned = false; + bool IsDependent = false; + Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, + KWLoc, SS, Name, NameLoc, Attr, AS_none, + MultiTemplateParamsArg(*this, 0, 0), + Owned, IsDependent, false, false, + TypeResult()); + assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); + + if (!TagD) + return true; + + TagDecl *Tag = cast<TagDecl>(TagD); + if (Tag->isEnum()) { + Diag(TemplateLoc, diag::err_explicit_instantiation_enum) + << Context.getTypeDeclType(Tag); + return true; + } + + if (Tag->isInvalidDecl()) + return true; + + CXXRecordDecl *Record = cast<CXXRecordDecl>(Tag); + CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass(); + if (!Pattern) { + Diag(TemplateLoc, diag::err_explicit_instantiation_nontemplate_type) + << Context.getTypeDeclType(Record); + Diag(Record->getLocation(), diag::note_nontemplate_decl_here); + return true; + } + + // C++0x [temp.explicit]p2: + // If the explicit instantiation is for a class or member class, the + // elaborated-type-specifier in the declaration shall include a + // simple-template-id. + // + // C++98 has the same restriction, just worded differently. + if (!ScopeSpecifierHasTemplateId(SS)) + Diag(TemplateLoc, diag::ext_explicit_instantiation_without_qualified_id) + << Record << SS.getRange(); + + // C++0x [temp.explicit]p2: + // There are two forms of explicit instantiation: an explicit instantiation + // definition and an explicit instantiation declaration. An explicit + // instantiation declaration begins with the extern keyword. [...] + TemplateSpecializationKind TSK + = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition + : TSK_ExplicitInstantiationDeclaration; + + // C++0x [temp.explicit]p2: + // [...] An explicit instantiation shall appear in an enclosing + // namespace of its template. [...] + // + // This is C++ DR 275. + CheckExplicitInstantiationScope(*this, Record, NameLoc, true); + + // Verify that it is okay to explicitly instantiate here. + CXXRecordDecl *PrevDecl + = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration()); + if (!PrevDecl && Record->getDefinition()) + PrevDecl = Record; + if (PrevDecl) { + MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo(); + bool HasNoEffect = false; + assert(MSInfo && "No member specialization information?"); + if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK, + PrevDecl, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + HasNoEffect)) + return true; + if (HasNoEffect) + return TagD; + } + + CXXRecordDecl *RecordDef + = cast_or_null<CXXRecordDecl>(Record->getDefinition()); + if (!RecordDef) { + // C++ [temp.explicit]p3: + // A definition of a member class of a class template shall be in scope + // at the point of an explicit instantiation of the member class. + CXXRecordDecl *Def + = cast_or_null<CXXRecordDecl>(Pattern->getDefinition()); + if (!Def) { + Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member) + << 0 << Record->getDeclName() << Record->getDeclContext(); + Diag(Pattern->getLocation(), diag::note_forward_declaration) + << Pattern; + return true; + } else { + if (InstantiateClass(NameLoc, Record, Def, + getTemplateInstantiationArgs(Record), + TSK)) + return true; + + RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition()); + if (!RecordDef) + return true; + } + } + + // Instantiate all of the members of the class. + InstantiateClassMembers(NameLoc, RecordDef, + getTemplateInstantiationArgs(Record), TSK); + + if (TSK == TSK_ExplicitInstantiationDefinition) + MarkVTableUsed(NameLoc, RecordDef, true); + + // FIXME: We don't have any representation for explicit instantiations of + // member classes. Such a representation is not needed for compilation, but it + // should be available for clients that want to see all of the declarations in + // the source code. + return TagD; +} + +DeclResult Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + Declarator &D) { + // Explicit instantiations always require a name. + // TODO: check if/when DNInfo should replace Name. + DeclarationNameInfo NameInfo = GetNameForDeclarator(D); + DeclarationName Name = NameInfo.getName(); + if (!Name) { + if (!D.isInvalidType()) + Diag(D.getDeclSpec().getSourceRange().getBegin(), + diag::err_explicit_instantiation_requires_name) + << D.getDeclSpec().getSourceRange() + << D.getSourceRange(); + + return true; + } + + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + while ((S->getFlags() & Scope::DeclScope) == 0 || + (S->getFlags() & Scope::TemplateParamScope) != 0) + S = S->getParent(); + + // Determine the type of the declaration. + TypeSourceInfo *T = GetTypeForDeclarator(D, S); + QualType R = T->getType(); + if (R.isNull()) + return true; + + // C++ [dcl.stc]p1: + // A storage-class-specifier shall not be specified in [...] an explicit + // instantiation (14.7.2) directive. + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef) + << Name; + return true; + } else if (D.getDeclSpec().getStorageClassSpec() + != DeclSpec::SCS_unspecified) { + // Complain about then remove the storage class specifier. + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + + D.getMutableDeclSpec().ClearStorageClassSpecs(); + } + + // C++0x [temp.explicit]p1: + // [...] An explicit instantiation of a function template shall not use the + // inline or constexpr specifiers. + // Presumably, this also applies to member functions of class templates as + // well. + if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x) + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_explicit_instantiation_inline) + <<FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); + + // FIXME: check for constexpr specifier. + + // C++0x [temp.explicit]p2: + // There are two forms of explicit instantiation: an explicit instantiation + // definition and an explicit instantiation declaration. An explicit + // instantiation declaration begins with the extern keyword. [...] + TemplateSpecializationKind TSK + = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition + : TSK_ExplicitInstantiationDeclaration; + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName); + LookupParsedName(Previous, S, &D.getCXXScopeSpec()); + + if (!R->isFunctionType()) { + // C++ [temp.explicit]p1: + // A [...] static data member of a class template can be explicitly + // instantiated from the member definition associated with its class + // template. + if (Previous.isAmbiguous()) + return true; + + VarDecl *Prev = Previous.getAsSingle<VarDecl>(); + if (!Prev || !Prev->isStaticDataMember()) { + // We expect to see a data data member here. + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known) + << Name; + for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); + P != PEnd; ++P) + Diag((*P)->getLocation(), diag::note_explicit_instantiation_here); + return true; + } + + if (!Prev->getInstantiatedFromStaticDataMember()) { + // FIXME: Check for explicit specialization? + Diag(D.getIdentifierLoc(), + diag::err_explicit_instantiation_data_member_not_instantiated) + << Prev; + Diag(Prev->getLocation(), diag::note_explicit_instantiation_here); + // FIXME: Can we provide a note showing where this was declared? + return true; + } + + // C++0x [temp.explicit]p2: + // If the explicit instantiation is for a member function, a member class + // or a static data member of a class template specialization, the name of + // the class template specialization in the qualified-id for the member + // name shall be a simple-template-id. + // + // C++98 has the same restriction, just worded differently. + if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) + Diag(D.getIdentifierLoc(), + diag::ext_explicit_instantiation_without_qualified_id) + << Prev << D.getCXXScopeSpec().getRange(); + + // Check the scope of this explicit instantiation. + CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true); + + // Verify that it is okay to explicitly instantiate here. + MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo(); + assert(MSInfo && "Missing static data member specialization info?"); + bool HasNoEffect = false; + if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + HasNoEffect)) + return true; + if (HasNoEffect) + return (Decl*) 0; + + // Instantiate static data member. + Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); + if (TSK == TSK_ExplicitInstantiationDefinition) + InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev); + + // FIXME: Create an ExplicitInstantiation node? + return (Decl*) 0; + } + + // If the declarator is a template-id, translate the parser's template + // argument list into our AST format. + bool HasExplicitTemplateArgs = false; + TemplateArgumentListInfo TemplateArgs; + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, TemplateArgs); + HasExplicitTemplateArgs = true; + TemplateArgsPtr.release(); + } + + // C++ [temp.explicit]p1: + // A [...] function [...] can be explicitly instantiated from its template. + // A member function [...] of a class template can be explicitly + // instantiated from the member definition associated with its class + // template. + UnresolvedSet<8> Matches; + for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); + P != PEnd; ++P) { + NamedDecl *Prev = *P; + if (!HasExplicitTemplateArgs) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) { + if (Context.hasSameUnqualifiedType(Method->getType(), R)) { + Matches.clear(); + + Matches.addDecl(Method, P.getAccess()); + if (Method->getTemplateSpecializationKind() == TSK_Undeclared) + break; + } + } + } + + FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Prev); + if (!FunTmpl) + continue; + + TemplateDeductionInfo Info(Context, D.getIdentifierLoc()); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult TDK + = DeduceTemplateArguments(FunTmpl, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), + R, Specialization, Info)) { + // FIXME: Keep track of almost-matches? + (void)TDK; + continue; + } + + Matches.addDecl(Specialization, P.getAccess()); + } + + // Find the most specialized function template specialization. + UnresolvedSetIterator Result + = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0, + D.getIdentifierLoc(), + PDiag(diag::err_explicit_instantiation_not_known) << Name, + PDiag(diag::err_explicit_instantiation_ambiguous) << Name, + PDiag(diag::note_explicit_instantiation_candidate)); + + if (Result == Matches.end()) + return true; + + // Ignore access control bits, we don't need them for redeclaration checking. + FunctionDecl *Specialization = cast<FunctionDecl>(*Result); + + if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) { + Diag(D.getIdentifierLoc(), + diag::err_explicit_instantiation_member_function_not_instantiated) + << Specialization + << (Specialization->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization); + Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here); + return true; + } + + FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration(); + if (!PrevDecl && Specialization->isThisDeclarationADefinition()) + PrevDecl = Specialization; + + if (PrevDecl) { + bool HasNoEffect = false; + if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, + PrevDecl, + PrevDecl->getTemplateSpecializationKind(), + PrevDecl->getPointOfInstantiation(), + HasNoEffect)) + return true; + + // FIXME: We may still want to build some representation of this + // explicit specialization. + if (HasNoEffect) + return (Decl*) 0; + } + + Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); + + if (TSK == TSK_ExplicitInstantiationDefinition) + InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization); + + // C++0x [temp.explicit]p2: + // If the explicit instantiation is for a member function, a member class + // or a static data member of a class template specialization, the name of + // the class template specialization in the qualified-id for the member + // name shall be a simple-template-id. + // + // C++98 has the same restriction, just worded differently. + FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate(); + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl && + D.getCXXScopeSpec().isSet() && + !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) + Diag(D.getIdentifierLoc(), + diag::ext_explicit_instantiation_without_qualified_id) + << Specialization << D.getCXXScopeSpec().getRange(); + + CheckExplicitInstantiationScope(*this, + FunTmpl? (NamedDecl *)FunTmpl + : Specialization->getInstantiatedFromMemberFunction(), + D.getIdentifierLoc(), + D.getCXXScopeSpec().isSet()); + + // FIXME: Create some kind of ExplicitInstantiationDecl here. + return (Decl*) 0; +} + +TypeResult +Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + const CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation TagLoc, SourceLocation NameLoc) { + // This has to hold, because SS is expected to be defined. + assert(Name && "Expected a name in a dependent tag"); + + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + if (!NNS) + return true; + + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); + + if (TUK == TUK_Declaration || TUK == TUK_Definition) { + Diag(NameLoc, diag::err_dependent_tag_decl) + << (TUK == TUK_Definition) << Kind << SS.getRange(); + return true; + } + + // Create the resulting type. + ElaboratedTypeKeyword Kwd = TypeWithKeyword::getKeywordForTagTypeKind(Kind); + QualType Result = Context.getDependentNameType(Kwd, NNS, Name); + + // Create type-source location information for this type. + TypeLocBuilder TLB; + DependentNameTypeLoc TL = TLB.push<DependentNameTypeLoc>(Result); + TL.setKeywordLoc(TagLoc); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(NameLoc); + return CreateParsedType(Result, TLB.getTypeSourceInfo(Context, Result)); +} + +TypeResult +Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, const IdentifierInfo &II, + SourceLocation IdLoc) { + if (SS.isInvalid()) + return true; + + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && + !getLangOptions().CPlusPlus0x) + Diag(TypenameLoc, diag::ext_typename_outside_of_template) + << FixItHint::CreateRemoval(TypenameLoc); + + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None, + TypenameLoc, QualifierLoc, II, IdLoc); + if (T.isNull()) + return true; + + TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); + if (isa<DependentNameType>(T)) { + DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + TL.setKeywordLoc(TypenameLoc); + TL.setQualifierLoc(QualifierLoc); + TL.setNameLoc(IdLoc); + } else { + ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); + TL.setKeywordLoc(TypenameLoc); + TL.setQualifierLoc(QualifierLoc); + cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc); + } + + return CreateParsedType(T, TSI); +} + +TypeResult +Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, + TemplateTy TemplateIn, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc) { + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && + !getLangOptions().CPlusPlus0x) + Diag(TypenameLoc, diag::ext_typename_outside_of_template) + << FixItHint::CreateRemoval(TypenameLoc); + + // Translate the parser's template argument list in our AST format. + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); + translateTemplateArguments(TemplateArgsIn, TemplateArgs); + + TemplateName Template = TemplateIn.get(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + // Construct a dependent template specialization type. + assert(DTN && "dependent template has non-dependent name?"); + assert(DTN->getQualifier() + == static_cast<NestedNameSpecifier*>(SS.getScopeRep())); + QualType T = Context.getDependentTemplateSpecializationType(ETK_Typename, + DTN->getQualifier(), + DTN->getIdentifier(), + TemplateArgs); + + // Create source-location information for this type. + TypeLocBuilder Builder; + DependentTemplateSpecializationTypeLoc SpecTL + = Builder.push<DependentTemplateSpecializationTypeLoc>(T); + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setKeywordLoc(TypenameLoc); + SpecTL.setQualifierLoc(SS.getWithLocInContext(Context)); + SpecTL.setNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); + } + + QualType T = CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); + if (T.isNull()) + return true; + + // Provide source-location information for the template specialization + // type. + TypeLocBuilder Builder; + TemplateSpecializationTypeLoc SpecTL + = Builder.push<TemplateSpecializationTypeLoc>(T); + + // FIXME: No place to set the location of the 'template' keyword! + SpecTL.setLAngleLoc(LAngleLoc); + SpecTL.setRAngleLoc(RAngleLoc); + SpecTL.setTemplateNameLoc(TemplateNameLoc); + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + SpecTL.setArgLocInfo(I, TemplateArgs[I].getLocInfo()); + + T = Context.getElaboratedType(ETK_Typename, SS.getScopeRep(), T); + ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T); + TL.setKeywordLoc(TypenameLoc); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + + TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); + return CreateParsedType(T, TSI); +} + + +/// \brief Build the type that describes a C++ typename specifier, +/// e.g., "typename T::type". +QualType +Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, + SourceLocation KeywordLoc, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, + SourceLocation IILoc) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + DeclContext *Ctx = computeDeclContext(SS); + if (!Ctx) { + // If the nested-name-specifier is dependent and couldn't be + // resolved to a type, build a typename type. + assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); + } + + // If the nested-name-specifier refers to the current instantiation, + // the "typename" keyword itself is superfluous. In C++03, the + // program is actually ill-formed. However, DR 382 (in C++0x CD1) + // allows such extraneous "typename" keywords, and we retroactively + // apply this DR to C++03 code with only a warning. In any case we continue. + + if (RequireCompleteDeclContext(SS, Ctx)) + return QualType(); + + DeclarationName Name(&II); + LookupResult Result(*this, Name, IILoc, LookupOrdinaryName); + LookupQualifiedName(Result, Ctx); + unsigned DiagID = 0; + Decl *Referenced = 0; + switch (Result.getResultKind()) { + case LookupResult::NotFound: + DiagID = diag::err_typename_nested_not_found; + break; + + case LookupResult::FoundUnresolvedValue: { + // We found a using declaration that is a value. Most likely, the using + // declaration itself is meant to have the 'typename' keyword. + SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), + IILoc); + Diag(IILoc, diag::err_typename_refers_to_using_value_decl) + << Name << Ctx << FullRange; + if (UnresolvedUsingValueDecl *Using + = dyn_cast<UnresolvedUsingValueDecl>(Result.getRepresentativeDecl())){ + SourceLocation Loc = Using->getQualifierLoc().getBeginLoc(); + Diag(Loc, diag::note_using_value_decl_missing_typename) + << FixItHint::CreateInsertion(Loc, "typename "); + } + } + // Fall through to create a dependent typename type, from which we can recover + // better. + + case LookupResult::NotFoundInCurrentInstantiation: + // Okay, it's a member of an unknown instantiation. + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); + + case LookupResult::Found: + if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { + // We found a type. Build an ElaboratedType, since the + // typename-specifier was just sugar. + return Context.getElaboratedType(ETK_Typename, + QualifierLoc.getNestedNameSpecifier(), + Context.getTypeDeclType(Type)); + } + + DiagID = diag::err_typename_nested_not_type; + Referenced = Result.getFoundDecl(); + break; + + + llvm_unreachable("unresolved using decl in non-dependent context"); + return QualType(); + + case LookupResult::FoundOverloaded: + DiagID = diag::err_typename_nested_not_type; + Referenced = *Result.begin(); + break; + + case LookupResult::Ambiguous: + return QualType(); + } + + // If we get here, it's because name lookup did not find a + // type. Emit an appropriate diagnostic and return an error. + SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), + IILoc); + Diag(IILoc, DiagID) << FullRange << Name << Ctx; + if (Referenced) + Diag(Referenced->getLocation(), diag::note_typename_refers_here) + << Name; + return QualType(); +} + +namespace { + // See Sema::RebuildTypeInCurrentInstantiation + class CurrentInstantiationRebuilder + : public TreeTransform<CurrentInstantiationRebuilder> { + SourceLocation Loc; + DeclarationName Entity; + + public: + typedef TreeTransform<CurrentInstantiationRebuilder> inherited; + + CurrentInstantiationRebuilder(Sema &SemaRef, + SourceLocation Loc, + DeclarationName Entity) + : TreeTransform<CurrentInstantiationRebuilder>(SemaRef), + Loc(Loc), Entity(Entity) { } + + /// \brief Determine whether the given type \p T has already been + /// transformed. + /// + /// For the purposes of type reconstruction, a type has already been + /// transformed if it is NULL or if it is not dependent. + bool AlreadyTransformed(QualType T) { + return T.isNull() || !T->isDependentType(); + } + + /// \brief Returns the location of the entity whose type is being + /// rebuilt. + SourceLocation getBaseLocation() { return Loc; } + + /// \brief Returns the name of the entity whose type is being rebuilt. + DeclarationName getBaseEntity() { return Entity; } + + /// \brief Sets the "base" location and entity when that + /// information is known based on another transformation. + void setBase(SourceLocation Loc, DeclarationName Entity) { + this->Loc = Loc; + this->Entity = Entity; + } + }; +} + +/// \brief Rebuilds a type within the context of the current instantiation. +/// +/// The type \p T is part of the type of an out-of-line member definition of +/// a class template (or class template partial specialization) that was parsed +/// and constructed before we entered the scope of the class template (or +/// partial specialization thereof). This routine will rebuild that type now +/// that we have entered the declarator's scope, which may produce different +/// canonical types, e.g., +/// +/// \code +/// template<typename T> +/// struct X { +/// typedef T* pointer; +/// pointer data(); +/// }; +/// +/// template<typename T> +/// typename X<T>::pointer X<T>::data() { ... } +/// \endcode +/// +/// Here, the type "typename X<T>::pointer" will be created as a DependentNameType, +/// since we do not know that we can look into X<T> when we parsed the type. +/// This function will rebuild the type, performing the lookup of "pointer" +/// in X<T> and returning an ElaboratedType whose canonical type is the same +/// as the canonical type of T*, allowing the return types of the out-of-line +/// definition and the declaration to match. +TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, + SourceLocation Loc, + DeclarationName Name) { + if (!T || !T->getType()->isDependentType()) + return T; + + CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name); + return Rebuilder.TransformType(T); +} + +ExprResult Sema::RebuildExprInCurrentInstantiation(Expr *E) { + CurrentInstantiationRebuilder Rebuilder(*this, E->getExprLoc(), + DeclarationName()); + return Rebuilder.TransformExpr(E); +} + +bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) { + if (SS.isInvalid()) + return true; + + NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); + CurrentInstantiationRebuilder Rebuilder(*this, SS.getRange().getBegin(), + DeclarationName()); + NestedNameSpecifierLoc Rebuilt + = Rebuilder.TransformNestedNameSpecifierLoc(QualifierLoc); + if (!Rebuilt) + return true; + + SS.Adopt(Rebuilt); + return false; +} + +/// \brief Produces a formatted string that describes the binding of +/// template parameters to template arguments. +std::string +Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgumentList &Args) { + return getTemplateArgumentBindingsText(Params, Args.data(), Args.size()); +} + +std::string +Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgument *Args, + unsigned NumArgs) { + llvm::SmallString<128> Str; + llvm::raw_svector_ostream Out(Str); + + if (!Params || Params->size() == 0 || NumArgs == 0) + return std::string(); + + for (unsigned I = 0, N = Params->size(); I != N; ++I) { + if (I >= NumArgs) + break; + + if (I == 0) + Out << "[with "; + else + Out << ", "; + + if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) { + Out << Id->getName(); + } else { + Out << '$' << I; + } + + Out << " = "; + Args[I].print(Context.PrintingPolicy, Out); + } + + Out << ']'; + return Out.str(); +} + +void Sema::MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag) { + if (!FD) + return; + FD->setLateTemplateParsed(Flag); +} + +bool Sema::IsInsideALocalClassWithinATemplateFunction() { + DeclContext *DC = CurContext; + + while (DC) { + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) { + const FunctionDecl *FD = RD->isLocalClass(); + return (FD && FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate); + } else if (DC->isTranslationUnit() || DC->isNamespace()) + return false; + + DC = DC->getParent(); + } + return false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp new file mode 100644 index 0000000..7d0ce8b --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -0,0 +1,4012 @@ +//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements C++ template argument deduction. +// +//===----------------------------------------------------------------------===/ + +#include "clang/Sema/Sema.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/SemaDiagnostic.h" // FIXME: temporary! +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "llvm/ADT/BitVector.h" +#include "TreeTransform.h" +#include <algorithm> + +namespace clang { + using namespace sema; + + /// \brief Various flags that control template argument deduction. + /// + /// These flags can be bitwise-OR'd together. + enum TemplateDeductionFlags { + /// \brief No template argument deduction flags, which indicates the + /// strictest results for template argument deduction (as used for, e.g., + /// matching class template partial specializations). + TDF_None = 0, + /// \brief Within template argument deduction from a function call, we are + /// matching with a parameter type for which the original parameter was + /// a reference. + TDF_ParamWithReferenceType = 0x1, + /// \brief Within template argument deduction from a function call, we + /// are matching in a case where we ignore cv-qualifiers. + TDF_IgnoreQualifiers = 0x02, + /// \brief Within template argument deduction from a function call, + /// we are matching in a case where we can perform template argument + /// deduction from a template-id of a derived class of the argument type. + TDF_DerivedClass = 0x04, + /// \brief Allow non-dependent types to differ, e.g., when performing + /// template argument deduction from a function call where conversions + /// may apply. + TDF_SkipNonDependent = 0x08, + /// \brief Whether we are performing template argument deduction for + /// parameters and arguments in a top-level template argument + TDF_TopLevelParameterTypeList = 0x10 + }; +} + +using namespace clang; + +/// \brief Compare two APSInts, extending and switching the sign as +/// necessary to compare their values regardless of underlying type. +static bool hasSameExtendedValue(llvm::APSInt X, llvm::APSInt Y) { + if (Y.getBitWidth() > X.getBitWidth()) + X = X.extend(Y.getBitWidth()); + else if (Y.getBitWidth() < X.getBitWidth()) + Y = Y.extend(X.getBitWidth()); + + // If there is a signedness mismatch, correct it. + if (X.isSigned() != Y.isSigned()) { + // If the signed value is negative, then the values cannot be the same. + if ((Y.isSigned() && Y.isNegative()) || (X.isSigned() && X.isNegative())) + return false; + + Y.setIsSigned(true); + X.setIsSigned(true); + } + + return X == Y; +} + +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + const TemplateArgument &Param, + TemplateArgument Arg, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced); + +/// \brief Whether template argument deduction for two reference parameters +/// resulted in the argument type, parameter type, or neither type being more +/// qualified than the other. +enum DeductionQualifierComparison { + NeitherMoreQualified = 0, + ParamMoreQualified, + ArgMoreQualified +}; + +/// \brief Stores the result of comparing two reference parameters while +/// performing template argument deduction for partial ordering of function +/// templates. +struct RefParamPartialOrderingComparison { + /// \brief Whether the parameter type is an rvalue reference type. + bool ParamIsRvalueRef; + /// \brief Whether the argument type is an rvalue reference type. + bool ArgIsRvalueRef; + + /// \brief Whether the parameter or argument (or neither) is more qualified. + DeductionQualifierComparison Qualifiers; +}; + + + +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + QualType Param, + QualType Arg, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned TDF, + bool PartialOrdering = false, + llvm::SmallVectorImpl<RefParamPartialOrderingComparison> * + RefParamComparisons = 0); + +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + const TemplateArgument *Params, unsigned NumParams, + const TemplateArgument *Args, unsigned NumArgs, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + bool NumberOfArgumentsMustMatch = true); + +/// \brief If the given expression is of a form that permits the deduction +/// of a non-type template parameter, return the declaration of that +/// non-type template parameter. +static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) { + if (ImplicitCastExpr *IC = dyn_cast<ImplicitCastExpr>(E)) + E = IC->getSubExpr(); + + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + return dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); + + return 0; +} + +/// \brief Determine whether two declaration pointers refer to the same +/// declaration. +static bool isSameDeclaration(Decl *X, Decl *Y) { + if (!X || !Y) + return !X && !Y; + + if (NamedDecl *NX = dyn_cast<NamedDecl>(X)) + X = NX->getUnderlyingDecl(); + if (NamedDecl *NY = dyn_cast<NamedDecl>(Y)) + Y = NY->getUnderlyingDecl(); + + return X->getCanonicalDecl() == Y->getCanonicalDecl(); +} + +/// \brief Verify that the given, deduced template arguments are compatible. +/// +/// \returns The deduced template argument, or a NULL template argument if +/// the deduced template arguments were incompatible. +static DeducedTemplateArgument +checkDeducedTemplateArguments(ASTContext &Context, + const DeducedTemplateArgument &X, + const DeducedTemplateArgument &Y) { + // We have no deduction for one or both of the arguments; they're compatible. + if (X.isNull()) + return Y; + if (Y.isNull()) + return X; + + switch (X.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Non-deduced template arguments handled above"); + + case TemplateArgument::Type: + // If two template type arguments have the same type, they're compatible. + if (Y.getKind() == TemplateArgument::Type && + Context.hasSameType(X.getAsType(), Y.getAsType())) + return X; + + return DeducedTemplateArgument(); + + case TemplateArgument::Integral: + // If we deduced a constant in one case and either a dependent expression or + // declaration in another case, keep the integral constant. + // If both are integral constants with the same value, keep that value. + if (Y.getKind() == TemplateArgument::Expression || + Y.getKind() == TemplateArgument::Declaration || + (Y.getKind() == TemplateArgument::Integral && + hasSameExtendedValue(*X.getAsIntegral(), *Y.getAsIntegral()))) + return DeducedTemplateArgument(X, + X.wasDeducedFromArrayBound() && + Y.wasDeducedFromArrayBound()); + + // All other combinations are incompatible. + return DeducedTemplateArgument(); + + case TemplateArgument::Template: + if (Y.getKind() == TemplateArgument::Template && + Context.hasSameTemplateName(X.getAsTemplate(), Y.getAsTemplate())) + return X; + + // All other combinations are incompatible. + return DeducedTemplateArgument(); + + case TemplateArgument::TemplateExpansion: + if (Y.getKind() == TemplateArgument::TemplateExpansion && + Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(), + Y.getAsTemplateOrTemplatePattern())) + return X; + + // All other combinations are incompatible. + return DeducedTemplateArgument(); + + case TemplateArgument::Expression: + // If we deduced a dependent expression in one case and either an integral + // constant or a declaration in another case, keep the integral constant + // or declaration. + if (Y.getKind() == TemplateArgument::Integral || + Y.getKind() == TemplateArgument::Declaration) + return DeducedTemplateArgument(Y, X.wasDeducedFromArrayBound() && + Y.wasDeducedFromArrayBound()); + + if (Y.getKind() == TemplateArgument::Expression) { + // Compare the expressions for equality + llvm::FoldingSetNodeID ID1, ID2; + X.getAsExpr()->Profile(ID1, Context, true); + Y.getAsExpr()->Profile(ID2, Context, true); + if (ID1 == ID2) + return X; + } + + // All other combinations are incompatible. + return DeducedTemplateArgument(); + + case TemplateArgument::Declaration: + // If we deduced a declaration and a dependent expression, keep the + // declaration. + if (Y.getKind() == TemplateArgument::Expression) + return X; + + // If we deduced a declaration and an integral constant, keep the + // integral constant. + if (Y.getKind() == TemplateArgument::Integral) + return Y; + + // If we deduced two declarations, make sure they they refer to the + // same declaration. + if (Y.getKind() == TemplateArgument::Declaration && + isSameDeclaration(X.getAsDecl(), Y.getAsDecl())) + return X; + + // All other combinations are incompatible. + return DeducedTemplateArgument(); + + case TemplateArgument::Pack: + if (Y.getKind() != TemplateArgument::Pack || + X.pack_size() != Y.pack_size()) + return DeducedTemplateArgument(); + + for (TemplateArgument::pack_iterator XA = X.pack_begin(), + XAEnd = X.pack_end(), + YA = Y.pack_begin(); + XA != XAEnd; ++XA, ++YA) { + if (checkDeducedTemplateArguments(Context, + DeducedTemplateArgument(*XA, X.wasDeducedFromArrayBound()), + DeducedTemplateArgument(*YA, Y.wasDeducedFromArrayBound())) + .isNull()) + return DeducedTemplateArgument(); + } + + return X; + } + + return DeducedTemplateArgument(); +} + +/// \brief Deduce the value of the given non-type template parameter +/// from the given constant. +static Sema::TemplateDeductionResult +DeduceNonTypeTemplateArgument(Sema &S, + NonTypeTemplateParmDecl *NTTP, + llvm::APSInt Value, QualType ValueType, + bool DeducedFromArrayBound, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument with depth > 0"); + + DeducedTemplateArgument NewDeduced(Value, ValueType, DeducedFromArrayBound); + DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, + Deduced[NTTP->getIndex()], + NewDeduced); + if (Result.isNull()) { + Info.Param = NTTP; + Info.FirstArg = Deduced[NTTP->getIndex()]; + Info.SecondArg = NewDeduced; + return Sema::TDK_Inconsistent; + } + + Deduced[NTTP->getIndex()] = Result; + return Sema::TDK_Success; +} + +/// \brief Deduce the value of the given non-type template parameter +/// from the given type- or value-dependent expression. +/// +/// \returns true if deduction succeeded, false otherwise. +static Sema::TemplateDeductionResult +DeduceNonTypeTemplateArgument(Sema &S, + NonTypeTemplateParmDecl *NTTP, + Expr *Value, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument with depth > 0"); + assert((Value->isTypeDependent() || Value->isValueDependent()) && + "Expression template argument must be type- or value-dependent."); + + DeducedTemplateArgument NewDeduced(Value); + DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, + Deduced[NTTP->getIndex()], + NewDeduced); + + if (Result.isNull()) { + Info.Param = NTTP; + Info.FirstArg = Deduced[NTTP->getIndex()]; + Info.SecondArg = NewDeduced; + return Sema::TDK_Inconsistent; + } + + Deduced[NTTP->getIndex()] = Result; + return Sema::TDK_Success; +} + +/// \brief Deduce the value of the given non-type template parameter +/// from the given declaration. +/// +/// \returns true if deduction succeeded, false otherwise. +static Sema::TemplateDeductionResult +DeduceNonTypeTemplateArgument(Sema &S, + NonTypeTemplateParmDecl *NTTP, + Decl *D, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument with depth > 0"); + + DeducedTemplateArgument NewDeduced(D? D->getCanonicalDecl() : 0); + DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, + Deduced[NTTP->getIndex()], + NewDeduced); + if (Result.isNull()) { + Info.Param = NTTP; + Info.FirstArg = Deduced[NTTP->getIndex()]; + Info.SecondArg = NewDeduced; + return Sema::TDK_Inconsistent; + } + + Deduced[NTTP->getIndex()] = Result; + return Sema::TDK_Success; +} + +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + TemplateName Param, + TemplateName Arg, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + TemplateDecl *ParamDecl = Param.getAsTemplateDecl(); + if (!ParamDecl) { + // The parameter type is dependent and is not a template template parameter, + // so there is nothing that we can deduce. + return Sema::TDK_Success; + } + + if (TemplateTemplateParmDecl *TempParam + = dyn_cast<TemplateTemplateParmDecl>(ParamDecl)) { + DeducedTemplateArgument NewDeduced(S.Context.getCanonicalTemplateName(Arg)); + DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, + Deduced[TempParam->getIndex()], + NewDeduced); + if (Result.isNull()) { + Info.Param = TempParam; + Info.FirstArg = Deduced[TempParam->getIndex()]; + Info.SecondArg = NewDeduced; + return Sema::TDK_Inconsistent; + } + + Deduced[TempParam->getIndex()] = Result; + return Sema::TDK_Success; + } + + // Verify that the two template names are equivalent. + if (S.Context.hasSameTemplateName(Param, Arg)) + return Sema::TDK_Success; + + // Mismatch of non-dependent template parameter to argument. + Info.FirstArg = TemplateArgument(Param); + Info.SecondArg = TemplateArgument(Arg); + return Sema::TDK_NonDeducedMismatch; +} + +/// \brief Deduce the template arguments by comparing the template parameter +/// type (which is a template-id) with the template argument type. +/// +/// \param S the Sema +/// +/// \param TemplateParams the template parameters that we are deducing +/// +/// \param Param the parameter type +/// +/// \param Arg the argument type +/// +/// \param Info information about the template argument deduction itself +/// +/// \param Deduced the deduced template arguments +/// +/// \returns the result of template argument deduction so far. Note that a +/// "success" result means that template argument deduction has not yet failed, +/// but it may still fail, later, for other reasons. +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + const TemplateSpecializationType *Param, + QualType Arg, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + assert(Arg.isCanonical() && "Argument type must be canonical"); + + // Check whether the template argument is a dependent template-id. + if (const TemplateSpecializationType *SpecArg + = dyn_cast<TemplateSpecializationType>(Arg)) { + // Perform template argument deduction for the template name. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + Param->getTemplateName(), + SpecArg->getTemplateName(), + Info, Deduced)) + return Result; + + + // Perform template argument deduction on each template + // argument. Ignore any missing/extra arguments, since they could be + // filled in by default arguments. + return DeduceTemplateArguments(S, TemplateParams, + Param->getArgs(), Param->getNumArgs(), + SpecArg->getArgs(), SpecArg->getNumArgs(), + Info, Deduced, + /*NumberOfArgumentsMustMatch=*/false); + } + + // If the argument type is a class template specialization, we + // perform template argument deduction using its template + // arguments. + const RecordType *RecordArg = dyn_cast<RecordType>(Arg); + if (!RecordArg) + return Sema::TDK_NonDeducedMismatch; + + ClassTemplateSpecializationDecl *SpecArg + = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl()); + if (!SpecArg) + return Sema::TDK_NonDeducedMismatch; + + // Perform template argument deduction for the template name. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, + TemplateParams, + Param->getTemplateName(), + TemplateName(SpecArg->getSpecializedTemplate()), + Info, Deduced)) + return Result; + + // Perform template argument deduction for the template arguments. + return DeduceTemplateArguments(S, TemplateParams, + Param->getArgs(), Param->getNumArgs(), + SpecArg->getTemplateArgs().data(), + SpecArg->getTemplateArgs().size(), + Info, Deduced); +} + +/// \brief Determines whether the given type is an opaque type that +/// might be more qualified when instantiated. +static bool IsPossiblyOpaquelyQualifiedType(QualType T) { + switch (T->getTypeClass()) { + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::DependentName: + case Type::Decltype: + case Type::UnresolvedUsing: + case Type::TemplateTypeParm: + return true; + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + return IsPossiblyOpaquelyQualifiedType( + cast<ArrayType>(T)->getElementType()); + + default: + return false; + } +} + +/// \brief Retrieve the depth and index of a template parameter. +static std::pair<unsigned, unsigned> +getDepthAndIndex(NamedDecl *ND) { + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND)) + return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); + + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND); + return std::make_pair(TTP->getDepth(), TTP->getIndex()); +} + +/// \brief Retrieve the depth and index of an unexpanded parameter pack. +static std::pair<unsigned, unsigned> +getDepthAndIndex(UnexpandedParameterPack UPP) { + if (const TemplateTypeParmType *TTP + = UPP.first.dyn_cast<const TemplateTypeParmType *>()) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + return getDepthAndIndex(UPP.first.get<NamedDecl *>()); +} + +/// \brief Helper function to build a TemplateParameter when we don't +/// know its type statically. +static TemplateParameter makeTemplateParameter(Decl *D) { + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D)) + return TemplateParameter(TTP); + else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) + return TemplateParameter(NTTP); + + return TemplateParameter(cast<TemplateTemplateParmDecl>(D)); +} + +/// \brief Prepare to perform template argument deduction for all of the +/// arguments in a set of argument packs. +static void PrepareArgumentPackDeduction(Sema &S, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + const llvm::SmallVectorImpl<unsigned> &PackIndices, + llvm::SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, + llvm::SmallVectorImpl< + llvm::SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks) { + // Save the deduced template arguments for each parameter pack expanded + // by this pack expansion, then clear out the deduction. + for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) { + // Save the previously-deduced argument pack, then clear it out so that we + // can deduce a new argument pack. + SavedPacks[I] = Deduced[PackIndices[I]]; + Deduced[PackIndices[I]] = TemplateArgument(); + + // If the template arugment pack was explicitly specified, add that to + // the set of deduced arguments. + const TemplateArgument *ExplicitArgs; + unsigned NumExplicitArgs; + if (NamedDecl *PartiallySubstitutedPack + = S.CurrentInstantiationScope->getPartiallySubstitutedPack( + &ExplicitArgs, + &NumExplicitArgs)) { + if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I]) + NewlyDeducedPacks[I].append(ExplicitArgs, + ExplicitArgs + NumExplicitArgs); + } + } +} + +/// \brief Finish template argument deduction for a set of argument packs, +/// producing the argument packs and checking for consistency with prior +/// deductions. +static Sema::TemplateDeductionResult +FinishArgumentPackDeduction(Sema &S, + TemplateParameterList *TemplateParams, + bool HasAnyArguments, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + const llvm::SmallVectorImpl<unsigned> &PackIndices, + llvm::SmallVectorImpl<DeducedTemplateArgument> &SavedPacks, + llvm::SmallVectorImpl< + llvm::SmallVector<DeducedTemplateArgument, 4> > &NewlyDeducedPacks, + TemplateDeductionInfo &Info) { + // Build argument packs for each of the parameter packs expanded by this + // pack expansion. + for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) { + if (HasAnyArguments && NewlyDeducedPacks[I].empty()) { + // We were not able to deduce anything for this parameter pack, + // so just restore the saved argument pack. + Deduced[PackIndices[I]] = SavedPacks[I]; + continue; + } + + DeducedTemplateArgument NewPack; + + if (NewlyDeducedPacks[I].empty()) { + // If we deduced an empty argument pack, create it now. + NewPack = DeducedTemplateArgument(TemplateArgument(0, 0)); + } else { + TemplateArgument *ArgumentPack + = new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()]; + std::copy(NewlyDeducedPacks[I].begin(), NewlyDeducedPacks[I].end(), + ArgumentPack); + NewPack + = DeducedTemplateArgument(TemplateArgument(ArgumentPack, + NewlyDeducedPacks[I].size()), + NewlyDeducedPacks[I][0].wasDeducedFromArrayBound()); + } + + DeducedTemplateArgument Result + = checkDeducedTemplateArguments(S.Context, SavedPacks[I], NewPack); + if (Result.isNull()) { + Info.Param + = makeTemplateParameter(TemplateParams->getParam(PackIndices[I])); + Info.FirstArg = SavedPacks[I]; + Info.SecondArg = NewPack; + return Sema::TDK_Inconsistent; + } + + Deduced[PackIndices[I]] = Result; + } + + return Sema::TDK_Success; +} + +/// \brief Deduce the template arguments by comparing the list of parameter +/// types to the list of argument types, as in the parameter-type-lists of +/// function types (C++ [temp.deduct.type]p10). +/// +/// \param S The semantic analysis object within which we are deducing +/// +/// \param TemplateParams The template parameters that we are deducing +/// +/// \param Params The list of parameter types +/// +/// \param NumParams The number of types in \c Params +/// +/// \param Args The list of argument types +/// +/// \param NumArgs The number of types in \c Args +/// +/// \param Info information about the template argument deduction itself +/// +/// \param Deduced the deduced template arguments +/// +/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe +/// how template argument deduction is performed. +/// +/// \param PartialOrdering If true, we are performing template argument +/// deduction for during partial ordering for a call +/// (C++0x [temp.deduct.partial]). +/// +/// \param RefParamComparisons If we're performing template argument deduction +/// in the context of partial ordering, the set of qualifier comparisons. +/// +/// \returns the result of template argument deduction so far. Note that a +/// "success" result means that template argument deduction has not yet failed, +/// but it may still fail, later, for other reasons. +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + const QualType *Params, unsigned NumParams, + const QualType *Args, unsigned NumArgs, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned TDF, + bool PartialOrdering = false, + llvm::SmallVectorImpl<RefParamPartialOrderingComparison> * + RefParamComparisons = 0) { + // Fast-path check to see if we have too many/too few arguments. + if (NumParams != NumArgs && + !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) && + !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1]))) + return Sema::TDK_NonDeducedMismatch; + + // C++0x [temp.deduct.type]p10: + // Similarly, if P has a form that contains (T), then each parameter type + // Pi of the respective parameter-type- list of P is compared with the + // corresponding parameter type Ai of the corresponding parameter-type-list + // of A. [...] + unsigned ArgIdx = 0, ParamIdx = 0; + for (; ParamIdx != NumParams; ++ParamIdx) { + // Check argument types. + const PackExpansionType *Expansion + = dyn_cast<PackExpansionType>(Params[ParamIdx]); + if (!Expansion) { + // Simple case: compare the parameter and argument types at this point. + + // Make sure we have an argument. + if (ArgIdx >= NumArgs) + return Sema::TDK_NonDeducedMismatch; + + if (isa<PackExpansionType>(Args[ArgIdx])) { + // C++0x [temp.deduct.type]p22: + // If the original function parameter associated with A is a function + // parameter pack and the function parameter associated with P is not + // a function parameter pack, then template argument deduction fails. + return Sema::TDK_NonDeducedMismatch; + } + + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + Params[ParamIdx], + Args[ArgIdx], + Info, Deduced, TDF, + PartialOrdering, + RefParamComparisons)) + return Result; + + ++ArgIdx; + continue; + } + + // C++0x [temp.deduct.type]p5: + // The non-deduced contexts are: + // - A function parameter pack that does not occur at the end of the + // parameter-declaration-clause. + if (ParamIdx + 1 < NumParams) + return Sema::TDK_Success; + + // C++0x [temp.deduct.type]p10: + // If the parameter-declaration corresponding to Pi is a function + // parameter pack, then the type of its declarator- id is compared with + // each remaining parameter type in the parameter-type-list of A. Each + // comparison deduces template arguments for subsequent positions in the + // template parameter packs expanded by the function parameter pack. + + // Compute the set of template parameter indices that correspond to + // parameter packs expanded by the pack expansion. + llvm::SmallVector<unsigned, 2> PackIndices; + QualType Pattern = Expansion->getPattern(); + { + llvm::BitVector SawIndices(TemplateParams->size()); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + S.collectUnexpandedParameterPacks(Pattern, Unexpanded); + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { + unsigned Depth, Index; + llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]); + if (Depth == 0 && !SawIndices[Index]) { + SawIndices[Index] = true; + PackIndices.push_back(Index); + } + } + } + assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?"); + + // Keep track of the deduced template arguments for each parameter pack + // expanded by this pack expansion (the outer index) and for each + // template argument (the inner SmallVectors). + llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2> + NewlyDeducedPacks(PackIndices.size()); + llvm::SmallVector<DeducedTemplateArgument, 2> + SavedPacks(PackIndices.size()); + PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks, + NewlyDeducedPacks); + + bool HasAnyArguments = false; + for (; ArgIdx < NumArgs; ++ArgIdx) { + HasAnyArguments = true; + + // Deduce template arguments from the pattern. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx], + Info, Deduced, TDF, PartialOrdering, + RefParamComparisons)) + return Result; + + // Capture the deduced template arguments for each parameter pack expanded + // by this pack expansion, add them to the list of arguments we've deduced + // for that pack, then clear out the deduced argument. + for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) { + DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]]; + if (!DeducedArg.isNull()) { + NewlyDeducedPacks[I].push_back(DeducedArg); + DeducedArg = DeducedTemplateArgument(); + } + } + } + + // Build argument packs for each of the parameter packs expanded by this + // pack expansion. + if (Sema::TemplateDeductionResult Result + = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments, + Deduced, PackIndices, SavedPacks, + NewlyDeducedPacks, Info)) + return Result; + } + + // Make sure we don't have any extra arguments. + if (ArgIdx < NumArgs) + return Sema::TDK_NonDeducedMismatch; + + return Sema::TDK_Success; +} + +/// \brief Determine whether the parameter has qualifiers that are either +/// inconsistent with or a superset of the argument's qualifiers. +static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType, + QualType ArgType) { + Qualifiers ParamQs = ParamType.getQualifiers(); + Qualifiers ArgQs = ArgType.getQualifiers(); + + if (ParamQs == ArgQs) + return false; + + // Mismatched (but not missing) Objective-C GC attributes. + if (ParamQs.getObjCGCAttr() != ArgQs.getObjCGCAttr() && + ParamQs.hasObjCGCAttr()) + return true; + + // Mismatched (but not missing) address spaces. + if (ParamQs.getAddressSpace() != ArgQs.getAddressSpace() && + ParamQs.hasAddressSpace()) + return true; + + // CVR qualifier superset. + return (ParamQs.getCVRQualifiers() != ArgQs.getCVRQualifiers()) && + ((ParamQs.getCVRQualifiers() | ArgQs.getCVRQualifiers()) + == ParamQs.getCVRQualifiers()); +} + +/// \brief Deduce the template arguments by comparing the parameter type and +/// the argument type (C++ [temp.deduct.type]). +/// +/// \param S the semantic analysis object within which we are deducing +/// +/// \param TemplateParams the template parameters that we are deducing +/// +/// \param ParamIn the parameter type +/// +/// \param ArgIn the argument type +/// +/// \param Info information about the template argument deduction itself +/// +/// \param Deduced the deduced template arguments +/// +/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe +/// how template argument deduction is performed. +/// +/// \param PartialOrdering Whether we're performing template argument deduction +/// in the context of partial ordering (C++0x [temp.deduct.partial]). +/// +/// \param RefParamComparisons If we're performing template argument deduction +/// in the context of partial ordering, the set of qualifier comparisons. +/// +/// \returns the result of template argument deduction so far. Note that a +/// "success" result means that template argument deduction has not yet failed, +/// but it may still fail, later, for other reasons. +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + QualType ParamIn, QualType ArgIn, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned TDF, + bool PartialOrdering, + llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) { + // We only want to look at the canonical types, since typedefs and + // sugar are not part of template argument deduction. + QualType Param = S.Context.getCanonicalType(ParamIn); + QualType Arg = S.Context.getCanonicalType(ArgIn); + + // If the argument type is a pack expansion, look at its pattern. + // This isn't explicitly called out + if (const PackExpansionType *ArgExpansion + = dyn_cast<PackExpansionType>(Arg)) + Arg = ArgExpansion->getPattern(); + + if (PartialOrdering) { + // C++0x [temp.deduct.partial]p5: + // Before the partial ordering is done, certain transformations are + // performed on the types used for partial ordering: + // - If P is a reference type, P is replaced by the type referred to. + const ReferenceType *ParamRef = Param->getAs<ReferenceType>(); + if (ParamRef) + Param = ParamRef->getPointeeType(); + + // - If A is a reference type, A is replaced by the type referred to. + const ReferenceType *ArgRef = Arg->getAs<ReferenceType>(); + if (ArgRef) + Arg = ArgRef->getPointeeType(); + + if (RefParamComparisons && ParamRef && ArgRef) { + // C++0x [temp.deduct.partial]p6: + // If both P and A were reference types (before being replaced with the + // type referred to above), determine which of the two types (if any) is + // more cv-qualified than the other; otherwise the types are considered + // to be equally cv-qualified for partial ordering purposes. The result + // of this determination will be used below. + // + // We save this information for later, using it only when deduction + // succeeds in both directions. + RefParamPartialOrderingComparison Comparison; + Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>(); + Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>(); + Comparison.Qualifiers = NeitherMoreQualified; + + Qualifiers ParamQuals = Param.getQualifiers(); + Qualifiers ArgQuals = Arg.getQualifiers(); + if (ParamQuals.isStrictSupersetOf(ArgQuals)) + Comparison.Qualifiers = ParamMoreQualified; + else if (ArgQuals.isStrictSupersetOf(ParamQuals)) + Comparison.Qualifiers = ArgMoreQualified; + RefParamComparisons->push_back(Comparison); + } + + // C++0x [temp.deduct.partial]p7: + // Remove any top-level cv-qualifiers: + // - If P is a cv-qualified type, P is replaced by the cv-unqualified + // version of P. + Param = Param.getUnqualifiedType(); + // - If A is a cv-qualified type, A is replaced by the cv-unqualified + // version of A. + Arg = Arg.getUnqualifiedType(); + } else { + // C++0x [temp.deduct.call]p4 bullet 1: + // - If the original P is a reference type, the deduced A (i.e., the type + // referred to by the reference) can be more cv-qualified than the + // transformed A. + if (TDF & TDF_ParamWithReferenceType) { + Qualifiers Quals; + QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals); + Quals.setCVRQualifiers(Quals.getCVRQualifiers() & + Arg.getCVRQualifiers()); + Param = S.Context.getQualifiedType(UnqualParam, Quals); + } + + if ((TDF & TDF_TopLevelParameterTypeList) && !Param->isFunctionType()) { + // C++0x [temp.deduct.type]p10: + // If P and A are function types that originated from deduction when + // taking the address of a function template (14.8.2.2) or when deducing + // template arguments from a function declaration (14.8.2.6) and Pi and + // Ai are parameters of the top-level parameter-type-list of P and A, + // respectively, Pi is adjusted if it is an rvalue reference to a + // cv-unqualified template parameter and Ai is an lvalue reference, in + // which case the type of Pi is changed to be the template parameter + // type (i.e., T&& is changed to simply T). [ Note: As a result, when + // Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be + // deduced as X&. - end note ] + TDF &= ~TDF_TopLevelParameterTypeList; + + if (const RValueReferenceType *ParamRef + = Param->getAs<RValueReferenceType>()) { + if (isa<TemplateTypeParmType>(ParamRef->getPointeeType()) && + !ParamRef->getPointeeType().getQualifiers()) + if (Arg->isLValueReferenceType()) + Param = ParamRef->getPointeeType(); + } + } + } + + // If the parameter type is not dependent, there is nothing to deduce. + if (!Param->isDependentType()) { + if (!(TDF & TDF_SkipNonDependent) && Param != Arg) + return Sema::TDK_NonDeducedMismatch; + + return Sema::TDK_Success; + } + + // C++ [temp.deduct.type]p9: + // A template type argument T, a template template argument TT or a + // template non-type argument i can be deduced if P and A have one of + // the following forms: + // + // T + // cv-list T + if (const TemplateTypeParmType *TemplateTypeParm + = Param->getAs<TemplateTypeParmType>()) { + unsigned Index = TemplateTypeParm->getIndex(); + bool RecanonicalizeArg = false; + + // If the argument type is an array type, move the qualifiers up to the + // top level, so they can be matched with the qualifiers on the parameter. + if (isa<ArrayType>(Arg)) { + Qualifiers Quals; + Arg = S.Context.getUnqualifiedArrayType(Arg, Quals); + if (Quals) { + Arg = S.Context.getQualifiedType(Arg, Quals); + RecanonicalizeArg = true; + } + } + + // The argument type can not be less qualified than the parameter + // type. + if (!(TDF & TDF_IgnoreQualifiers) && + hasInconsistentOrSupersetQualifiersOf(Param, Arg)) { + Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index)); + Info.FirstArg = TemplateArgument(Param); + Info.SecondArg = TemplateArgument(Arg); + return Sema::TDK_Underqualified; + } + + assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0"); + assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function"); + QualType DeducedType = Arg; + + // Remove any qualifiers on the parameter from the deduced type. + // We checked the qualifiers for consistency above. + Qualifiers DeducedQs = DeducedType.getQualifiers(); + Qualifiers ParamQs = Param.getQualifiers(); + DeducedQs.removeCVRQualifiers(ParamQs.getCVRQualifiers()); + if (ParamQs.hasObjCGCAttr()) + DeducedQs.removeObjCGCAttr(); + if (ParamQs.hasAddressSpace()) + DeducedQs.removeAddressSpace(); + DeducedType = S.Context.getQualifiedType(DeducedType.getUnqualifiedType(), + DeducedQs); + + if (RecanonicalizeArg) + DeducedType = S.Context.getCanonicalType(DeducedType); + + DeducedTemplateArgument NewDeduced(DeducedType); + DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, + Deduced[Index], + NewDeduced); + if (Result.isNull()) { + Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index)); + Info.FirstArg = Deduced[Index]; + Info.SecondArg = NewDeduced; + return Sema::TDK_Inconsistent; + } + + Deduced[Index] = Result; + return Sema::TDK_Success; + } + + // Set up the template argument deduction information for a failure. + Info.FirstArg = TemplateArgument(ParamIn); + Info.SecondArg = TemplateArgument(ArgIn); + + // If the parameter is an already-substituted template parameter + // pack, do nothing: we don't know which of its arguments to look + // at, so we have to wait until all of the parameter packs in this + // expansion have arguments. + if (isa<SubstTemplateTypeParmPackType>(Param)) + return Sema::TDK_Success; + + // Check the cv-qualifiers on the parameter and argument types. + if (!(TDF & TDF_IgnoreQualifiers)) { + if (TDF & TDF_ParamWithReferenceType) { + if (hasInconsistentOrSupersetQualifiersOf(Param, Arg)) + return Sema::TDK_NonDeducedMismatch; + } else if (!IsPossiblyOpaquelyQualifiedType(Param)) { + if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) + return Sema::TDK_NonDeducedMismatch; + } + } + + switch (Param->getTypeClass()) { + // No deduction possible for these types + case Type::Builtin: + return Sema::TDK_NonDeducedMismatch; + + // T * + case Type::Pointer: { + QualType PointeeType; + if (const PointerType *PointerArg = Arg->getAs<PointerType>()) { + PointeeType = PointerArg->getPointeeType(); + } else if (const ObjCObjectPointerType *PointerArg + = Arg->getAs<ObjCObjectPointerType>()) { + PointeeType = PointerArg->getPointeeType(); + } else { + return Sema::TDK_NonDeducedMismatch; + } + + unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass); + return DeduceTemplateArguments(S, TemplateParams, + cast<PointerType>(Param)->getPointeeType(), + PointeeType, + Info, Deduced, SubTDF); + } + + // T & + case Type::LValueReference: { + const LValueReferenceType *ReferenceArg = Arg->getAs<LValueReferenceType>(); + if (!ReferenceArg) + return Sema::TDK_NonDeducedMismatch; + + return DeduceTemplateArguments(S, TemplateParams, + cast<LValueReferenceType>(Param)->getPointeeType(), + ReferenceArg->getPointeeType(), + Info, Deduced, 0); + } + + // T && [C++0x] + case Type::RValueReference: { + const RValueReferenceType *ReferenceArg = Arg->getAs<RValueReferenceType>(); + if (!ReferenceArg) + return Sema::TDK_NonDeducedMismatch; + + return DeduceTemplateArguments(S, TemplateParams, + cast<RValueReferenceType>(Param)->getPointeeType(), + ReferenceArg->getPointeeType(), + Info, Deduced, 0); + } + + // T [] (implied, but not stated explicitly) + case Type::IncompleteArray: { + const IncompleteArrayType *IncompleteArrayArg = + S.Context.getAsIncompleteArrayType(Arg); + if (!IncompleteArrayArg) + return Sema::TDK_NonDeducedMismatch; + + unsigned SubTDF = TDF & TDF_IgnoreQualifiers; + return DeduceTemplateArguments(S, TemplateParams, + S.Context.getAsIncompleteArrayType(Param)->getElementType(), + IncompleteArrayArg->getElementType(), + Info, Deduced, SubTDF); + } + + // T [integer-constant] + case Type::ConstantArray: { + const ConstantArrayType *ConstantArrayArg = + S.Context.getAsConstantArrayType(Arg); + if (!ConstantArrayArg) + return Sema::TDK_NonDeducedMismatch; + + const ConstantArrayType *ConstantArrayParm = + S.Context.getAsConstantArrayType(Param); + if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize()) + return Sema::TDK_NonDeducedMismatch; + + unsigned SubTDF = TDF & TDF_IgnoreQualifiers; + return DeduceTemplateArguments(S, TemplateParams, + ConstantArrayParm->getElementType(), + ConstantArrayArg->getElementType(), + Info, Deduced, SubTDF); + } + + // type [i] + case Type::DependentSizedArray: { + const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg); + if (!ArrayArg) + return Sema::TDK_NonDeducedMismatch; + + unsigned SubTDF = TDF & TDF_IgnoreQualifiers; + + // Check the element type of the arrays + const DependentSizedArrayType *DependentArrayParm + = S.Context.getAsDependentSizedArrayType(Param); + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + DependentArrayParm->getElementType(), + ArrayArg->getElementType(), + Info, Deduced, SubTDF)) + return Result; + + // Determine the array bound is something we can deduce. + NonTypeTemplateParmDecl *NTTP + = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr()); + if (!NTTP) + return Sema::TDK_Success; + + // We can perform template argument deduction for the given non-type + // template parameter. + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument at depth > 0"); + if (const ConstantArrayType *ConstantArrayArg + = dyn_cast<ConstantArrayType>(ArrayArg)) { + llvm::APSInt Size(ConstantArrayArg->getSize()); + return DeduceNonTypeTemplateArgument(S, NTTP, Size, + S.Context.getSizeType(), + /*ArrayBound=*/true, + Info, Deduced); + } + if (const DependentSizedArrayType *DependentArrayArg + = dyn_cast<DependentSizedArrayType>(ArrayArg)) + if (DependentArrayArg->getSizeExpr()) + return DeduceNonTypeTemplateArgument(S, NTTP, + DependentArrayArg->getSizeExpr(), + Info, Deduced); + + // Incomplete type does not match a dependently-sized array type + return Sema::TDK_NonDeducedMismatch; + } + + // type(*)(T) + // T(*)() + // T(*)(T) + case Type::FunctionProto: { + unsigned SubTDF = TDF & TDF_TopLevelParameterTypeList; + const FunctionProtoType *FunctionProtoArg = + dyn_cast<FunctionProtoType>(Arg); + if (!FunctionProtoArg) + return Sema::TDK_NonDeducedMismatch; + + const FunctionProtoType *FunctionProtoParam = + cast<FunctionProtoType>(Param); + + if (FunctionProtoParam->getTypeQuals() + != FunctionProtoArg->getTypeQuals() || + FunctionProtoParam->getRefQualifier() + != FunctionProtoArg->getRefQualifier() || + FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic()) + return Sema::TDK_NonDeducedMismatch; + + // Check return types. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + FunctionProtoParam->getResultType(), + FunctionProtoArg->getResultType(), + Info, Deduced, 0)) + return Result; + + return DeduceTemplateArguments(S, TemplateParams, + FunctionProtoParam->arg_type_begin(), + FunctionProtoParam->getNumArgs(), + FunctionProtoArg->arg_type_begin(), + FunctionProtoArg->getNumArgs(), + Info, Deduced, SubTDF); + } + + case Type::InjectedClassName: { + // Treat a template's injected-class-name as if the template + // specialization type had been used. + Param = cast<InjectedClassNameType>(Param) + ->getInjectedSpecializationType(); + assert(isa<TemplateSpecializationType>(Param) && + "injected class name is not a template specialization type"); + // fall through + } + + // template-name<T> (where template-name refers to a class template) + // template-name<i> + // TT<T> + // TT<i> + // TT<> + case Type::TemplateSpecialization: { + const TemplateSpecializationType *SpecParam + = cast<TemplateSpecializationType>(Param); + + // Try to deduce template arguments from the template-id. + Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg, + Info, Deduced); + + if (Result && (TDF & TDF_DerivedClass)) { + // C++ [temp.deduct.call]p3b3: + // If P is a class, and P has the form template-id, then A can be a + // derived class of the deduced A. Likewise, if P is a pointer to a + // class of the form template-id, A can be a pointer to a derived + // class pointed to by the deduced A. + // + // More importantly: + // These alternatives are considered only if type deduction would + // otherwise fail. + if (const RecordType *RecordT = Arg->getAs<RecordType>()) { + // We cannot inspect base classes as part of deduction when the type + // is incomplete, so either instantiate any templates necessary to + // complete the type, or skip over it if it cannot be completed. + if (S.RequireCompleteType(Info.getLocation(), Arg, 0)) + return Result; + + // Use data recursion to crawl through the list of base classes. + // Visited contains the set of nodes we have already visited, while + // ToVisit is our stack of records that we still need to visit. + llvm::SmallPtrSet<const RecordType *, 8> Visited; + llvm::SmallVector<const RecordType *, 8> ToVisit; + ToVisit.push_back(RecordT); + bool Successful = false; + llvm::SmallVectorImpl<DeducedTemplateArgument> DeducedOrig(0); + DeducedOrig = Deduced; + while (!ToVisit.empty()) { + // Retrieve the next class in the inheritance hierarchy. + const RecordType *NextT = ToVisit.back(); + ToVisit.pop_back(); + + // If we have already seen this type, skip it. + if (!Visited.insert(NextT)) + continue; + + // If this is a base class, try to perform template argument + // deduction from it. + if (NextT != RecordT) { + Sema::TemplateDeductionResult BaseResult + = DeduceTemplateArguments(S, TemplateParams, SpecParam, + QualType(NextT, 0), Info, Deduced); + + // If template argument deduction for this base was successful, + // note that we had some success. Otherwise, ignore any deductions + // from this base class. + if (BaseResult == Sema::TDK_Success) { + Successful = true; + DeducedOrig = Deduced; + } + else + Deduced = DeducedOrig; + } + + // Visit base classes + CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl()); + for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(), + BaseEnd = Next->bases_end(); + Base != BaseEnd; ++Base) { + assert(Base->getType()->isRecordType() && + "Base class that isn't a record?"); + ToVisit.push_back(Base->getType()->getAs<RecordType>()); + } + } + + if (Successful) + return Sema::TDK_Success; + } + + } + + return Result; + } + + // T type::* + // T T::* + // T (type::*)() + // type (T::*)() + // type (type::*)(T) + // type (T::*)(T) + // T (type::*)(T) + // T (T::*)() + // T (T::*)(T) + case Type::MemberPointer: { + const MemberPointerType *MemPtrParam = cast<MemberPointerType>(Param); + const MemberPointerType *MemPtrArg = dyn_cast<MemberPointerType>(Arg); + if (!MemPtrArg) + return Sema::TDK_NonDeducedMismatch; + + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + MemPtrParam->getPointeeType(), + MemPtrArg->getPointeeType(), + Info, Deduced, + TDF & TDF_IgnoreQualifiers)) + return Result; + + return DeduceTemplateArguments(S, TemplateParams, + QualType(MemPtrParam->getClass(), 0), + QualType(MemPtrArg->getClass(), 0), + Info, Deduced, 0); + } + + // (clang extension) + // + // type(^)(T) + // T(^)() + // T(^)(T) + case Type::BlockPointer: { + const BlockPointerType *BlockPtrParam = cast<BlockPointerType>(Param); + const BlockPointerType *BlockPtrArg = dyn_cast<BlockPointerType>(Arg); + + if (!BlockPtrArg) + return Sema::TDK_NonDeducedMismatch; + + return DeduceTemplateArguments(S, TemplateParams, + BlockPtrParam->getPointeeType(), + BlockPtrArg->getPointeeType(), Info, + Deduced, 0); + } + + case Type::TypeOfExpr: + case Type::TypeOf: + case Type::DependentName: + // No template argument deduction for these types + return Sema::TDK_Success; + + default: + break; + } + + // FIXME: Many more cases to go (to go). + return Sema::TDK_Success; +} + +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + const TemplateArgument &Param, + TemplateArgument Arg, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + // If the template argument is a pack expansion, perform template argument + // deduction against the pattern of that expansion. This only occurs during + // partial ordering. + if (Arg.isPackExpansion()) + Arg = Arg.getPackExpansionPattern(); + + switch (Param.getKind()) { + case TemplateArgument::Null: + assert(false && "Null template argument in parameter list"); + break; + + case TemplateArgument::Type: + if (Arg.getKind() == TemplateArgument::Type) + return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(), + Arg.getAsType(), Info, Deduced, 0); + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + + case TemplateArgument::Template: + if (Arg.getKind() == TemplateArgument::Template) + return DeduceTemplateArguments(S, TemplateParams, + Param.getAsTemplate(), + Arg.getAsTemplate(), Info, Deduced); + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + + case TemplateArgument::TemplateExpansion: + llvm_unreachable("caller should handle pack expansions"); + break; + + case TemplateArgument::Declaration: + if (Arg.getKind() == TemplateArgument::Declaration && + Param.getAsDecl()->getCanonicalDecl() == + Arg.getAsDecl()->getCanonicalDecl()) + return Sema::TDK_Success; + + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + + case TemplateArgument::Integral: + if (Arg.getKind() == TemplateArgument::Integral) { + if (hasSameExtendedValue(*Param.getAsIntegral(), *Arg.getAsIntegral())) + return Sema::TDK_Success; + + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + } + + if (Arg.getKind() == TemplateArgument::Expression) { + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + } + + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + + case TemplateArgument::Expression: { + if (NonTypeTemplateParmDecl *NTTP + = getDeducedParameterFromExpr(Param.getAsExpr())) { + if (Arg.getKind() == TemplateArgument::Integral) + return DeduceNonTypeTemplateArgument(S, NTTP, + *Arg.getAsIntegral(), + Arg.getIntegralType(), + /*ArrayBound=*/false, + Info, Deduced); + if (Arg.getKind() == TemplateArgument::Expression) + return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(), + Info, Deduced); + if (Arg.getKind() == TemplateArgument::Declaration) + return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(), + Info, Deduced); + + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + } + + // Can't deduce anything, but that's okay. + return Sema::TDK_Success; + } + case TemplateArgument::Pack: + llvm_unreachable("Argument packs should be expanded by the caller!"); + } + + return Sema::TDK_Success; +} + +/// \brief Determine whether there is a template argument to be used for +/// deduction. +/// +/// This routine "expands" argument packs in-place, overriding its input +/// parameters so that \c Args[ArgIdx] will be the available template argument. +/// +/// \returns true if there is another template argument (which will be at +/// \c Args[ArgIdx]), false otherwise. +static bool hasTemplateArgumentForDeduction(const TemplateArgument *&Args, + unsigned &ArgIdx, + unsigned &NumArgs) { + if (ArgIdx == NumArgs) + return false; + + const TemplateArgument &Arg = Args[ArgIdx]; + if (Arg.getKind() != TemplateArgument::Pack) + return true; + + assert(ArgIdx == NumArgs - 1 && "Pack not at the end of argument list?"); + Args = Arg.pack_begin(); + NumArgs = Arg.pack_size(); + ArgIdx = 0; + return ArgIdx < NumArgs; +} + +/// \brief Determine whether the given set of template arguments has a pack +/// expansion that is not the last template argument. +static bool hasPackExpansionBeforeEnd(const TemplateArgument *Args, + unsigned NumArgs) { + unsigned ArgIdx = 0; + while (ArgIdx < NumArgs) { + const TemplateArgument &Arg = Args[ArgIdx]; + + // Unwrap argument packs. + if (Args[ArgIdx].getKind() == TemplateArgument::Pack) { + Args = Arg.pack_begin(); + NumArgs = Arg.pack_size(); + ArgIdx = 0; + continue; + } + + ++ArgIdx; + if (ArgIdx == NumArgs) + return false; + + if (Arg.isPackExpansion()) + return true; + } + + return false; +} + +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + const TemplateArgument *Params, unsigned NumParams, + const TemplateArgument *Args, unsigned NumArgs, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + bool NumberOfArgumentsMustMatch) { + // C++0x [temp.deduct.type]p9: + // If the template argument list of P contains a pack expansion that is not + // the last template argument, the entire template argument list is a + // non-deduced context. + if (hasPackExpansionBeforeEnd(Params, NumParams)) + return Sema::TDK_Success; + + // C++0x [temp.deduct.type]p9: + // If P has a form that contains <T> or <i>, then each argument Pi of the + // respective template argument list P is compared with the corresponding + // argument Ai of the corresponding template argument list of A. + unsigned ArgIdx = 0, ParamIdx = 0; + for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams); + ++ParamIdx) { + if (!Params[ParamIdx].isPackExpansion()) { + // The simple case: deduce template arguments by matching Pi and Ai. + + // Check whether we have enough arguments. + if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) + return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch + : Sema::TDK_Success; + + if (Args[ArgIdx].isPackExpansion()) { + // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here, + // but applied to pack expansions that are template arguments. + return Sema::TDK_NonDeducedMismatch; + } + + // Perform deduction for this Pi/Ai pair. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + Params[ParamIdx], Args[ArgIdx], + Info, Deduced)) + return Result; + + // Move to the next argument. + ++ArgIdx; + continue; + } + + // The parameter is a pack expansion. + + // C++0x [temp.deduct.type]p9: + // If Pi is a pack expansion, then the pattern of Pi is compared with + // each remaining argument in the template argument list of A. Each + // comparison deduces template arguments for subsequent positions in the + // template parameter packs expanded by Pi. + TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern(); + + // Compute the set of template parameter indices that correspond to + // parameter packs expanded by the pack expansion. + llvm::SmallVector<unsigned, 2> PackIndices; + { + llvm::BitVector SawIndices(TemplateParams->size()); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + S.collectUnexpandedParameterPacks(Pattern, Unexpanded); + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { + unsigned Depth, Index; + llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]); + if (Depth == 0 && !SawIndices[Index]) { + SawIndices[Index] = true; + PackIndices.push_back(Index); + } + } + } + assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?"); + + // FIXME: If there are no remaining arguments, we can bail out early + // and set any deduced parameter packs to an empty argument pack. + // The latter part of this is a (minor) correctness issue. + + // Save the deduced template arguments for each parameter pack expanded + // by this pack expansion, then clear out the deduction. + llvm::SmallVector<DeducedTemplateArgument, 2> + SavedPacks(PackIndices.size()); + llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2> + NewlyDeducedPacks(PackIndices.size()); + PrepareArgumentPackDeduction(S, Deduced, PackIndices, SavedPacks, + NewlyDeducedPacks); + + // Keep track of the deduced template arguments for each parameter pack + // expanded by this pack expansion (the outer index) and for each + // template argument (the inner SmallVectors). + bool HasAnyArguments = false; + while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) { + HasAnyArguments = true; + + // Deduce template arguments from the pattern. + if (Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx], + Info, Deduced)) + return Result; + + // Capture the deduced template arguments for each parameter pack expanded + // by this pack expansion, add them to the list of arguments we've deduced + // for that pack, then clear out the deduced argument. + for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) { + DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]]; + if (!DeducedArg.isNull()) { + NewlyDeducedPacks[I].push_back(DeducedArg); + DeducedArg = DeducedTemplateArgument(); + } + } + + ++ArgIdx; + } + + // Build argument packs for each of the parameter packs expanded by this + // pack expansion. + if (Sema::TemplateDeductionResult Result + = FinishArgumentPackDeduction(S, TemplateParams, HasAnyArguments, + Deduced, PackIndices, SavedPacks, + NewlyDeducedPacks, Info)) + return Result; + } + + // If there is an argument remaining, then we had too many arguments. + if (NumberOfArgumentsMustMatch && + hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) + return Sema::TDK_NonDeducedMismatch; + + return Sema::TDK_Success; +} + +static Sema::TemplateDeductionResult +DeduceTemplateArguments(Sema &S, + TemplateParameterList *TemplateParams, + const TemplateArgumentList &ParamList, + const TemplateArgumentList &ArgList, + TemplateDeductionInfo &Info, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced) { + return DeduceTemplateArguments(S, TemplateParams, + ParamList.data(), ParamList.size(), + ArgList.data(), ArgList.size(), + Info, Deduced); +} + +/// \brief Determine whether two template arguments are the same. +static bool isSameTemplateArg(ASTContext &Context, + const TemplateArgument &X, + const TemplateArgument &Y) { + if (X.getKind() != Y.getKind()) + return false; + + switch (X.getKind()) { + case TemplateArgument::Null: + assert(false && "Comparing NULL template argument"); + break; + + case TemplateArgument::Type: + return Context.getCanonicalType(X.getAsType()) == + Context.getCanonicalType(Y.getAsType()); + + case TemplateArgument::Declaration: + return X.getAsDecl()->getCanonicalDecl() == + Y.getAsDecl()->getCanonicalDecl(); + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + return Context.getCanonicalTemplateName( + X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() == + Context.getCanonicalTemplateName( + Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer(); + + case TemplateArgument::Integral: + return *X.getAsIntegral() == *Y.getAsIntegral(); + + case TemplateArgument::Expression: { + llvm::FoldingSetNodeID XID, YID; + X.getAsExpr()->Profile(XID, Context, true); + Y.getAsExpr()->Profile(YID, Context, true); + return XID == YID; + } + + case TemplateArgument::Pack: + if (X.pack_size() != Y.pack_size()) + return false; + + for (TemplateArgument::pack_iterator XP = X.pack_begin(), + XPEnd = X.pack_end(), + YP = Y.pack_begin(); + XP != XPEnd; ++XP, ++YP) + if (!isSameTemplateArg(Context, *XP, *YP)) + return false; + + return true; + } + + return false; +} + +/// \brief Allocate a TemplateArgumentLoc where all locations have +/// been initialized to the given location. +/// +/// \param S The semantic analysis object. +/// +/// \param The template argument we are producing template argument +/// location information for. +/// +/// \param NTTPType For a declaration template argument, the type of +/// the non-type template parameter that corresponds to this template +/// argument. +/// +/// \param Loc The source location to use for the resulting template +/// argument. +static TemplateArgumentLoc +getTrivialTemplateArgumentLoc(Sema &S, + const TemplateArgument &Arg, + QualType NTTPType, + SourceLocation Loc) { + switch (Arg.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("Can't get a NULL template argument here"); + break; + + case TemplateArgument::Type: + return TemplateArgumentLoc(Arg, + S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc)); + + case TemplateArgument::Declaration: { + Expr *E + = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc) + .takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case TemplateArgument::Integral: { + Expr *E + = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(S.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(S.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + return TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(S.Context), + Loc); + + + return TemplateArgumentLoc(Arg, Builder.getWithLocInContext(S.Context), + Loc, Loc); + } + + case TemplateArgument::Expression: + return TemplateArgumentLoc(Arg, Arg.getAsExpr()); + + case TemplateArgument::Pack: + return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); + } + + return TemplateArgumentLoc(); +} + + +/// \brief Convert the given deduced template argument and add it to the set of +/// fully-converted template arguments. +static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, + DeducedTemplateArgument Arg, + NamedDecl *Template, + QualType NTTPType, + unsigned ArgumentPackIndex, + TemplateDeductionInfo &Info, + bool InFunctionTemplate, + llvm::SmallVectorImpl<TemplateArgument> &Output) { + if (Arg.getKind() == TemplateArgument::Pack) { + // This is a template argument pack, so check each of its arguments against + // the template parameter. + llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder; + for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), + PAEnd = Arg.pack_end(); + PA != PAEnd; ++PA) { + // When converting the deduced template argument, append it to the + // general output list. We need to do this so that the template argument + // checking logic has all of the prior template arguments available. + DeducedTemplateArgument InnerArg(*PA); + InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound()); + if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template, + NTTPType, PackedArgsBuilder.size(), + Info, InFunctionTemplate, Output)) + return true; + + // Move the converted template argument into our argument pack. + PackedArgsBuilder.push_back(Output.back()); + Output.pop_back(); + } + + // Create the resulting argument pack. + Output.push_back(TemplateArgument::CreatePackCopy(S.Context, + PackedArgsBuilder.data(), + PackedArgsBuilder.size())); + return false; + } + + // Convert the deduced template argument into a template + // argument that we can check, almost as if the user had written + // the template argument explicitly. + TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType, + Info.getLocation()); + + // Check the template argument, converting it as necessary. + return S.CheckTemplateArgument(Param, ArgLoc, + Template, + Template->getLocation(), + Template->getSourceRange().getEnd(), + ArgumentPackIndex, + Output, + InFunctionTemplate + ? (Arg.wasDeducedFromArrayBound() + ? Sema::CTAK_DeducedFromArrayBound + : Sema::CTAK_Deduced) + : Sema::CTAK_Specified); +} + +/// Complete template argument deduction for a class template partial +/// specialization. +static Sema::TemplateDeductionResult +FinishTemplateArgumentDeduction(Sema &S, + ClassTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + TemplateDeductionInfo &Info) { + // Trap errors. + Sema::SFINAETrap Trap(S); + + Sema::ContextRAII SavedContext(S, Partial); + + // C++ [temp.deduct.type]p2: + // [...] or if any template argument remains neither deduced nor + // explicitly specified, template argument deduction fails. + llvm::SmallVector<TemplateArgument, 4> Builder; + TemplateParameterList *PartialParams = Partial->getTemplateParameters(); + for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) { + NamedDecl *Param = PartialParams->getParam(I); + if (Deduced[I].isNull()) { + Info.Param = makeTemplateParameter(Param); + return Sema::TDK_Incomplete; + } + + // We have deduced this argument, so it still needs to be + // checked and converted. + + // First, for a non-type template parameter type that is + // initialized by a declaration, we need the type of the + // corresponding non-type template parameter. + QualType NTTPType; + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + NTTPType = NTTP->getType(); + if (NTTPType->isDependentType()) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Builder.data(), Builder.size()); + NTTPType = S.SubstType(NTTPType, + MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), + NTTP->getDeclName()); + if (NTTPType.isNull()) { + Info.Param = makeTemplateParameter(Param); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(S.Context, + Builder.data(), + Builder.size())); + return Sema::TDK_SubstitutionFailure; + } + } + } + + if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], + Partial, NTTPType, 0, Info, false, + Builder)) { + Info.Param = makeTemplateParameter(Param); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(), + Builder.size())); + return Sema::TDK_SubstitutionFailure; + } + } + + // Form the template argument list from the deduced template arguments. + TemplateArgumentList *DeducedArgumentList + = TemplateArgumentList::CreateCopy(S.Context, Builder.data(), + Builder.size()); + + Info.reset(DeducedArgumentList); + + // Substitute the deduced template arguments into the template + // arguments of the class template partial specialization, and + // verify that the instantiated template arguments are both valid + // and are equivalent to the template arguments originally provided + // to the class template. + LocalInstantiationScope InstScope(S); + ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate(); + const TemplateArgumentLoc *PartialTemplateArgs + = Partial->getTemplateArgsAsWritten(); + + // Note that we don't provide the langle and rangle locations. + TemplateArgumentListInfo InstArgs; + + if (S.Subst(PartialTemplateArgs, + Partial->getNumTemplateArgsAsWritten(), + InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) { + unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx; + if (ParamIdx >= Partial->getTemplateParameters()->size()) + ParamIdx = Partial->getTemplateParameters()->size() - 1; + + Decl *Param + = const_cast<NamedDecl *>( + Partial->getTemplateParameters()->getParam(ParamIdx)); + Info.Param = makeTemplateParameter(Param); + Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument(); + return Sema::TDK_SubstitutionFailure; + } + + llvm::SmallVector<TemplateArgument, 4> ConvertedInstArgs; + if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(), + InstArgs, false, ConvertedInstArgs)) + return Sema::TDK_SubstitutionFailure; + + TemplateParameterList *TemplateParams + = ClassTemplate->getTemplateParameters(); + for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { + TemplateArgument InstArg = ConvertedInstArgs.data()[I]; + if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) { + Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); + Info.FirstArg = TemplateArgs[I]; + Info.SecondArg = InstArg; + return Sema::TDK_NonDeducedMismatch; + } + } + + if (Trap.hasErrorOccurred()) + return Sema::TDK_SubstitutionFailure; + + return Sema::TDK_Success; +} + +/// \brief Perform template argument deduction to determine whether +/// the given template arguments match the given class template +/// partial specialization per C++ [temp.class.spec.match]. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs, + TemplateDeductionInfo &Info) { + // C++ [temp.class.spec.match]p2: + // A partial specialization matches a given actual template + // argument list if the template arguments of the partial + // specialization can be deduced from the actual template argument + // list (14.8.2). + SFINAETrap Trap(*this); + llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; + Deduced.resize(Partial->getTemplateParameters()->size()); + if (TemplateDeductionResult Result + = ::DeduceTemplateArguments(*this, + Partial->getTemplateParameters(), + Partial->getTemplateArgs(), + TemplateArgs, Info, Deduced)) + return Result; + + InstantiatingTemplate Inst(*this, Partial->getLocation(), Partial, + Deduced.data(), Deduced.size(), Info); + if (Inst) + return TDK_InstantiationDepth; + + if (Trap.hasErrorOccurred()) + return Sema::TDK_SubstitutionFailure; + + return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs, + Deduced, Info); +} + +/// \brief Determine whether the given type T is a simple-template-id type. +static bool isSimpleTemplateIdType(QualType T) { + if (const TemplateSpecializationType *Spec + = T->getAs<TemplateSpecializationType>()) + return Spec->getTemplateName().getAsTemplateDecl() != 0; + + return false; +} + +/// \brief Substitute the explicitly-provided template arguments into the +/// given function template according to C++ [temp.arg.explicit]. +/// +/// \param FunctionTemplate the function template into which the explicit +/// template arguments will be substituted. +/// +/// \param ExplicitTemplateArguments the explicitly-specified template +/// arguments. +/// +/// \param Deduced the deduced template arguments, which will be populated +/// with the converted and checked explicit template arguments. +/// +/// \param ParamTypes will be populated with the instantiated function +/// parameters. +/// +/// \param FunctionType if non-NULL, the result type of the function template +/// will also be instantiated and the pointed-to value will be updated with +/// the instantiated function type. +/// +/// \param Info if substitution fails for any reason, this object will be +/// populated with more information about the failure. +/// +/// \returns TDK_Success if substitution was successful, or some failure +/// condition. +Sema::TemplateDeductionResult +Sema::SubstituteExplicitTemplateArguments( + FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo &ExplicitTemplateArgs, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + llvm::SmallVectorImpl<QualType> &ParamTypes, + QualType *FunctionType, + TemplateDeductionInfo &Info) { + FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + TemplateParameterList *TemplateParams + = FunctionTemplate->getTemplateParameters(); + + if (ExplicitTemplateArgs.size() == 0) { + // No arguments to substitute; just copy over the parameter types and + // fill in the function type. + for (FunctionDecl::param_iterator P = Function->param_begin(), + PEnd = Function->param_end(); + P != PEnd; + ++P) + ParamTypes.push_back((*P)->getType()); + + if (FunctionType) + *FunctionType = Function->getType(); + return TDK_Success; + } + + // Substitution of the explicit template arguments into a function template + /// is a SFINAE context. Trap any errors that might occur. + SFINAETrap Trap(*this); + + // C++ [temp.arg.explicit]p3: + // Template arguments that are present shall be specified in the + // declaration order of their corresponding template-parameters. The + // template argument list shall not specify more template-arguments than + // there are corresponding template-parameters. + llvm::SmallVector<TemplateArgument, 4> Builder; + + // Enter a new template instantiation context where we check the + // explicitly-specified template arguments against this function template, + // and then substitute them into the function parameter types. + InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), + FunctionTemplate, Deduced.data(), Deduced.size(), + ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution, + Info); + if (Inst) + return TDK_InstantiationDepth; + + if (CheckTemplateArgumentList(FunctionTemplate, + SourceLocation(), + ExplicitTemplateArgs, + true, + Builder) || Trap.hasErrorOccurred()) { + unsigned Index = Builder.size(); + if (Index >= TemplateParams->size()) + Index = TemplateParams->size() - 1; + Info.Param = makeTemplateParameter(TemplateParams->getParam(Index)); + return TDK_InvalidExplicitArguments; + } + + // Form the template argument list from the explicitly-specified + // template arguments. + TemplateArgumentList *ExplicitArgumentList + = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size()); + Info.reset(ExplicitArgumentList); + + // Template argument deduction and the final substitution should be + // done in the context of the templated declaration. Explicit + // argument substitution, on the other hand, needs to happen in the + // calling context. + ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl()); + + // If we deduced template arguments for a template parameter pack, + // note that the template argument pack is partially substituted and record + // the explicit template arguments. They'll be used as part of deduction + // for this template parameter pack. + for (unsigned I = 0, N = Builder.size(); I != N; ++I) { + const TemplateArgument &Arg = Builder[I]; + if (Arg.getKind() == TemplateArgument::Pack) { + CurrentInstantiationScope->SetPartiallySubstitutedPack( + TemplateParams->getParam(I), + Arg.pack_begin(), + Arg.pack_size()); + break; + } + } + + // Instantiate the types of each of the function parameters given the + // explicitly-specified template arguments. + if (SubstParmTypes(Function->getLocation(), + Function->param_begin(), Function->getNumParams(), + MultiLevelTemplateArgumentList(*ExplicitArgumentList), + ParamTypes)) + return TDK_SubstitutionFailure; + + // If the caller wants a full function type back, instantiate the return + // type and form that function type. + if (FunctionType) { + // FIXME: exception-specifications? + const FunctionProtoType *Proto + = Function->getType()->getAs<FunctionProtoType>(); + assert(Proto && "Function template does not have a prototype?"); + + QualType ResultType + = SubstType(Proto->getResultType(), + MultiLevelTemplateArgumentList(*ExplicitArgumentList), + Function->getTypeSpecStartLoc(), + Function->getDeclName()); + if (ResultType.isNull() || Trap.hasErrorOccurred()) + return TDK_SubstitutionFailure; + + *FunctionType = BuildFunctionType(ResultType, + ParamTypes.data(), ParamTypes.size(), + Proto->isVariadic(), + Proto->getTypeQuals(), + Proto->getRefQualifier(), + Function->getLocation(), + Function->getDeclName(), + Proto->getExtInfo()); + if (FunctionType->isNull() || Trap.hasErrorOccurred()) + return TDK_SubstitutionFailure; + } + + // C++ [temp.arg.explicit]p2: + // Trailing template arguments that can be deduced (14.8.2) may be + // omitted from the list of explicit template-arguments. If all of the + // template arguments can be deduced, they may all be omitted; in this + // case, the empty template argument list <> itself may also be omitted. + // + // Take all of the explicitly-specified arguments and put them into + // the set of deduced template arguments. Explicitly-specified + // parameter packs, however, will be set to NULL since the deduction + // mechanisms handle explicitly-specified argument packs directly. + Deduced.reserve(TemplateParams->size()); + for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) { + const TemplateArgument &Arg = ExplicitArgumentList->get(I); + if (Arg.getKind() == TemplateArgument::Pack) + Deduced.push_back(DeducedTemplateArgument()); + else + Deduced.push_back(Arg); + } + + return TDK_Success; +} + +/// \brief Finish template argument deduction for a function template, +/// checking the deduced template arguments for completeness and forming +/// the function template specialization. +Sema::TemplateDeductionResult +Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, + llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, + unsigned NumExplicitlySpecified, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info) { + TemplateParameterList *TemplateParams + = FunctionTemplate->getTemplateParameters(); + + // Template argument deduction for function templates in a SFINAE context. + // Trap any errors that might occur. + SFINAETrap Trap(*this); + + // Enter a new template instantiation context while we instantiate the + // actual function declaration. + InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), + FunctionTemplate, Deduced.data(), Deduced.size(), + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution, + Info); + if (Inst) + return TDK_InstantiationDepth; + + ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl()); + + // C++ [temp.deduct.type]p2: + // [...] or if any template argument remains neither deduced nor + // explicitly specified, template argument deduction fails. + llvm::SmallVector<TemplateArgument, 4> Builder; + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + NamedDecl *Param = TemplateParams->getParam(I); + + if (!Deduced[I].isNull()) { + if (I < NumExplicitlySpecified) { + // We have already fully type-checked and converted this + // argument, because it was explicitly-specified. Just record the + // presence of this argument. + Builder.push_back(Deduced[I]); + continue; + } + + // We have deduced this argument, so it still needs to be + // checked and converted. + + // First, for a non-type template parameter type that is + // initialized by a declaration, we need the type of the + // corresponding non-type template parameter. + QualType NTTPType; + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + NTTPType = NTTP->getType(); + if (NTTPType->isDependentType()) { + TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, + Builder.data(), Builder.size()); + NTTPType = SubstType(NTTPType, + MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), + NTTP->getDeclName()); + if (NTTPType.isNull()) { + Info.Param = makeTemplateParameter(Param); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(Context, + Builder.data(), + Builder.size())); + return TDK_SubstitutionFailure; + } + } + } + + if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I], + FunctionTemplate, NTTPType, 0, Info, + true, Builder)) { + Info.Param = makeTemplateParameter(Param); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), + Builder.size())); + return TDK_SubstitutionFailure; + } + + continue; + } + + // C++0x [temp.arg.explicit]p3: + // A trailing template parameter pack (14.5.3) not otherwise deduced will + // be deduced to an empty sequence of template arguments. + // FIXME: Where did the word "trailing" come from? + if (Param->isTemplateParameterPack()) { + // We may have had explicitly-specified template arguments for this + // template parameter pack. If so, our empty deduction extends the + // explicitly-specified set (C++0x [temp.arg.explicit]p9). + const TemplateArgument *ExplicitArgs; + unsigned NumExplicitArgs; + if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs, + &NumExplicitArgs) + == Param) + Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs)); + else + Builder.push_back(TemplateArgument(0, 0)); + + continue; + } + + // Substitute into the default template argument, if available. + TemplateArgumentLoc DefArg + = SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + Param, + Builder); + + // If there was no default argument, deduction is incomplete. + if (DefArg.getArgument().isNull()) { + Info.Param = makeTemplateParameter( + const_cast<NamedDecl *>(TemplateParams->getParam(I))); + return TDK_Incomplete; + } + + // Check whether we can actually use the default argument. + if (CheckTemplateArgument(Param, DefArg, + FunctionTemplate, + FunctionTemplate->getLocation(), + FunctionTemplate->getSourceRange().getEnd(), + 0, Builder, + CTAK_Specified)) { + Info.Param = makeTemplateParameter( + const_cast<NamedDecl *>(TemplateParams->getParam(I))); + // FIXME: These template arguments are temporary. Free them! + Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), + Builder.size())); + return TDK_SubstitutionFailure; + } + + // If we get here, we successfully used the default template argument. + } + + // Form the template argument list from the deduced template arguments. + TemplateArgumentList *DeducedArgumentList + = TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size()); + Info.reset(DeducedArgumentList); + + // Substitute the deduced template arguments into the function template + // declaration to produce the function template specialization. + DeclContext *Owner = FunctionTemplate->getDeclContext(); + if (FunctionTemplate->getFriendObjectKind()) + Owner = FunctionTemplate->getLexicalDeclContext(); + Specialization = cast_or_null<FunctionDecl>( + SubstDecl(FunctionTemplate->getTemplatedDecl(), Owner, + MultiLevelTemplateArgumentList(*DeducedArgumentList))); + if (!Specialization) + return TDK_SubstitutionFailure; + + assert(Specialization->getPrimaryTemplate()->getCanonicalDecl() == + FunctionTemplate->getCanonicalDecl()); + + // If the template argument list is owned by the function template + // specialization, release it. + if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList && + !Trap.hasErrorOccurred()) + Info.take(); + + // There may have been an error that did not prevent us from constructing a + // declaration. Mark the declaration invalid and return with a substitution + // failure. + if (Trap.hasErrorOccurred()) { + Specialization->setInvalidDecl(true); + return TDK_SubstitutionFailure; + } + + // If we suppressed any diagnostics while performing template argument + // deduction, and if we haven't already instantiated this declaration, + // keep track of these diagnostics. They'll be emitted if this specialization + // is actually used. + if (Info.diag_begin() != Info.diag_end()) { + llvm::DenseMap<Decl *, llvm::SmallVector<PartialDiagnosticAt, 1> >::iterator + Pos = SuppressedDiagnostics.find(Specialization->getCanonicalDecl()); + if (Pos == SuppressedDiagnostics.end()) + SuppressedDiagnostics[Specialization->getCanonicalDecl()] + .append(Info.diag_begin(), Info.diag_end()); + } + + return TDK_Success; +} + +/// Gets the type of a function for template-argument-deducton +/// purposes when it's considered as part of an overload set. +static QualType GetTypeOfFunction(ASTContext &Context, + const OverloadExpr::FindResult &R, + FunctionDecl *Fn) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) + if (Method->isInstance()) { + // An instance method that's referenced in a form that doesn't + // look like a member pointer is just invalid. + if (!R.HasFormOfMemberPointer) return QualType(); + + return Context.getMemberPointerType(Fn->getType(), + Context.getTypeDeclType(Method->getParent()).getTypePtr()); + } + + if (!R.IsAddressOfOperand) return Fn->getType(); + return Context.getPointerType(Fn->getType()); +} + +/// Apply the deduction rules for overload sets. +/// +/// \return the null type if this argument should be treated as an +/// undeduced context +static QualType +ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, + Expr *Arg, QualType ParamType, + bool ParamWasReference) { + + OverloadExpr::FindResult R = OverloadExpr::find(Arg); + + OverloadExpr *Ovl = R.Expression; + + // C++0x [temp.deduct.call]p4 + unsigned TDF = 0; + if (ParamWasReference) + TDF |= TDF_ParamWithReferenceType; + if (R.IsAddressOfOperand) + TDF |= TDF_IgnoreQualifiers; + + // If there were explicit template arguments, we can only find + // something via C++ [temp.arg.explicit]p3, i.e. if the arguments + // unambiguously name a full specialization. + if (Ovl->hasExplicitTemplateArgs()) { + // But we can still look for an explicit specialization. + if (FunctionDecl *ExplicitSpec + = S.ResolveSingleFunctionTemplateSpecialization(Ovl)) + return GetTypeOfFunction(S.Context, R, ExplicitSpec); + return QualType(); + } + + // C++0x [temp.deduct.call]p6: + // When P is a function type, pointer to function type, or pointer + // to member function type: + + if (!ParamType->isFunctionType() && + !ParamType->isFunctionPointerType() && + !ParamType->isMemberFunctionPointerType()) + return QualType(); + + QualType Match; + for (UnresolvedSetIterator I = Ovl->decls_begin(), + E = Ovl->decls_end(); I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + + // - If the argument is an overload set containing one or more + // function templates, the parameter is treated as a + // non-deduced context. + if (isa<FunctionTemplateDecl>(D)) + return QualType(); + + FunctionDecl *Fn = cast<FunctionDecl>(D); + QualType ArgType = GetTypeOfFunction(S.Context, R, Fn); + if (ArgType.isNull()) continue; + + // Function-to-pointer conversion. + if (!ParamWasReference && ParamType->isPointerType() && + ArgType->isFunctionType()) + ArgType = S.Context.getPointerType(ArgType); + + // - If the argument is an overload set (not containing function + // templates), trial argument deduction is attempted using each + // of the members of the set. If deduction succeeds for only one + // of the overload set members, that member is used as the + // argument value for the deduction. If deduction succeeds for + // more than one member of the overload set the parameter is + // treated as a non-deduced context. + + // We do all of this in a fresh context per C++0x [temp.deduct.type]p2: + // Type deduction is done independently for each P/A pair, and + // the deduced template argument values are then combined. + // So we do not reject deductions which were made elsewhere. + llvm::SmallVector<DeducedTemplateArgument, 8> + Deduced(TemplateParams->size()); + TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc()); + Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + ParamType, ArgType, + Info, Deduced, TDF); + if (Result) continue; + if (!Match.isNull()) return QualType(); + Match = ArgType; + } + + return Match; +} + +/// \brief Perform the adjustments to the parameter and argument types +/// described in C++ [temp.deduct.call]. +/// +/// \returns true if the caller should not attempt to perform any template +/// argument deduction based on this P/A pair. +static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, + TemplateParameterList *TemplateParams, + QualType &ParamType, + QualType &ArgType, + Expr *Arg, + unsigned &TDF) { + // C++0x [temp.deduct.call]p3: + // If P is a cv-qualified type, the top level cv-qualifiers of P's type + // are ignored for type deduction. + if (ParamType.hasQualifiers()) + ParamType = ParamType.getUnqualifiedType(); + const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>(); + if (ParamRefType) { + QualType PointeeType = ParamRefType->getPointeeType(); + + // If the argument has incomplete array type, try to complete it's type. + if (ArgType->isIncompleteArrayType() && + !S.RequireCompleteExprType(Arg, S.PDiag(), + std::make_pair(SourceLocation(), S.PDiag()))) + ArgType = Arg->getType(); + + // [C++0x] If P is an rvalue reference to a cv-unqualified + // template parameter and the argument is an lvalue, the type + // "lvalue reference to A" is used in place of A for type + // deduction. + if (isa<RValueReferenceType>(ParamType)) { + if (!PointeeType.getQualifiers() && + isa<TemplateTypeParmType>(PointeeType) && + Arg->Classify(S.Context).isLValue() && + Arg->getType() != S.Context.OverloadTy && + Arg->getType() != S.Context.BoundMemberTy) + ArgType = S.Context.getLValueReferenceType(ArgType); + } + + // [...] If P is a reference type, the type referred to by P is used + // for type deduction. + ParamType = PointeeType; + } + + // Overload sets usually make this parameter an undeduced + // context, but there are sometimes special circumstances. + if (ArgType == S.Context.OverloadTy) { + ArgType = ResolveOverloadForDeduction(S, TemplateParams, + Arg, ParamType, + ParamRefType != 0); + if (ArgType.isNull()) + return true; + } + + if (ParamRefType) { + // C++0x [temp.deduct.call]p3: + // [...] If P is of the form T&&, where T is a template parameter, and + // the argument is an lvalue, the type A& is used in place of A for + // type deduction. + if (ParamRefType->isRValueReferenceType() && + ParamRefType->getAs<TemplateTypeParmType>() && + Arg->isLValue()) + ArgType = S.Context.getLValueReferenceType(ArgType); + } else { + // C++ [temp.deduct.call]p2: + // If P is not a reference type: + // - If A is an array type, the pointer type produced by the + // array-to-pointer standard conversion (4.2) is used in place of + // A for type deduction; otherwise, + if (ArgType->isArrayType()) + ArgType = S.Context.getArrayDecayedType(ArgType); + // - If A is a function type, the pointer type produced by the + // function-to-pointer standard conversion (4.3) is used in place + // of A for type deduction; otherwise, + else if (ArgType->isFunctionType()) + ArgType = S.Context.getPointerType(ArgType); + else { + // - If A is a cv-qualified type, the top level cv-qualifiers of A's + // type are ignored for type deduction. + ArgType = ArgType.getUnqualifiedType(); + } + } + + // C++0x [temp.deduct.call]p4: + // In general, the deduction process attempts to find template argument + // values that will make the deduced A identical to A (after the type A + // is transformed as described above). [...] + TDF = TDF_SkipNonDependent; + + // - If the original P is a reference type, the deduced A (i.e., the + // type referred to by the reference) can be more cv-qualified than + // the transformed A. + if (ParamRefType) + TDF |= TDF_ParamWithReferenceType; + // - The transformed A can be another pointer or pointer to member + // type that can be converted to the deduced A via a qualification + // conversion (4.4). + if (ArgType->isPointerType() || ArgType->isMemberPointerType() || + ArgType->isObjCObjectPointerType()) + TDF |= TDF_IgnoreQualifiers; + // - If P is a class and P has the form simple-template-id, then the + // transformed A can be a derived class of the deduced A. Likewise, + // if P is a pointer to a class of the form simple-template-id, the + // transformed A can be a pointer to a derived class pointed to by + // the deduced A. + if (isSimpleTemplateIdType(ParamType) || + (isa<PointerType>(ParamType) && + isSimpleTemplateIdType( + ParamType->getAs<PointerType>()->getPointeeType()))) + TDF |= TDF_DerivedClass; + + return false; +} + +/// \brief Perform template argument deduction from a function call +/// (C++ [temp.deduct.call]). +/// +/// \param FunctionTemplate the function template for which we are performing +/// template argument deduction. +/// +/// \param ExplicitTemplateArguments the explicit template arguments provided +/// for this call. +/// +/// \param Args the function call arguments +/// +/// \param NumArgs the number of arguments in Args +/// +/// \param Name the name of the function being called. This is only significant +/// when the function template is a conversion function template, in which +/// case this routine will also perform template argument deduction based on +/// the function to which +/// +/// \param Specialization if template argument deduction was successful, +/// this will be set to the function template specialization produced by +/// template argument deduction. +/// +/// \param Info the argument will be updated to provide additional information +/// about template argument deduction. +/// +/// \returns the result of template argument deduction. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, + Expr **Args, unsigned NumArgs, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info) { + FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + + // C++ [temp.deduct.call]p1: + // Template argument deduction is done by comparing each function template + // parameter type (call it P) with the type of the corresponding argument + // of the call (call it A) as described below. + unsigned CheckArgs = NumArgs; + if (NumArgs < Function->getMinRequiredArguments()) + return TDK_TooFewArguments; + else if (NumArgs > Function->getNumParams()) { + const FunctionProtoType *Proto + = Function->getType()->getAs<FunctionProtoType>(); + if (Proto->isTemplateVariadic()) + /* Do nothing */; + else if (Proto->isVariadic()) + CheckArgs = Function->getNumParams(); + else + return TDK_TooManyArguments; + } + + // The types of the parameters from which we will perform template argument + // deduction. + LocalInstantiationScope InstScope(*this); + TemplateParameterList *TemplateParams + = FunctionTemplate->getTemplateParameters(); + llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; + llvm::SmallVector<QualType, 4> ParamTypes; + unsigned NumExplicitlySpecified = 0; + if (ExplicitTemplateArgs) { + TemplateDeductionResult Result = + SubstituteExplicitTemplateArguments(FunctionTemplate, + *ExplicitTemplateArgs, + Deduced, + ParamTypes, + 0, + Info); + if (Result) + return Result; + + NumExplicitlySpecified = Deduced.size(); + } else { + // Just fill in the parameter types from the function declaration. + for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) + ParamTypes.push_back(Function->getParamDecl(I)->getType()); + } + + // Deduce template arguments from the function parameters. + Deduced.resize(TemplateParams->size()); + unsigned ArgIdx = 0; + for (unsigned ParamIdx = 0, NumParams = ParamTypes.size(); + ParamIdx != NumParams; ++ParamIdx) { + QualType ParamType = ParamTypes[ParamIdx]; + + const PackExpansionType *ParamExpansion + = dyn_cast<PackExpansionType>(ParamType); + if (!ParamExpansion) { + // Simple case: matching a function parameter to a function argument. + if (ArgIdx >= CheckArgs) + break; + + Expr *Arg = Args[ArgIdx++]; + QualType ArgType = Arg->getType(); + unsigned TDF = 0; + if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams, + ParamType, ArgType, Arg, + TDF)) + continue; + + if (TemplateDeductionResult Result + = ::DeduceTemplateArguments(*this, TemplateParams, + ParamType, ArgType, Info, Deduced, + TDF)) + return Result; + + // FIXME: we need to check that the deduced A is the same as A, + // modulo the various allowed differences. + continue; + } + + // C++0x [temp.deduct.call]p1: + // For a function parameter pack that occurs at the end of the + // parameter-declaration-list, the type A of each remaining argument of + // the call is compared with the type P of the declarator-id of the + // function parameter pack. Each comparison deduces template arguments + // for subsequent positions in the template parameter packs expanded by + // the function parameter pack. For a function parameter pack that does + // not occur at the end of the parameter-declaration-list, the type of + // the parameter pack is a non-deduced context. + if (ParamIdx + 1 < NumParams) + break; + + QualType ParamPattern = ParamExpansion->getPattern(); + llvm::SmallVector<unsigned, 2> PackIndices; + { + llvm::BitVector SawIndices(TemplateParams->size()); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + collectUnexpandedParameterPacks(ParamPattern, Unexpanded); + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { + unsigned Depth, Index; + llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]); + if (Depth == 0 && !SawIndices[Index]) { + SawIndices[Index] = true; + PackIndices.push_back(Index); + } + } + } + assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?"); + + // Keep track of the deduced template arguments for each parameter pack + // expanded by this pack expansion (the outer index) and for each + // template argument (the inner SmallVectors). + llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2> + NewlyDeducedPacks(PackIndices.size()); + llvm::SmallVector<DeducedTemplateArgument, 2> + SavedPacks(PackIndices.size()); + PrepareArgumentPackDeduction(*this, Deduced, PackIndices, SavedPacks, + NewlyDeducedPacks); + bool HasAnyArguments = false; + for (; ArgIdx < NumArgs; ++ArgIdx) { + HasAnyArguments = true; + + ParamType = ParamPattern; + Expr *Arg = Args[ArgIdx]; + QualType ArgType = Arg->getType(); + unsigned TDF = 0; + if (AdjustFunctionParmAndArgTypesForDeduction(*this, TemplateParams, + ParamType, ArgType, Arg, + TDF)) { + // We can't actually perform any deduction for this argument, so stop + // deduction at this point. + ++ArgIdx; + break; + } + + if (TemplateDeductionResult Result + = ::DeduceTemplateArguments(*this, TemplateParams, + ParamType, ArgType, Info, Deduced, + TDF)) + return Result; + + // Capture the deduced template arguments for each parameter pack expanded + // by this pack expansion, add them to the list of arguments we've deduced + // for that pack, then clear out the deduced argument. + for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) { + DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]]; + if (!DeducedArg.isNull()) { + NewlyDeducedPacks[I].push_back(DeducedArg); + DeducedArg = DeducedTemplateArgument(); + } + } + } + + // Build argument packs for each of the parameter packs expanded by this + // pack expansion. + if (Sema::TemplateDeductionResult Result + = FinishArgumentPackDeduction(*this, TemplateParams, HasAnyArguments, + Deduced, PackIndices, SavedPacks, + NewlyDeducedPacks, Info)) + return Result; + + // After we've matching against a parameter pack, we're done. + break; + } + + return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, + NumExplicitlySpecified, + Specialization, Info); +} + +/// \brief Deduce template arguments when taking the address of a function +/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to +/// a template. +/// +/// \param FunctionTemplate the function template for which we are performing +/// template argument deduction. +/// +/// \param ExplicitTemplateArguments the explicitly-specified template +/// arguments. +/// +/// \param ArgFunctionType the function type that will be used as the +/// "argument" type (A) when performing template argument deduction from the +/// function template's function type. This type may be NULL, if there is no +/// argument type to compare against, in C++0x [temp.arg.explicit]p3. +/// +/// \param Specialization if template argument deduction was successful, +/// this will be set to the function template specialization produced by +/// template argument deduction. +/// +/// \param Info the argument will be updated to provide additional information +/// about template argument deduction. +/// +/// \returns the result of template argument deduction. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, + QualType ArgFunctionType, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info) { + FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + TemplateParameterList *TemplateParams + = FunctionTemplate->getTemplateParameters(); + QualType FunctionType = Function->getType(); + + // Substitute any explicit template arguments. + LocalInstantiationScope InstScope(*this); + llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; + unsigned NumExplicitlySpecified = 0; + llvm::SmallVector<QualType, 4> ParamTypes; + if (ExplicitTemplateArgs) { + if (TemplateDeductionResult Result + = SubstituteExplicitTemplateArguments(FunctionTemplate, + *ExplicitTemplateArgs, + Deduced, ParamTypes, + &FunctionType, Info)) + return Result; + + NumExplicitlySpecified = Deduced.size(); + } + + // Template argument deduction for function templates in a SFINAE context. + // Trap any errors that might occur. + SFINAETrap Trap(*this); + + Deduced.resize(TemplateParams->size()); + + if (!ArgFunctionType.isNull()) { + // Deduce template arguments from the function type. + if (TemplateDeductionResult Result + = ::DeduceTemplateArguments(*this, TemplateParams, + FunctionType, ArgFunctionType, Info, + Deduced, TDF_TopLevelParameterTypeList)) + return Result; + } + + if (TemplateDeductionResult Result + = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, + NumExplicitlySpecified, + Specialization, Info)) + return Result; + + // If the requested function type does not match the actual type of the + // specialization, template argument deduction fails. + if (!ArgFunctionType.isNull() && + !Context.hasSameType(ArgFunctionType, Specialization->getType())) + return TDK_NonDeducedMismatch; + + return TDK_Success; +} + +/// \brief Deduce template arguments for a templated conversion +/// function (C++ [temp.deduct.conv]) and, if successful, produce a +/// conversion function template specialization. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + QualType ToType, + CXXConversionDecl *&Specialization, + TemplateDeductionInfo &Info) { + CXXConversionDecl *Conv + = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()); + QualType FromType = Conv->getConversionType(); + + // Canonicalize the types for deduction. + QualType P = Context.getCanonicalType(FromType); + QualType A = Context.getCanonicalType(ToType); + + // C++0x [temp.deduct.conv]p2: + // If P is a reference type, the type referred to by P is used for + // type deduction. + if (const ReferenceType *PRef = P->getAs<ReferenceType>()) + P = PRef->getPointeeType(); + + // C++0x [temp.deduct.conv]p4: + // [...] If A is a reference type, the type referred to by A is used + // for type deduction. + if (const ReferenceType *ARef = A->getAs<ReferenceType>()) + A = ARef->getPointeeType().getUnqualifiedType(); + // C++ [temp.deduct.conv]p3: + // + // If A is not a reference type: + else { + assert(!A->isReferenceType() && "Reference types were handled above"); + + // - If P is an array type, the pointer type produced by the + // array-to-pointer standard conversion (4.2) is used in place + // of P for type deduction; otherwise, + if (P->isArrayType()) + P = Context.getArrayDecayedType(P); + // - If P is a function type, the pointer type produced by the + // function-to-pointer standard conversion (4.3) is used in + // place of P for type deduction; otherwise, + else if (P->isFunctionType()) + P = Context.getPointerType(P); + // - If P is a cv-qualified type, the top level cv-qualifiers of + // P's type are ignored for type deduction. + else + P = P.getUnqualifiedType(); + + // C++0x [temp.deduct.conv]p4: + // If A is a cv-qualified type, the top level cv-qualifiers of A's + // type are ignored for type deduction. If A is a reference type, the type + // referred to by A is used for type deduction. + A = A.getUnqualifiedType(); + } + + // Template argument deduction for function templates in a SFINAE context. + // Trap any errors that might occur. + SFINAETrap Trap(*this); + + // C++ [temp.deduct.conv]p1: + // Template argument deduction is done by comparing the return + // type of the template conversion function (call it P) with the + // type that is required as the result of the conversion (call it + // A) as described in 14.8.2.4. + TemplateParameterList *TemplateParams + = FunctionTemplate->getTemplateParameters(); + llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; + Deduced.resize(TemplateParams->size()); + + // C++0x [temp.deduct.conv]p4: + // In general, the deduction process attempts to find template + // argument values that will make the deduced A identical to + // A. However, there are two cases that allow a difference: + unsigned TDF = 0; + // - If the original A is a reference type, A can be more + // cv-qualified than the deduced A (i.e., the type referred to + // by the reference) + if (ToType->isReferenceType()) + TDF |= TDF_ParamWithReferenceType; + // - The deduced A can be another pointer or pointer to member + // type that can be converted to A via a qualification + // conversion. + // + // (C++0x [temp.deduct.conv]p6 clarifies that this only happens when + // both P and A are pointers or member pointers. In this case, we + // just ignore cv-qualifiers completely). + if ((P->isPointerType() && A->isPointerType()) || + (P->isMemberPointerType() && P->isMemberPointerType())) + TDF |= TDF_IgnoreQualifiers; + if (TemplateDeductionResult Result + = ::DeduceTemplateArguments(*this, TemplateParams, + P, A, Info, Deduced, TDF)) + return Result; + + // FIXME: we need to check that the deduced A is the same as A, + // modulo the various allowed differences. + + // Finish template argument deduction. + LocalInstantiationScope InstScope(*this); + FunctionDecl *Spec = 0; + TemplateDeductionResult Result + = FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 0, Spec, + Info); + Specialization = cast_or_null<CXXConversionDecl>(Spec); + return Result; +} + +/// \brief Deduce template arguments for a function template when there is +/// nothing to deduce against (C++0x [temp.arg.explicit]p3). +/// +/// \param FunctionTemplate the function template for which we are performing +/// template argument deduction. +/// +/// \param ExplicitTemplateArguments the explicitly-specified template +/// arguments. +/// +/// \param Specialization if template argument deduction was successful, +/// this will be set to the function template specialization produced by +/// template argument deduction. +/// +/// \param Info the argument will be updated to provide additional information +/// about template argument deduction. +/// +/// \returns the result of template argument deduction. +Sema::TemplateDeductionResult +Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + TemplateArgumentListInfo *ExplicitTemplateArgs, + FunctionDecl *&Specialization, + TemplateDeductionInfo &Info) { + return DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, + QualType(), Specialization, Info); +} + +namespace { + /// Substitute the 'auto' type specifier within a type for a given replacement + /// type. + class SubstituteAutoTransform : + public TreeTransform<SubstituteAutoTransform> { + QualType Replacement; + public: + SubstituteAutoTransform(Sema &SemaRef, QualType Replacement) : + TreeTransform<SubstituteAutoTransform>(SemaRef), Replacement(Replacement) { + } + QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) { + // If we're building the type pattern to deduce against, don't wrap the + // substituted type in an AutoType. Certain template deduction rules + // apply only when a template type parameter appears directly (and not if + // the parameter is found through desugaring). For instance: + // auto &&lref = lvalue; + // must transform into "rvalue reference to T" not "rvalue reference to + // auto type deduced as T" in order for [temp.deduct.call]p3 to apply. + if (isa<TemplateTypeParmType>(Replacement)) { + QualType Result = Replacement; + TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } else { + QualType Result = RebuildAutoType(Replacement); + AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } + } + }; +} + +/// \brief Deduce the type for an auto type-specifier (C++0x [dcl.spec.auto]p6) +/// +/// \param Type the type pattern using the auto type-specifier. +/// +/// \param Init the initializer for the variable whose type is to be deduced. +/// +/// \param Result if type deduction was successful, this will be set to the +/// deduced type. This may still contain undeduced autos if the type is +/// dependent. This will be set to null if deduction succeeded, but auto +/// substitution failed; the appropriate diagnostic will already have been +/// produced in that case. +/// +/// \returns true if deduction succeeded, false if it failed. +bool +Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *Init, + TypeSourceInfo *&Result) { + if (Init->isTypeDependent()) { + Result = Type; + return true; + } + + SourceLocation Loc = Init->getExprLoc(); + + LocalInstantiationScope InstScope(*this); + + // Build template<class TemplParam> void Func(FuncParam); + TemplateTypeParmDecl *TemplParam = + TemplateTypeParmDecl::Create(Context, 0, SourceLocation(), Loc, 0, 0, 0, + false, false); + QualType TemplArg = QualType(TemplParam->getTypeForDecl(), 0); + NamedDecl *TemplParamPtr = TemplParam; + FixedSizeTemplateParameterList<1> TemplateParams(Loc, Loc, &TemplParamPtr, + Loc); + + TypeSourceInfo *FuncParamInfo = + SubstituteAutoTransform(*this, TemplArg).TransformType(Type); + assert(FuncParamInfo && "substituting template parameter for 'auto' failed"); + QualType FuncParam = FuncParamInfo->getType(); + + // Deduce type of TemplParam in Func(Init) + llvm::SmallVector<DeducedTemplateArgument, 1> Deduced; + Deduced.resize(1); + QualType InitType = Init->getType(); + unsigned TDF = 0; + if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams, + FuncParam, InitType, Init, + TDF)) + return false; + + TemplateDeductionInfo Info(Context, Loc); + if (::DeduceTemplateArguments(*this, &TemplateParams, + FuncParam, InitType, Info, Deduced, + TDF)) + return false; + + QualType DeducedType = Deduced[0].getAsType(); + if (DeducedType.isNull()) + return false; + + Result = SubstituteAutoTransform(*this, DeducedType).TransformType(Type); + return true; +} + +static void +MarkUsedTemplateParameters(Sema &SemaRef, QualType T, + bool OnlyDeduced, + unsigned Level, + llvm::SmallVectorImpl<bool> &Deduced); + +/// \brief If this is a non-static member function, +static void MaybeAddImplicitObjectParameterType(ASTContext &Context, + CXXMethodDecl *Method, + llvm::SmallVectorImpl<QualType> &ArgTypes) { + if (Method->isStatic()) + return; + + // C++ [over.match.funcs]p4: + // + // For non-static member functions, the type of the implicit + // object parameter is + // - "lvalue reference to cv X" for functions declared without a + // ref-qualifier or with the & ref-qualifier + // - "rvalue reference to cv X" for functions declared with the + // && ref-qualifier + // + // FIXME: We don't have ref-qualifiers yet, so we don't do that part. + QualType ArgTy = Context.getTypeDeclType(Method->getParent()); + ArgTy = Context.getQualifiedType(ArgTy, + Qualifiers::fromCVRMask(Method->getTypeQualifiers())); + ArgTy = Context.getLValueReferenceType(ArgTy); + ArgTypes.push_back(ArgTy); +} + +/// \brief Determine whether the function template \p FT1 is at least as +/// specialized as \p FT2. +static bool isAtLeastAsSpecializedAs(Sema &S, + SourceLocation Loc, + FunctionTemplateDecl *FT1, + FunctionTemplateDecl *FT2, + TemplatePartialOrderingContext TPOC, + unsigned NumCallArguments, + llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) { + FunctionDecl *FD1 = FT1->getTemplatedDecl(); + FunctionDecl *FD2 = FT2->getTemplatedDecl(); + const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *Proto2 = FD2->getType()->getAs<FunctionProtoType>(); + + assert(Proto1 && Proto2 && "Function templates must have prototypes"); + TemplateParameterList *TemplateParams = FT2->getTemplateParameters(); + llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; + Deduced.resize(TemplateParams->size()); + + // C++0x [temp.deduct.partial]p3: + // The types used to determine the ordering depend on the context in which + // the partial ordering is done: + TemplateDeductionInfo Info(S.Context, Loc); + CXXMethodDecl *Method1 = 0; + CXXMethodDecl *Method2 = 0; + bool IsNonStatic2 = false; + bool IsNonStatic1 = false; + unsigned Skip2 = 0; + switch (TPOC) { + case TPOC_Call: { + // - In the context of a function call, the function parameter types are + // used. + Method1 = dyn_cast<CXXMethodDecl>(FD1); + Method2 = dyn_cast<CXXMethodDecl>(FD2); + IsNonStatic1 = Method1 && !Method1->isStatic(); + IsNonStatic2 = Method2 && !Method2->isStatic(); + + // C++0x [temp.func.order]p3: + // [...] If only one of the function templates is a non-static + // member, that function template is considered to have a new + // first parameter inserted in its function parameter list. The + // new parameter is of type "reference to cv A," where cv are + // the cv-qualifiers of the function template (if any) and A is + // the class of which the function template is a member. + // + // C++98/03 doesn't have this provision, so instead we drop the + // first argument of the free function or static member, which + // seems to match existing practice. + llvm::SmallVector<QualType, 4> Args1; + unsigned Skip1 = !S.getLangOptions().CPlusPlus0x && + IsNonStatic2 && !IsNonStatic1; + if (S.getLangOptions().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2) + MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1); + Args1.insert(Args1.end(), + Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end()); + + llvm::SmallVector<QualType, 4> Args2; + Skip2 = !S.getLangOptions().CPlusPlus0x && + IsNonStatic1 && !IsNonStatic2; + if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) + MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2); + Args2.insert(Args2.end(), + Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end()); + + // C++ [temp.func.order]p5: + // The presence of unused ellipsis and default arguments has no effect on + // the partial ordering of function templates. + if (Args1.size() > NumCallArguments) + Args1.resize(NumCallArguments); + if (Args2.size() > NumCallArguments) + Args2.resize(NumCallArguments); + if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(), + Args1.data(), Args1.size(), Info, Deduced, + TDF_None, /*PartialOrdering=*/true, + RefParamComparisons)) + return false; + + break; + } + + case TPOC_Conversion: + // - In the context of a call to a conversion operator, the return types + // of the conversion function templates are used. + if (DeduceTemplateArguments(S, TemplateParams, Proto2->getResultType(), + Proto1->getResultType(), Info, Deduced, + TDF_None, /*PartialOrdering=*/true, + RefParamComparisons)) + return false; + break; + + case TPOC_Other: + // - In other contexts (14.6.6.2) the function template's function type + // is used. + // FIXME: Don't we actually want to perform the adjustments on the parameter + // types? + if (DeduceTemplateArguments(S, TemplateParams, FD2->getType(), + FD1->getType(), Info, Deduced, TDF_None, + /*PartialOrdering=*/true, RefParamComparisons)) + return false; + break; + } + + // C++0x [temp.deduct.partial]p11: + // In most cases, all template parameters must have values in order for + // deduction to succeed, but for partial ordering purposes a template + // parameter may remain without a value provided it is not used in the + // types being used for partial ordering. [ Note: a template parameter used + // in a non-deduced context is considered used. -end note] + unsigned ArgIdx = 0, NumArgs = Deduced.size(); + for (; ArgIdx != NumArgs; ++ArgIdx) + if (Deduced[ArgIdx].isNull()) + break; + + if (ArgIdx == NumArgs) { + // All template arguments were deduced. FT1 is at least as specialized + // as FT2. + return true; + } + + // Figure out which template parameters were used. + llvm::SmallVector<bool, 4> UsedParameters; + UsedParameters.resize(TemplateParams->size()); + switch (TPOC) { + case TPOC_Call: { + unsigned NumParams = std::min(NumCallArguments, + std::min(Proto1->getNumArgs(), + Proto2->getNumArgs())); + if (S.getLangOptions().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) + ::MarkUsedTemplateParameters(S, Method2->getThisType(S.Context), false, + TemplateParams->getDepth(), UsedParameters); + for (unsigned I = Skip2; I < NumParams; ++I) + ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false, + TemplateParams->getDepth(), + UsedParameters); + break; + } + + case TPOC_Conversion: + ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false, + TemplateParams->getDepth(), + UsedParameters); + break; + + case TPOC_Other: + ::MarkUsedTemplateParameters(S, FD2->getType(), false, + TemplateParams->getDepth(), + UsedParameters); + break; + } + + for (; ArgIdx != NumArgs; ++ArgIdx) + // If this argument had no value deduced but was used in one of the types + // used for partial ordering, then deduction fails. + if (Deduced[ArgIdx].isNull() && UsedParameters[ArgIdx]) + return false; + + return true; +} + +/// \brief Determine whether this a function template whose parameter-type-list +/// ends with a function parameter pack. +static bool isVariadicFunctionTemplate(FunctionTemplateDecl *FunTmpl) { + FunctionDecl *Function = FunTmpl->getTemplatedDecl(); + unsigned NumParams = Function->getNumParams(); + if (NumParams == 0) + return false; + + ParmVarDecl *Last = Function->getParamDecl(NumParams - 1); + if (!Last->isParameterPack()) + return false; + + // Make sure that no previous parameter is a parameter pack. + while (--NumParams > 0) { + if (Function->getParamDecl(NumParams - 1)->isParameterPack()) + return false; + } + + return true; +} + +/// \brief Returns the more specialized function template according +/// to the rules of function template partial ordering (C++ [temp.func.order]). +/// +/// \param FT1 the first function template +/// +/// \param FT2 the second function template +/// +/// \param TPOC the context in which we are performing partial ordering of +/// function templates. +/// +/// \param NumCallArguments The number of arguments in a call, used only +/// when \c TPOC is \c TPOC_Call. +/// +/// \returns the more specialized function template. If neither +/// template is more specialized, returns NULL. +FunctionTemplateDecl * +Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, + FunctionTemplateDecl *FT2, + SourceLocation Loc, + TemplatePartialOrderingContext TPOC, + unsigned NumCallArguments) { + llvm::SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons; + bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, + NumCallArguments, 0); + bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, + NumCallArguments, + &RefParamComparisons); + + if (Better1 != Better2) // We have a clear winner + return Better1? FT1 : FT2; + + if (!Better1 && !Better2) // Neither is better than the other + return 0; + + // C++0x [temp.deduct.partial]p10: + // If for each type being considered a given template is at least as + // specialized for all types and more specialized for some set of types and + // the other template is not more specialized for any types or is not at + // least as specialized for any types, then the given template is more + // specialized than the other template. Otherwise, neither template is more + // specialized than the other. + Better1 = false; + Better2 = false; + for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) { + // C++0x [temp.deduct.partial]p9: + // If, for a given type, deduction succeeds in both directions (i.e., the + // types are identical after the transformations above) and both P and A + // were reference types (before being replaced with the type referred to + // above): + + // -- if the type from the argument template was an lvalue reference + // and the type from the parameter template was not, the argument + // type is considered to be more specialized than the other; + // otherwise, + if (!RefParamComparisons[I].ArgIsRvalueRef && + RefParamComparisons[I].ParamIsRvalueRef) { + Better2 = true; + if (Better1) + return 0; + continue; + } else if (!RefParamComparisons[I].ParamIsRvalueRef && + RefParamComparisons[I].ArgIsRvalueRef) { + Better1 = true; + if (Better2) + return 0; + continue; + } + + // -- if the type from the argument template is more cv-qualified than + // the type from the parameter template (as described above), the + // argument type is considered to be more specialized than the + // other; otherwise, + switch (RefParamComparisons[I].Qualifiers) { + case NeitherMoreQualified: + break; + + case ParamMoreQualified: + Better1 = true; + if (Better2) + return 0; + continue; + + case ArgMoreQualified: + Better2 = true; + if (Better1) + return 0; + continue; + } + + // -- neither type is more specialized than the other. + } + + assert(!(Better1 && Better2) && "Should have broken out in the loop above"); + if (Better1) + return FT1; + else if (Better2) + return FT2; + + // FIXME: This mimics what GCC implements, but doesn't match up with the + // proposed resolution for core issue 692. This area needs to be sorted out, + // but for now we attempt to maintain compatibility. + bool Variadic1 = isVariadicFunctionTemplate(FT1); + bool Variadic2 = isVariadicFunctionTemplate(FT2); + if (Variadic1 != Variadic2) + return Variadic1? FT2 : FT1; + + return 0; +} + +/// \brief Determine if the two templates are equivalent. +static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { + if (T1 == T2) + return true; + + if (!T1 || !T2) + return false; + + return T1->getCanonicalDecl() == T2->getCanonicalDecl(); +} + +/// \brief Retrieve the most specialized of the given function template +/// specializations. +/// +/// \param SpecBegin the start iterator of the function template +/// specializations that we will be comparing. +/// +/// \param SpecEnd the end iterator of the function template +/// specializations, paired with \p SpecBegin. +/// +/// \param TPOC the partial ordering context to use to compare the function +/// template specializations. +/// +/// \param NumCallArguments The number of arguments in a call, used only +/// when \c TPOC is \c TPOC_Call. +/// +/// \param Loc the location where the ambiguity or no-specializations +/// diagnostic should occur. +/// +/// \param NoneDiag partial diagnostic used to diagnose cases where there are +/// no matching candidates. +/// +/// \param AmbigDiag partial diagnostic used to diagnose an ambiguity, if one +/// occurs. +/// +/// \param CandidateDiag partial diagnostic used for each function template +/// specialization that is a candidate in the ambiguous ordering. One parameter +/// in this diagnostic should be unbound, which will correspond to the string +/// describing the template arguments for the function template specialization. +/// +/// \param Index if non-NULL and the result of this function is non-nULL, +/// receives the index corresponding to the resulting function template +/// specialization. +/// +/// \returns the most specialized function template specialization, if +/// found. Otherwise, returns SpecEnd. +/// +/// \todo FIXME: Consider passing in the "also-ran" candidates that failed +/// template argument deduction. +UnresolvedSetIterator +Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, + UnresolvedSetIterator SpecEnd, + TemplatePartialOrderingContext TPOC, + unsigned NumCallArguments, + SourceLocation Loc, + const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag, + bool Complain) { + if (SpecBegin == SpecEnd) { + if (Complain) + Diag(Loc, NoneDiag); + return SpecEnd; + } + + if (SpecBegin + 1 == SpecEnd) + return SpecBegin; + + // Find the function template that is better than all of the templates it + // has been compared to. + UnresolvedSetIterator Best = SpecBegin; + FunctionTemplateDecl *BestTemplate + = cast<FunctionDecl>(*Best)->getPrimaryTemplate(); + assert(BestTemplate && "Not a function template specialization?"); + for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) { + FunctionTemplateDecl *Challenger + = cast<FunctionDecl>(*I)->getPrimaryTemplate(); + assert(Challenger && "Not a function template specialization?"); + if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, + Loc, TPOC, NumCallArguments), + Challenger)) { + Best = I; + BestTemplate = Challenger; + } + } + + // Make sure that the "best" function template is more specialized than all + // of the others. + bool Ambiguous = false; + for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) { + FunctionTemplateDecl *Challenger + = cast<FunctionDecl>(*I)->getPrimaryTemplate(); + if (I != Best && + !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, + Loc, TPOC, NumCallArguments), + BestTemplate)) { + Ambiguous = true; + break; + } + } + + if (!Ambiguous) { + // We found an answer. Return it. + return Best; + } + + // Diagnose the ambiguity. + if (Complain) + Diag(Loc, AmbigDiag); + + if (Complain) + // FIXME: Can we order the candidates in some sane way? + for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) + Diag((*I)->getLocation(), CandidateDiag) + << getTemplateArgumentBindingsText( + cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(), + *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs()); + + return SpecEnd; +} + +/// \brief Returns the more specialized class template partial specialization +/// according to the rules of partial ordering of class template partial +/// specializations (C++ [temp.class.order]). +/// +/// \param PS1 the first class template partial specialization +/// +/// \param PS2 the second class template partial specialization +/// +/// \returns the more specialized class template partial specialization. If +/// neither partial specialization is more specialized, returns NULL. +ClassTemplatePartialSpecializationDecl * +Sema::getMoreSpecializedPartialSpecialization( + ClassTemplatePartialSpecializationDecl *PS1, + ClassTemplatePartialSpecializationDecl *PS2, + SourceLocation Loc) { + // C++ [temp.class.order]p1: + // For two class template partial specializations, the first is at least as + // specialized as the second if, given the following rewrite to two + // function templates, the first function template is at least as + // specialized as the second according to the ordering rules for function + // templates (14.6.6.2): + // - the first function template has the same template parameters as the + // first partial specialization and has a single function parameter + // whose type is a class template specialization with the template + // arguments of the first partial specialization, and + // - the second function template has the same template parameters as the + // second partial specialization and has a single function parameter + // whose type is a class template specialization with the template + // arguments of the second partial specialization. + // + // Rather than synthesize function templates, we merely perform the + // equivalent partial ordering by performing deduction directly on + // the template arguments of the class template partial + // specializations. This computation is slightly simpler than the + // general problem of function template partial ordering, because + // class template partial specializations are more constrained. We + // know that every template parameter is deducible from the class + // template partial specialization's template arguments, for + // example. + llvm::SmallVector<DeducedTemplateArgument, 4> Deduced; + TemplateDeductionInfo Info(Context, Loc); + + QualType PT1 = PS1->getInjectedSpecializationType(); + QualType PT2 = PS2->getInjectedSpecializationType(); + + // Determine whether PS1 is at least as specialized as PS2 + Deduced.resize(PS2->getTemplateParameters()->size()); + bool Better1 = !::DeduceTemplateArguments(*this, PS2->getTemplateParameters(), + PT2, PT1, Info, Deduced, TDF_None, + /*PartialOrdering=*/true, + /*RefParamComparisons=*/0); + if (Better1) { + InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2, + Deduced.data(), Deduced.size(), Info); + Better1 = !::FinishTemplateArgumentDeduction(*this, PS2, + PS1->getTemplateArgs(), + Deduced, Info); + } + + // Determine whether PS2 is at least as specialized as PS1 + Deduced.clear(); + Deduced.resize(PS1->getTemplateParameters()->size()); + bool Better2 = !::DeduceTemplateArguments(*this, PS1->getTemplateParameters(), + PT1, PT2, Info, Deduced, TDF_None, + /*PartialOrdering=*/true, + /*RefParamComparisons=*/0); + if (Better2) { + InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1, + Deduced.data(), Deduced.size(), Info); + Better2 = !::FinishTemplateArgumentDeduction(*this, PS1, + PS2->getTemplateArgs(), + Deduced, Info); + } + + if (Better1 == Better2) + return 0; + + return Better1? PS1 : PS2; +} + +static void +MarkUsedTemplateParameters(Sema &SemaRef, + const TemplateArgument &TemplateArg, + bool OnlyDeduced, + unsigned Depth, + llvm::SmallVectorImpl<bool> &Used); + +/// \brief Mark the template parameters that are used by the given +/// expression. +static void +MarkUsedTemplateParameters(Sema &SemaRef, + const Expr *E, + bool OnlyDeduced, + unsigned Depth, + llvm::SmallVectorImpl<bool> &Used) { + // We can deduce from a pack expansion. + if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E)) + E = Expansion->getPattern(); + + // Skip through any implicit casts we added while type-checking. + while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + E = ICE->getSubExpr(); + + // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to + // find other occurrences of template parameters. + const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); + if (!DRE) + return; + + const NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); + if (!NTTP) + return; + + if (NTTP->getDepth() == Depth) + Used[NTTP->getIndex()] = true; +} + +/// \brief Mark the template parameters that are used by the given +/// nested name specifier. +static void +MarkUsedTemplateParameters(Sema &SemaRef, + NestedNameSpecifier *NNS, + bool OnlyDeduced, + unsigned Depth, + llvm::SmallVectorImpl<bool> &Used) { + if (!NNS) + return; + + MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth, + Used); + MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0), + OnlyDeduced, Depth, Used); +} + +/// \brief Mark the template parameters that are used by the given +/// template name. +static void +MarkUsedTemplateParameters(Sema &SemaRef, + TemplateName Name, + bool OnlyDeduced, + unsigned Depth, + llvm::SmallVectorImpl<bool> &Used) { + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast<TemplateTemplateParmDecl>(Template)) { + if (TTP->getDepth() == Depth) + Used[TTP->getIndex()] = true; + } + return; + } + + if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) + MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced, + Depth, Used); + if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) + MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, + Depth, Used); +} + +/// \brief Mark the template parameters that are used by the given +/// type. +static void +MarkUsedTemplateParameters(Sema &SemaRef, QualType T, + bool OnlyDeduced, + unsigned Depth, + llvm::SmallVectorImpl<bool> &Used) { + if (T.isNull()) + return; + + // Non-dependent types have nothing deducible + if (!T->isDependentType()) + return; + + T = SemaRef.Context.getCanonicalType(T); + switch (T->getTypeClass()) { + case Type::Pointer: + MarkUsedTemplateParameters(SemaRef, + cast<PointerType>(T)->getPointeeType(), + OnlyDeduced, + Depth, + Used); + break; + + case Type::BlockPointer: + MarkUsedTemplateParameters(SemaRef, + cast<BlockPointerType>(T)->getPointeeType(), + OnlyDeduced, + Depth, + Used); + break; + + case Type::LValueReference: + case Type::RValueReference: + MarkUsedTemplateParameters(SemaRef, + cast<ReferenceType>(T)->getPointeeType(), + OnlyDeduced, + Depth, + Used); + break; + + case Type::MemberPointer: { + const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr()); + MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced, + Depth, Used); + MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0), + OnlyDeduced, Depth, Used); + break; + } + + case Type::DependentSizedArray: + MarkUsedTemplateParameters(SemaRef, + cast<DependentSizedArrayType>(T)->getSizeExpr(), + OnlyDeduced, Depth, Used); + // Fall through to check the element type + + case Type::ConstantArray: + case Type::IncompleteArray: + MarkUsedTemplateParameters(SemaRef, + cast<ArrayType>(T)->getElementType(), + OnlyDeduced, Depth, Used); + break; + + case Type::Vector: + case Type::ExtVector: + MarkUsedTemplateParameters(SemaRef, + cast<VectorType>(T)->getElementType(), + OnlyDeduced, Depth, Used); + break; + + case Type::DependentSizedExtVector: { + const DependentSizedExtVectorType *VecType + = cast<DependentSizedExtVectorType>(T); + MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced, + Depth, Used); + MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced, + Depth, Used); + break; + } + + case Type::FunctionProto: { + const FunctionProtoType *Proto = cast<FunctionProtoType>(T); + MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced, + Depth, Used); + for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I) + MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced, + Depth, Used); + break; + } + + case Type::TemplateTypeParm: { + const TemplateTypeParmType *TTP = cast<TemplateTypeParmType>(T); + if (TTP->getDepth() == Depth) + Used[TTP->getIndex()] = true; + break; + } + + case Type::SubstTemplateTypeParmPack: { + const SubstTemplateTypeParmPackType *Subst + = cast<SubstTemplateTypeParmPackType>(T); + MarkUsedTemplateParameters(SemaRef, + QualType(Subst->getReplacedParameter(), 0), + OnlyDeduced, Depth, Used); + MarkUsedTemplateParameters(SemaRef, Subst->getArgumentPack(), + OnlyDeduced, Depth, Used); + break; + } + + case Type::InjectedClassName: + T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType(); + // fall through + + case Type::TemplateSpecialization: { + const TemplateSpecializationType *Spec + = cast<TemplateSpecializationType>(T); + MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced, + Depth, Used); + + // C++0x [temp.deduct.type]p9: + // If the template argument list of P contains a pack expansion that is not + // the last template argument, the entire template argument list is a + // non-deduced context. + if (OnlyDeduced && + hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs())) + break; + + for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) + MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + Used); + break; + } + + case Type::Complex: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<ComplexType>(T)->getElementType(), + OnlyDeduced, Depth, Used); + break; + + case Type::DependentName: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<DependentNameType>(T)->getQualifier(), + OnlyDeduced, Depth, Used); + break; + + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec + = cast<DependentTemplateSpecializationType>(T); + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(), + OnlyDeduced, Depth, Used); + + // C++0x [temp.deduct.type]p9: + // If the template argument list of P contains a pack expansion that is not + // the last template argument, the entire template argument list is a + // non-deduced context. + if (OnlyDeduced && + hasPackExpansionBeforeEnd(Spec->getArgs(), Spec->getNumArgs())) + break; + + for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) + MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + Used); + break; + } + + case Type::TypeOf: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<TypeOfType>(T)->getUnderlyingType(), + OnlyDeduced, Depth, Used); + break; + + case Type::TypeOfExpr: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<TypeOfExprType>(T)->getUnderlyingExpr(), + OnlyDeduced, Depth, Used); + break; + + case Type::Decltype: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<DecltypeType>(T)->getUnderlyingExpr(), + OnlyDeduced, Depth, Used); + break; + + case Type::UnaryTransform: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<UnaryTransformType>(T)->getUnderlyingType(), + OnlyDeduced, Depth, Used); + break; + + case Type::PackExpansion: + MarkUsedTemplateParameters(SemaRef, + cast<PackExpansionType>(T)->getPattern(), + OnlyDeduced, Depth, Used); + break; + + case Type::Auto: + MarkUsedTemplateParameters(SemaRef, + cast<AutoType>(T)->getDeducedType(), + OnlyDeduced, Depth, Used); + + // None of these types have any template parameters in them. + case Type::Builtin: + case Type::VariableArray: + case Type::FunctionNoProto: + case Type::Record: + case Type::Enum: + case Type::ObjCInterface: + case Type::ObjCObject: + case Type::ObjCObjectPointer: + case Type::UnresolvedUsing: +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define DEPENDENT_TYPE(Class, Base) +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + break; + } +} + +/// \brief Mark the template parameters that are used by this +/// template argument. +static void +MarkUsedTemplateParameters(Sema &SemaRef, + const TemplateArgument &TemplateArg, + bool OnlyDeduced, + unsigned Depth, + llvm::SmallVectorImpl<bool> &Used) { + switch (TemplateArg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Integral: + case TemplateArgument::Declaration: + break; + + case TemplateArgument::Type: + MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced, + Depth, Used); + break; + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + MarkUsedTemplateParameters(SemaRef, + TemplateArg.getAsTemplateOrTemplatePattern(), + OnlyDeduced, Depth, Used); + break; + + case TemplateArgument::Expression: + MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced, + Depth, Used); + break; + + case TemplateArgument::Pack: + for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(), + PEnd = TemplateArg.pack_end(); + P != PEnd; ++P) + MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Depth, Used); + break; + } +} + +/// \brief Mark the template parameters can be deduced by the given +/// template argument list. +/// +/// \param TemplateArgs the template argument list from which template +/// parameters will be deduced. +/// +/// \param Deduced a bit vector whose elements will be set to \c true +/// to indicate when the corresponding template parameter will be +/// deduced. +void +Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, + bool OnlyDeduced, unsigned Depth, + llvm::SmallVectorImpl<bool> &Used) { + // C++0x [temp.deduct.type]p9: + // If the template argument list of P contains a pack expansion that is not + // the last template argument, the entire template argument list is a + // non-deduced context. + if (OnlyDeduced && + hasPackExpansionBeforeEnd(TemplateArgs.data(), TemplateArgs.size())) + return; + + for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) + ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, + Depth, Used); +} + +/// \brief Marks all of the template parameters that will be deduced by a +/// call to the given function template. +void +Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, + llvm::SmallVectorImpl<bool> &Deduced) { + TemplateParameterList *TemplateParams + = FunctionTemplate->getTemplateParameters(); + Deduced.clear(); + Deduced.resize(TemplateParams->size()); + + FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) + ::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(), + true, TemplateParams->getDepth(), Deduced); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp new file mode 100644 index 0000000..3c19641 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -0,0 +1,2374 @@ +//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements C++ template instantiation. +// +//===----------------------------------------------------------------------===/ + +#include "clang/Sema/SemaInternal.h" +#include "TreeTransform.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/Basic/LangOptions.h" + +using namespace clang; +using namespace sema; + +//===----------------------------------------------------------------------===/ +// Template Instantiation Support +//===----------------------------------------------------------------------===/ + +/// \brief Retrieve the template argument list(s) that should be used to +/// instantiate the definition of the given declaration. +/// +/// \param D the declaration for which we are computing template instantiation +/// arguments. +/// +/// \param Innermost if non-NULL, the innermost template argument list. +/// +/// \param RelativeToPrimary true if we should get the template +/// arguments relative to the primary template, even when we're +/// dealing with a specialization. This is only relevant for function +/// template specializations. +/// +/// \param Pattern If non-NULL, indicates the pattern from which we will be +/// instantiating the definition of the given declaration, \p D. This is +/// used to determine the proper set of template instantiation arguments for +/// friend function template specializations. +MultiLevelTemplateArgumentList +Sema::getTemplateInstantiationArgs(NamedDecl *D, + const TemplateArgumentList *Innermost, + bool RelativeToPrimary, + const FunctionDecl *Pattern) { + // Accumulate the set of template argument lists in this structure. + MultiLevelTemplateArgumentList Result; + + if (Innermost) + Result.addOuterTemplateArguments(Innermost); + + DeclContext *Ctx = dyn_cast<DeclContext>(D); + if (!Ctx) { + Ctx = D->getDeclContext(); + + assert((!D->isTemplateParameter() || !Ctx->isTranslationUnit()) && + "Template parameter doesn't have its context yet!"); + } + + while (!Ctx->isFileContext()) { + // Add template arguments from a class template instantiation. + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) { + // We're done when we hit an explicit specialization. + if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization && + !isa<ClassTemplatePartialSpecializationDecl>(Spec)) + break; + + Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs()); + + // If this class template specialization was instantiated from a + // specialized member that is a class template, we're done. + assert(Spec->getSpecializedTemplate() && "No class template?"); + if (Spec->getSpecializedTemplate()->isMemberSpecialization()) + break; + } + // Add template arguments from a function template specialization. + else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) { + if (!RelativeToPrimary && + Function->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) + break; + + if (const TemplateArgumentList *TemplateArgs + = Function->getTemplateSpecializationArgs()) { + // Add the template arguments for this specialization. + Result.addOuterTemplateArguments(TemplateArgs); + + // If this function was instantiated from a specialized member that is + // a function template, we're done. + assert(Function->getPrimaryTemplate() && "No function template?"); + if (Function->getPrimaryTemplate()->isMemberSpecialization()) + break; + } else if (FunctionTemplateDecl *FunTmpl + = Function->getDescribedFunctionTemplate()) { + // Add the "injected" template arguments. + std::pair<const TemplateArgument *, unsigned> + Injected = FunTmpl->getInjectedTemplateArgs(); + Result.addOuterTemplateArguments(Injected.first, Injected.second); + } + + // If this is a friend declaration and it declares an entity at + // namespace scope, take arguments from its lexical parent + // instead of its semantic parent, unless of course the pattern we're + // instantiating actually comes from the file's context! + if (Function->getFriendObjectKind() && + Function->getDeclContext()->isFileContext() && + (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) { + Ctx = Function->getLexicalDeclContext(); + RelativeToPrimary = false; + continue; + } + } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) { + if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { + QualType T = ClassTemplate->getInjectedClassNameSpecialization(); + const TemplateSpecializationType *TST + = cast<TemplateSpecializationType>(Context.getCanonicalType(T)); + Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs()); + if (ClassTemplate->isMemberSpecialization()) + break; + } + } + + Ctx = Ctx->getParent(); + RelativeToPrimary = false; + } + + return Result; +} + +bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const { + switch (Kind) { + case TemplateInstantiation: + case DefaultTemplateArgumentInstantiation: + case DefaultFunctionArgumentInstantiation: + return true; + + case ExplicitTemplateArgumentSubstitution: + case DeducedTemplateArgumentSubstitution: + case PriorTemplateArgumentSubstitution: + case DefaultTemplateArgumentChecking: + return false; + } + + return true; +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + Decl *Entity, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = CheckInstantiationDepth(PointOfInstantiation, + InstantiationRange); + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(Entity); + Inst.TemplateArgs = 0; + Inst.NumTemplateArgs = 0; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + } +} + +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + SourceLocation PointOfInstantiation, + TemplateDecl *Template, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = CheckInstantiationDepth(PointOfInstantiation, + InstantiationRange); + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind + = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(Template); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + } +} + +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + SourceLocation PointOfInstantiation, + FunctionTemplateDecl *FunctionTemplate, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + ActiveTemplateInstantiation::InstantiationKind Kind, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = CheckInstantiationDepth(PointOfInstantiation, + InstantiationRange); + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind = Kind; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.DeductionInfo = &DeductionInfo; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + if (!Inst.isInstantiationRecord()) + ++SemaRef.NonInstantiationEntries; + } +} + +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + SourceLocation PointOfInstantiation, + ClassTemplatePartialSpecializationDecl *PartialSpec, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + sema::TemplateDeductionInfo &DeductionInfo, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.DeductionInfo = &DeductionInfo; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + SourceLocation PointOfInstantiation, + ParmVarDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); + + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind + = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + } +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + NamedDecl *Template, + NonTypeTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + NamedDecl *Template, + TemplateTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = false; + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NamedDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) + : SemaRef(SemaRef), + SavedInNonInstantiationSFINAEContext( + SemaRef.InNonInstantiationSFINAEContext) +{ + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.InNonInstantiationSFINAEContext = false; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +void Sema::InstantiatingTemplate::Clear() { + if (!Invalid) { + if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) { + assert(SemaRef.NonInstantiationEntries > 0); + --SemaRef.NonInstantiationEntries; + } + SemaRef.InNonInstantiationSFINAEContext + = SavedInNonInstantiationSFINAEContext; + SemaRef.ActiveTemplateInstantiations.pop_back(); + Invalid = true; + } +} + +bool Sema::InstantiatingTemplate::CheckInstantiationDepth( + SourceLocation PointOfInstantiation, + SourceRange InstantiationRange) { + assert(SemaRef.NonInstantiationEntries <= + SemaRef.ActiveTemplateInstantiations.size()); + if ((SemaRef.ActiveTemplateInstantiations.size() - + SemaRef.NonInstantiationEntries) + <= SemaRef.getLangOptions().InstantiationDepth) + return false; + + SemaRef.Diag(PointOfInstantiation, + diag::err_template_recursion_depth_exceeded) + << SemaRef.getLangOptions().InstantiationDepth + << InstantiationRange; + SemaRef.Diag(PointOfInstantiation, diag::note_template_recursion_depth) + << SemaRef.getLangOptions().InstantiationDepth; + return true; +} + +/// \brief Prints the current instantiation stack through a series of +/// notes. +void Sema::PrintInstantiationStack() { + // Determine which template instantiations to skip, if any. + unsigned SkipStart = ActiveTemplateInstantiations.size(), SkipEnd = SkipStart; + unsigned Limit = Diags.getTemplateBacktraceLimit(); + if (Limit && Limit < ActiveTemplateInstantiations.size()) { + SkipStart = Limit / 2 + Limit % 2; + SkipEnd = ActiveTemplateInstantiations.size() - Limit / 2; + } + + // FIXME: In all of these cases, we need to show the template arguments + unsigned InstantiationIdx = 0; + for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator + Active = ActiveTemplateInstantiations.rbegin(), + ActiveEnd = ActiveTemplateInstantiations.rend(); + Active != ActiveEnd; + ++Active, ++InstantiationIdx) { + // Skip this instantiation? + if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) { + if (InstantiationIdx == SkipStart) { + // Note that we're skipping instantiations. + Diags.Report(Active->PointOfInstantiation, + diag::note_instantiation_contexts_suppressed) + << unsigned(ActiveTemplateInstantiations.size() - Limit); + } + continue; + } + + switch (Active->Kind) { + case ActiveTemplateInstantiation::TemplateInstantiation: { + Decl *D = reinterpret_cast<Decl *>(Active->Entity); + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { + unsigned DiagID = diag::note_template_member_class_here; + if (isa<ClassTemplateSpecializationDecl>(Record)) + DiagID = diag::note_template_class_instantiation_here; + Diags.Report(Active->PointOfInstantiation, DiagID) + << Context.getTypeDeclType(Record) + << Active->InstantiationRange; + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + unsigned DiagID; + if (Function->getPrimaryTemplate()) + DiagID = diag::note_function_template_spec_here; + else + DiagID = diag::note_template_member_function_here; + Diags.Report(Active->PointOfInstantiation, DiagID) + << Function + << Active->InstantiationRange; + } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + Diags.Report(Active->PointOfInstantiation, + diag::note_template_static_data_member_def_here) + << VD + << Active->InstantiationRange; + } else { + Diags.Report(Active->PointOfInstantiation, + diag::note_template_type_alias_instantiation_here) + << cast<TypeAliasTemplateDecl>(D) + << Active->InstantiationRange; + } + break; + } + + case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: { + TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity); + std::string TemplateArgsStr + = TemplateSpecializationType::PrintTemplateArgumentList( + Active->TemplateArgs, + Active->NumTemplateArgs, + Context.PrintingPolicy); + Diags.Report(Active->PointOfInstantiation, + diag::note_default_arg_instantiation_here) + << (Template->getNameAsString() + TemplateArgsStr) + << Active->InstantiationRange; + break; + } + + case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: { + FunctionTemplateDecl *FnTmpl + = cast<FunctionTemplateDecl>((Decl *)Active->Entity); + Diags.Report(Active->PointOfInstantiation, + diag::note_explicit_template_arg_substitution_here) + << FnTmpl + << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(), + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + break; + } + + case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution: + if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>( + (Decl *)Active->Entity)) { + Diags.Report(Active->PointOfInstantiation, + diag::note_partial_spec_deduct_instantiation_here) + << Context.getTypeDeclType(PartialSpec) + << getTemplateArgumentBindingsText( + PartialSpec->getTemplateParameters(), + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + } else { + FunctionTemplateDecl *FnTmpl + = cast<FunctionTemplateDecl>((Decl *)Active->Entity); + Diags.Report(Active->PointOfInstantiation, + diag::note_function_template_deduction_instantiation_here) + << FnTmpl + << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(), + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + } + break; + + case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: { + ParmVarDecl *Param = cast<ParmVarDecl>((Decl *)Active->Entity); + FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext()); + + std::string TemplateArgsStr + = TemplateSpecializationType::PrintTemplateArgumentList( + Active->TemplateArgs, + Active->NumTemplateArgs, + Context.PrintingPolicy); + Diags.Report(Active->PointOfInstantiation, + diag::note_default_function_arg_instantiation_here) + << (FD->getNameAsString() + TemplateArgsStr) + << Active->InstantiationRange; + break; + } + + case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: { + NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity); + std::string Name; + if (!Parm->getName().empty()) + Name = std::string(" '") + Parm->getName().str() + "'"; + + TemplateParameterList *TemplateParams = 0; + if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template)) + TemplateParams = Template->getTemplateParameters(); + else + TemplateParams = + cast<ClassTemplatePartialSpecializationDecl>(Active->Template) + ->getTemplateParameters(); + Diags.Report(Active->PointOfInstantiation, + diag::note_prior_template_arg_substitution) + << isa<TemplateTemplateParmDecl>(Parm) + << Name + << getTemplateArgumentBindingsText(TemplateParams, + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + break; + } + + case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: { + TemplateParameterList *TemplateParams = 0; + if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template)) + TemplateParams = Template->getTemplateParameters(); + else + TemplateParams = + cast<ClassTemplatePartialSpecializationDecl>(Active->Template) + ->getTemplateParameters(); + + Diags.Report(Active->PointOfInstantiation, + diag::note_template_default_arg_checking) + << getTemplateArgumentBindingsText(TemplateParams, + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + break; + } + } + } +} + +llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { + using llvm::SmallVector; + if (InNonInstantiationSFINAEContext) + return llvm::Optional<TemplateDeductionInfo *>(0); + + for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator + Active = ActiveTemplateInstantiations.rbegin(), + ActiveEnd = ActiveTemplateInstantiations.rend(); + Active != ActiveEnd; + ++Active) + { + switch(Active->Kind) { + case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: + case ActiveTemplateInstantiation::TemplateInstantiation: + // This is a template instantiation, so there is no SFINAE. + return llvm::Optional<TemplateDeductionInfo *>(); + + case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: + case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: + case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: + // A default template argument instantiation and substitution into + // template parameters with arguments for prior parameters may or may + // not be a SFINAE context; look further up the stack. + break; + + case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: + case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution: + // We're either substitution explicitly-specified template arguments + // or deduced template arguments, so SFINAE applies. + assert(Active->DeductionInfo && "Missing deduction info pointer"); + return Active->DeductionInfo; + } + } + + return llvm::Optional<TemplateDeductionInfo *>(); +} + +/// \brief Retrieve the depth and index of a parameter pack. +static std::pair<unsigned, unsigned> +getDepthAndIndex(NamedDecl *ND) { + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND)) + return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); + + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND); + return std::make_pair(TTP->getDepth(), TTP->getIndex()); +} + +//===----------------------------------------------------------------------===/ +// Template Instantiation for Types +//===----------------------------------------------------------------------===/ +namespace { + class TemplateInstantiator : public TreeTransform<TemplateInstantiator> { + const MultiLevelTemplateArgumentList &TemplateArgs; + SourceLocation Loc; + DeclarationName Entity; + + public: + typedef TreeTransform<TemplateInstantiator> inherited; + + TemplateInstantiator(Sema &SemaRef, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, + DeclarationName Entity) + : inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc), + Entity(Entity) { } + + /// \brief Determine whether the given type \p T has already been + /// transformed. + /// + /// For the purposes of template instantiation, a type has already been + /// transformed if it is NULL or if it is not dependent. + bool AlreadyTransformed(QualType T); + + /// \brief Returns the location of the entity being instantiated, if known. + SourceLocation getBaseLocation() { return Loc; } + + /// \brief Returns the name of the entity being instantiated, if any. + DeclarationName getBaseEntity() { return Entity; } + + /// \brief Sets the "base" location and entity when that + /// information is known based on another transformation. + void setBase(SourceLocation Loc, DeclarationName Entity) { + this->Loc = Loc; + this->Entity = Entity; + } + + bool TryExpandParameterPacks(SourceLocation EllipsisLoc, + SourceRange PatternRange, + const UnexpandedParameterPack *Unexpanded, + unsigned NumUnexpanded, + bool &ShouldExpand, + bool &RetainExpansion, + llvm::Optional<unsigned> &NumExpansions) { + return getSema().CheckParameterPacksForExpansion(EllipsisLoc, + PatternRange, Unexpanded, + NumUnexpanded, + TemplateArgs, + ShouldExpand, + RetainExpansion, + NumExpansions); + } + + void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { + SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack); + } + + TemplateArgument ForgetPartiallySubstitutedPack() { + TemplateArgument Result; + if (NamedDecl *PartialPack + = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){ + MultiLevelTemplateArgumentList &TemplateArgs + = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs); + unsigned Depth, Index; + llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack); + if (TemplateArgs.hasTemplateArgument(Depth, Index)) { + Result = TemplateArgs(Depth, Index); + TemplateArgs.setArgument(Depth, Index, TemplateArgument()); + } + } + + return Result; + } + + void RememberPartiallySubstitutedPack(TemplateArgument Arg) { + if (Arg.isNull()) + return; + + if (NamedDecl *PartialPack + = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){ + MultiLevelTemplateArgumentList &TemplateArgs + = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs); + unsigned Depth, Index; + llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack); + TemplateArgs.setArgument(Depth, Index, Arg); + } + } + + /// \brief Transform the given declaration by instantiating a reference to + /// this declaration. + Decl *TransformDecl(SourceLocation Loc, Decl *D); + + /// \brief Transform the definition of the given declaration by + /// instantiating it. + Decl *TransformDefinition(SourceLocation Loc, Decl *D); + + /// \bried Transform the first qualifier within a scope by instantiating the + /// declaration. + NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc); + + /// \brief Rebuild the exception declaration and register the declaration + /// as an instantiated local. + VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, + TypeSourceInfo *Declarator, + SourceLocation StartLoc, + SourceLocation NameLoc, + IdentifierInfo *Name); + + /// \brief Rebuild the Objective-C exception declaration and register the + /// declaration as an instantiated local. + VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, + TypeSourceInfo *TSInfo, QualType T); + + /// \brief Check for tag mismatches when instantiating an + /// elaborated type. + QualType RebuildElaboratedType(SourceLocation KeywordLoc, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifierLoc QualifierLoc, + QualType T); + + TemplateName TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, + QualType ObjectType = QualType(), + NamedDecl *FirstQualifierInScope = 0); + + ExprResult TransformPredefinedExpr(PredefinedExpr *E); + ExprResult TransformDeclRefExpr(DeclRefExpr *E); + ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E); + ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E, + NonTypeTemplateParmDecl *D); + ExprResult TransformSubstNonTypeTemplateParmPackExpr( + SubstNonTypeTemplateParmPackExpr *E); + + QualType TransformFunctionProtoType(TypeLocBuilder &TLB, + FunctionProtoTypeLoc TL); + ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, + llvm::Optional<unsigned> NumExpansions); + + /// \brief Transforms a template type parameter type by performing + /// substitution of the corresponding template type argument. + QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, + TemplateTypeParmTypeLoc TL); + + /// \brief Transforms an already-substituted template type parameter pack + /// into either itself (if we aren't substituting into its pack expansion) + /// or the appropriate substituted argument. + QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB, + SubstTemplateTypeParmPackTypeLoc TL); + + ExprResult TransformCallExpr(CallExpr *CE) { + getSema().CallsUndergoingInstantiation.push_back(CE); + ExprResult Result = + TreeTransform<TemplateInstantiator>::TransformCallExpr(CE); + getSema().CallsUndergoingInstantiation.pop_back(); + return move(Result); + } + }; +} + +bool TemplateInstantiator::AlreadyTransformed(QualType T) { + if (T.isNull()) + return true; + + if (T->isDependentType() || T->isVariablyModifiedType()) + return false; + + getSema().MarkDeclarationsReferencedInType(Loc, T); + return true; +} + +Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { + if (!D) + return 0; + + if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { + if (TTP->getDepth() < TemplateArgs.getNumLevels()) { + // If the corresponding template argument is NULL or non-existent, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template, but there were some + // arguments left unspecified. + if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(), + TTP->getPosition())) + return D; + + TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition()); + + if (TTP->isParameterPack()) { + assert(Arg.getKind() == TemplateArgument::Pack && + "Missing argument pack"); + + assert(getSema().ArgumentPackSubstitutionIndex >= 0); + assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + } + + TemplateName Template = Arg.getAsTemplate(); + assert(!Template.isNull() && Template.getAsTemplateDecl() && + "Wrong kind of template template argument"); + return Template.getAsTemplateDecl(); + } + + // Fall through to find the instantiated declaration for this template + // template parameter. + } + + return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs); +} + +Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) { + Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs); + if (!Inst) + return 0; + + getSema().CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return Inst; +} + +NamedDecl * +TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D, + SourceLocation Loc) { + // If the first part of the nested-name-specifier was a template type + // parameter, instantiate that type parameter down to a tag type. + if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) { + const TemplateTypeParmType *TTP + = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD)); + + if (TTP->getDepth() < TemplateArgs.getNumLevels()) { + // FIXME: This needs testing w/ member access expressions. + TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getIndex()); + + if (TTP->isParameterPack()) { + assert(Arg.getKind() == TemplateArgument::Pack && + "Missing argument pack"); + + if (getSema().ArgumentPackSubstitutionIndex == -1) + return 0; + + assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + } + + QualType T = Arg.getAsType(); + if (T.isNull()) + return cast_or_null<NamedDecl>(TransformDecl(Loc, D)); + + if (const TagType *Tag = T->getAs<TagType>()) + return Tag->getDecl(); + + // The resulting type is not a tag; complain. + getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T; + return 0; + } + } + + return cast_or_null<NamedDecl>(TransformDecl(Loc, D)); +} + +VarDecl * +TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl, + TypeSourceInfo *Declarator, + SourceLocation StartLoc, + SourceLocation NameLoc, + IdentifierInfo *Name) { + VarDecl *Var = inherited::RebuildExceptionDecl(ExceptionDecl, Declarator, + StartLoc, NameLoc, Name); + if (Var) + getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var); + return Var; +} + +VarDecl *TemplateInstantiator::RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, + TypeSourceInfo *TSInfo, + QualType T) { + VarDecl *Var = inherited::RebuildObjCExceptionDecl(ExceptionDecl, TSInfo, T); + if (Var) + getSema().CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var); + return Var; +} + +QualType +TemplateInstantiator::RebuildElaboratedType(SourceLocation KeywordLoc, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifierLoc QualifierLoc, + QualType T) { + if (const TagType *TT = T->getAs<TagType>()) { + TagDecl* TD = TT->getDecl(); + + SourceLocation TagLocation = KeywordLoc; + + // FIXME: type might be anonymous. + IdentifierInfo *Id = TD->getIdentifier(); + + // TODO: should we even warn on struct/class mismatches for this? Seems + // like it's likely to produce a lot of spurious errors. + if (Keyword != ETK_None && Keyword != ETK_Typename) { + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); + if (!SemaRef.isAcceptableTagRedeclaration(TD, Kind, /*isDefinition*/false, + TagLocation, *Id)) { + SemaRef.Diag(TagLocation, diag::err_use_with_wrong_tag) + << Id + << FixItHint::CreateReplacement(SourceRange(TagLocation), + TD->getKindName()); + SemaRef.Diag(TD->getLocation(), diag::note_previous_use); + } + } + } + + return TreeTransform<TemplateInstantiator>::RebuildElaboratedType(KeywordLoc, + Keyword, + QualifierLoc, + T); +} + +TemplateName TemplateInstantiator::TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, + QualType ObjectType, + NamedDecl *FirstQualifierInScope) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) { + if (TTP->getDepth() < TemplateArgs.getNumLevels()) { + // If the corresponding template argument is NULL or non-existent, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template, but there were some + // arguments left unspecified. + if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(), + TTP->getPosition())) + return Name; + + TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition()); + + if (TTP->isParameterPack()) { + assert(Arg.getKind() == TemplateArgument::Pack && + "Missing argument pack"); + + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // We have the template argument pack to substitute, but we're not + // actually expanding the enclosing pack expansion yet. So, just + // keep the entire argument pack. + return getSema().Context.getSubstTemplateTemplateParmPack(TTP, Arg); + } + + assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + } + + TemplateName Template = Arg.getAsTemplate(); + assert(!Template.isNull() && "Null template template argument"); + + // We don't ever want to substitute for a qualified template name, since + // the qualifier is handled separately. So, look through the qualified + // template name to its underlying declaration. + if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Template = TemplateName(QTN->getTemplateDecl()); + + return Template; + } + } + + if (SubstTemplateTemplateParmPackStorage *SubstPack + = Name.getAsSubstTemplateTemplateParmPack()) { + if (getSema().ArgumentPackSubstitutionIndex == -1) + return Name; + + const TemplateArgument &ArgPack = SubstPack->getArgumentPack(); + assert(getSema().ArgumentPackSubstitutionIndex < (int)ArgPack.pack_size() && + "Pack substitution index out-of-range"); + return ArgPack.pack_begin()[getSema().ArgumentPackSubstitutionIndex] + .getAsTemplate(); + } + + return inherited::TransformTemplateName(SS, Name, NameLoc, ObjectType, + FirstQualifierInScope); +} + +ExprResult +TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { + if (!E->isTypeDependent()) + return SemaRef.Owned(E); + + FunctionDecl *currentDecl = getSema().getCurFunctionDecl(); + assert(currentDecl && "Must have current function declaration when " + "instantiating."); + + PredefinedExpr::IdentType IT = E->getIdentType(); + + unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); + + llvm::APInt LengthI(32, Length + 1); + QualType ResTy = getSema().Context.CharTy.withConst(); + ResTy = getSema().Context.getConstantArrayType(ResTy, LengthI, + ArrayType::Normal, 0); + PredefinedExpr *PE = + new (getSema().Context) PredefinedExpr(E->getLocation(), ResTy, IT); + return getSema().Owned(PE); +} + +ExprResult +TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, + NonTypeTemplateParmDecl *NTTP) { + // If the corresponding template argument is NULL or non-existent, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template, but there were some + // arguments left unspecified. + if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), + NTTP->getPosition())) + return SemaRef.Owned(E); + + TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition()); + if (NTTP->isParameterPack()) { + assert(Arg.getKind() == TemplateArgument::Pack && + "Missing argument pack"); + + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // We have an argument pack, but we can't select a particular argument + // out of it yet. Therefore, we'll build an expression to hold on to that + // argument pack. + QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs, + E->getLocation(), + NTTP->getDeclName()); + if (TargetType.isNull()) + return ExprError(); + + return new (SemaRef.Context) SubstNonTypeTemplateParmPackExpr(TargetType, + NTTP, + E->getLocation(), + Arg); + } + + assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + } + + // The template argument itself might be an expression, in which + // case we just return that expression. + if (Arg.getKind() == TemplateArgument::Expression) + return SemaRef.Owned(Arg.getAsExpr()); + + if (Arg.getKind() == TemplateArgument::Declaration) { + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); + + // Find the instantiation of the template argument. This is + // required for nested templates. + VD = cast_or_null<ValueDecl>( + getSema().FindInstantiatedDecl(E->getLocation(), + VD, TemplateArgs)); + if (!VD) + return ExprError(); + + // Derive the type we want the substituted decl to have. This had + // better be non-dependent, or these checks will have serious problems. + QualType TargetType; + if (NTTP->isExpandedParameterPack()) + TargetType = NTTP->getExpansionType( + getSema().ArgumentPackSubstitutionIndex); + else if (NTTP->isParameterPack() && + isa<PackExpansionType>(NTTP->getType())) { + TargetType = SemaRef.SubstType( + cast<PackExpansionType>(NTTP->getType())->getPattern(), + TemplateArgs, E->getLocation(), + NTTP->getDeclName()); + } else + TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs, + E->getLocation(), NTTP->getDeclName()); + assert(!TargetType.isNull() && "type substitution failed for param type"); + assert(!TargetType->isDependentType() && "param type still dependent"); + return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, + TargetType, + E->getLocation()); + } + + return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg, + E->getSourceRange().getBegin()); +} + +ExprResult +TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( + SubstNonTypeTemplateParmPackExpr *E) { + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // We aren't expanding the parameter pack, so just return ourselves. + return getSema().Owned(E); + } + + const TemplateArgument &ArgPack = E->getArgumentPack(); + unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; + assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); + + const TemplateArgument &Arg = ArgPack.pack_begin()[Index]; + if (Arg.getKind() == TemplateArgument::Expression) + return SemaRef.Owned(Arg.getAsExpr()); + + if (Arg.getKind() == TemplateArgument::Declaration) { + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); + + // Find the instantiation of the template argument. This is + // required for nested templates. + VD = cast_or_null<ValueDecl>( + getSema().FindInstantiatedDecl(E->getParameterPackLocation(), + VD, TemplateArgs)); + if (!VD) + return ExprError(); + + QualType T; + NonTypeTemplateParmDecl *NTTP = E->getParameterPack(); + if (NTTP->isExpandedParameterPack()) + T = NTTP->getExpansionType(getSema().ArgumentPackSubstitutionIndex); + else if (const PackExpansionType *Expansion + = dyn_cast<PackExpansionType>(NTTP->getType())) + T = SemaRef.SubstType(Expansion->getPattern(), TemplateArgs, + E->getParameterPackLocation(), NTTP->getDeclName()); + else + T = E->getType(); + return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, T, + E->getParameterPackLocation()); + } + + return SemaRef.BuildExpressionFromIntegralTemplateArgument(Arg, + E->getParameterPackLocation()); +} + +ExprResult +TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { + NamedDecl *D = E->getDecl(); + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { + if (NTTP->getDepth() < TemplateArgs.getNumLevels()) + return TransformTemplateParmRefExpr(E, NTTP); + + // We have a non-type template parameter that isn't fully substituted; + // FindInstantiatedDecl will find it in the local instantiation scope. + } + + return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E); +} + +ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( + CXXDefaultArgExpr *E) { + assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())-> + getDescribedFunctionTemplate() && + "Default arg expressions are never formed in dependent cases."); + return SemaRef.BuildCXXDefaultArgExpr(E->getUsedLocation(), + cast<FunctionDecl>(E->getParam()->getDeclContext()), + E->getParam()); +} + +QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, + FunctionProtoTypeLoc TL) { + // We need a local instantiation scope for this function prototype. + LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); + return inherited::TransformFunctionProtoType(TLB, TL); +} + +ParmVarDecl * +TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, + llvm::Optional<unsigned> NumExpansions) { + return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment, + NumExpansions); +} + +QualType +TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, + TemplateTypeParmTypeLoc TL) { + const TemplateTypeParmType *T = TL.getTypePtr(); + if (T->getDepth() < TemplateArgs.getNumLevels()) { + // Replace the template type parameter with its corresponding + // template argument. + + // If the corresponding template argument is NULL or doesn't exist, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template class, but there were some + // arguments left unspecified. + if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) { + TemplateTypeParmTypeLoc NewTL + = TLB.push<TemplateTypeParmTypeLoc>(TL.getType()); + NewTL.setNameLoc(TL.getNameLoc()); + return TL.getType(); + } + + TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex()); + + if (T->isParameterPack()) { + assert(Arg.getKind() == TemplateArgument::Pack && + "Missing argument pack"); + + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // We have the template argument pack, but we're not expanding the + // enclosing pack expansion yet. Just save the template argument + // pack for later substitution. + QualType Result + = getSema().Context.getSubstTemplateTypeParmPackType(T, Arg); + SubstTemplateTypeParmPackTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } + + assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size()); + Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + } + + assert(Arg.getKind() == TemplateArgument::Type && + "Template argument kind mismatch"); + + QualType Replacement = Arg.getAsType(); + + // TODO: only do this uniquing once, at the start of instantiation. + QualType Result + = getSema().Context.getSubstTemplateTypeParmType(T, Replacement); + SubstTemplateTypeParmTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } + + // The template type parameter comes from an inner template (e.g., + // the template parameter list of a member template inside the + // template we are instantiating). Create a new template type + // parameter with the template "level" reduced by one. + TemplateTypeParmDecl *NewTTPDecl = 0; + if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) + NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( + TransformDecl(TL.getNameLoc(), OldTTPDecl)); + + QualType Result + = getSema().Context.getTemplateTypeParmType(T->getDepth() + - TemplateArgs.getNumLevels(), + T->getIndex(), + T->isParameterPack(), + NewTTPDecl); + TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; +} + +QualType +TemplateInstantiator::TransformSubstTemplateTypeParmPackType( + TypeLocBuilder &TLB, + SubstTemplateTypeParmPackTypeLoc TL) { + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // We aren't expanding the parameter pack, so just return ourselves. + SubstTemplateTypeParmPackTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType()); + NewTL.setNameLoc(TL.getNameLoc()); + return TL.getType(); + } + + const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack(); + unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; + assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); + + QualType Result = ArgPack.pack_begin()[Index].getAsType(); + Result = getSema().Context.getSubstTemplateTypeParmType( + TL.getTypePtr()->getReplacedParameter(), + Result); + SubstTemplateTypeParmTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; +} + +/// \brief Perform substitution on the type T with a given set of template +/// arguments. +/// +/// This routine substitutes the given template arguments into the +/// type T and produces the instantiated type. +/// +/// \param T the type into which the template arguments will be +/// substituted. If this type is not dependent, it will be returned +/// immediately. +/// +/// \param TemplateArgs the template arguments that will be +/// substituted for the top-level template parameters within T. +/// +/// \param Loc the location in the source code where this substitution +/// is being performed. It will typically be the location of the +/// declarator (if we're instantiating the type of some declaration) +/// or the location of the type in the source code (if, e.g., we're +/// instantiating the type of a cast expression). +/// +/// \param Entity the name of the entity associated with a declaration +/// being instantiated (if any). May be empty to indicate that there +/// is no such entity (if, e.g., this is a type that occurs as part of +/// a cast expression) or that the entity has no name (e.g., an +/// unnamed function parameter). +/// +/// \returns If the instantiation succeeds, the instantiated +/// type. Otherwise, produces diagnostics and returns a NULL type. +TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, + const MultiLevelTemplateArgumentList &Args, + SourceLocation Loc, + DeclarationName Entity) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + if (!T->getType()->isDependentType() && + !T->getType()->isVariablyModifiedType()) + return T; + + TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + return Instantiator.TransformType(T); +} + +TypeSourceInfo *Sema::SubstType(TypeLoc TL, + const MultiLevelTemplateArgumentList &Args, + SourceLocation Loc, + DeclarationName Entity) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + if (TL.getType().isNull()) + return 0; + + if (!TL.getType()->isDependentType() && + !TL.getType()->isVariablyModifiedType()) { + // FIXME: Make a copy of the TypeLoc data here, so that we can + // return a new TypeSourceInfo. Inefficient! + TypeLocBuilder TLB; + TLB.pushFullCopy(TL); + return TLB.getTypeSourceInfo(Context, TL.getType()); + } + + TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + TypeLocBuilder TLB; + TLB.reserve(TL.getFullDataSize()); + QualType Result = Instantiator.TransformType(TLB, TL); + if (Result.isNull()) + return 0; + + return TLB.getTypeSourceInfo(Context, Result); +} + +/// Deprecated form of the above. +QualType Sema::SubstType(QualType T, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation Loc, DeclarationName Entity) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + // If T is not a dependent type or a variably-modified type, there + // is nothing to do. + if (!T->isDependentType() && !T->isVariablyModifiedType()) + return T; + + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, Entity); + return Instantiator.TransformType(T); +} + +static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) { + if (T->getType()->isDependentType() || T->getType()->isVariablyModifiedType()) + return true; + + TypeLoc TL = T->getTypeLoc().IgnoreParens(); + if (!isa<FunctionProtoTypeLoc>(TL)) + return false; + + FunctionProtoTypeLoc FP = cast<FunctionProtoTypeLoc>(TL); + for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) { + ParmVarDecl *P = FP.getArg(I); + + // The parameter's type as written might be dependent even if the + // decayed type was not dependent. + if (TypeSourceInfo *TSInfo = P->getTypeSourceInfo()) + if (TSInfo->getType()->isDependentType()) + return true; + + // TODO: currently we always rebuild expressions. When we + // properly get lazier about this, we should use the same + // logic to avoid rebuilding prototypes here. + if (P->hasDefaultArg()) + return true; + } + + return false; +} + +/// A form of SubstType intended specifically for instantiating the +/// type of a FunctionDecl. Its purpose is solely to force the +/// instantiation of default-argument expressions. +TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, + const MultiLevelTemplateArgumentList &Args, + SourceLocation Loc, + DeclarationName Entity) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + if (!NeedsInstantiationAsFunctionType(T)) + return T; + + TemplateInstantiator Instantiator(*this, Args, Loc, Entity); + + TypeLocBuilder TLB; + + TypeLoc TL = T->getTypeLoc(); + TLB.reserve(TL.getFullDataSize()); + + QualType Result = Instantiator.TransformType(TLB, TL); + if (Result.isNull()) + return 0; + + return TLB.getTypeSourceInfo(Context, Result); +} + +ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, + const MultiLevelTemplateArgumentList &TemplateArgs, + int indexAdjustment, + llvm::Optional<unsigned> NumExpansions) { + TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); + TypeSourceInfo *NewDI = 0; + + TypeLoc OldTL = OldDI->getTypeLoc(); + if (isa<PackExpansionTypeLoc>(OldTL)) { + PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(OldTL); + + // We have a function parameter pack. Substitute into the pattern of the + // expansion. + NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs, + OldParm->getLocation(), OldParm->getDeclName()); + if (!NewDI) + return 0; + + if (NewDI->getType()->containsUnexpandedParameterPack()) { + // We still have unexpanded parameter packs, which means that + // our function parameter is still a function parameter pack. + // Therefore, make its type a pack expansion type. + NewDI = CheckPackExpansion(NewDI, ExpansionTL.getEllipsisLoc(), + NumExpansions); + } + } else { + NewDI = SubstType(OldDI, TemplateArgs, OldParm->getLocation(), + OldParm->getDeclName()); + } + + if (!NewDI) + return 0; + + if (NewDI->getType()->isVoidType()) { + Diag(OldParm->getLocation(), diag::err_param_with_void_type); + return 0; + } + + ParmVarDecl *NewParm = CheckParameter(Context.getTranslationUnitDecl(), + OldParm->getInnerLocStart(), + OldParm->getLocation(), + OldParm->getIdentifier(), + NewDI->getType(), NewDI, + OldParm->getStorageClass(), + OldParm->getStorageClassAsWritten()); + if (!NewParm) + return 0; + + // Mark the (new) default argument as uninstantiated (if any). + if (OldParm->hasUninstantiatedDefaultArg()) { + Expr *Arg = OldParm->getUninstantiatedDefaultArg(); + NewParm->setUninstantiatedDefaultArg(Arg); + } else if (OldParm->hasUnparsedDefaultArg()) { + NewParm->setUnparsedDefaultArg(); + UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm); + } else if (Expr *Arg = OldParm->getDefaultArg()) + NewParm->setUninstantiatedDefaultArg(Arg); + + NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg()); + + // FIXME: When OldParm is a parameter pack and NewParm is not a parameter + // pack, we actually have a set of instantiated locations. Maintain this set! + if (OldParm->isParameterPack() && !NewParm->isParameterPack()) { + // Add the new parameter to + CurrentInstantiationScope->InstantiatedLocalPackArg(OldParm, NewParm); + } else { + // Introduce an Old -> New mapping + CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm); + } + + // FIXME: OldParm may come from a FunctionProtoType, in which case CurContext + // can be anything, is this right ? + NewParm->setDeclContext(CurContext); + + NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(), + OldParm->getFunctionScopeIndex() + indexAdjustment); + + return NewParm; +} + +/// \brief Substitute the given template arguments into the given set of +/// parameters, producing the set of parameter types that would be generated +/// from such a substitution. +bool Sema::SubstParmTypes(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, + const MultiLevelTemplateArgumentList &TemplateArgs, + llvm::SmallVectorImpl<QualType> &ParamTypes, + llvm::SmallVectorImpl<ParmVarDecl *> *OutParams) { + assert(!ActiveTemplateInstantiations.empty() && + "Cannot perform an instantiation without some context on the " + "instantiation stack"); + + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, + DeclarationName()); + return Instantiator.TransformFunctionTypeParams(Loc, Params, NumParams, 0, + ParamTypes, OutParams); +} + +/// \brief Perform substitution on the base class specifiers of the +/// given class template specialization. +/// +/// Produces a diagnostic and returns true on error, returns false and +/// attaches the instantiated base classes to the class template +/// specialization if successful. +bool +Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, + CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs) { + bool Invalid = false; + llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases; + for (ClassTemplateSpecializationDecl::base_class_iterator + Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end(); + Base != BaseEnd; ++Base) { + if (!Base->getType()->isDependentType()) { + InstantiatedBases.push_back(new (Context) CXXBaseSpecifier(*Base)); + continue; + } + + SourceLocation EllipsisLoc; + TypeSourceInfo *BaseTypeLoc; + if (Base->isPackExpansion()) { + // This is a pack expansion. See whether we should expand it now, or + // wait until later. + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(), + Unexpanded); + bool ShouldExpand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions; + if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(), + Base->getSourceRange(), + Unexpanded.data(), Unexpanded.size(), + TemplateArgs, ShouldExpand, + RetainExpansion, + NumExpansions)) { + Invalid = true; + continue; + } + + // If we should expand this pack expansion now, do so. + if (ShouldExpand) { + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); + + TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), + TemplateArgs, + Base->getSourceRange().getBegin(), + DeclarationName()); + if (!BaseTypeLoc) { + Invalid = true; + continue; + } + + if (CXXBaseSpecifier *InstantiatedBase + = CheckBaseSpecifier(Instantiation, + Base->getSourceRange(), + Base->isVirtual(), + Base->getAccessSpecifierAsWritten(), + BaseTypeLoc, + SourceLocation())) + InstantiatedBases.push_back(InstantiatedBase); + else + Invalid = true; + } + + continue; + } + + // The resulting base specifier will (still) be a pack expansion. + EllipsisLoc = Base->getEllipsisLoc(); + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1); + BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), + TemplateArgs, + Base->getSourceRange().getBegin(), + DeclarationName()); + } else { + BaseTypeLoc = SubstType(Base->getTypeSourceInfo(), + TemplateArgs, + Base->getSourceRange().getBegin(), + DeclarationName()); + } + + if (!BaseTypeLoc) { + Invalid = true; + continue; + } + + if (CXXBaseSpecifier *InstantiatedBase + = CheckBaseSpecifier(Instantiation, + Base->getSourceRange(), + Base->isVirtual(), + Base->getAccessSpecifierAsWritten(), + BaseTypeLoc, + EllipsisLoc)) + InstantiatedBases.push_back(InstantiatedBase); + else + Invalid = true; + } + + if (!Invalid && + AttachBaseSpecifiers(Instantiation, InstantiatedBases.data(), + InstantiatedBases.size())) + Invalid = true; + + return Invalid; +} + +/// \brief Instantiate the definition of a class from a given pattern. +/// +/// \param PointOfInstantiation The point of instantiation within the +/// source code. +/// +/// \param Instantiation is the declaration whose definition is being +/// instantiated. This will be either a class template specialization +/// or a member class of a class template specialization. +/// +/// \param Pattern is the pattern from which the instantiation +/// occurs. This will be either the declaration of a class template or +/// the declaration of a member class of a class template. +/// +/// \param TemplateArgs The template arguments to be substituted into +/// the pattern. +/// +/// \param TSK the kind of implicit or explicit instantiation to perform. +/// +/// \param Complain whether to complain if the class cannot be instantiated due +/// to the lack of a definition. +/// +/// \returns true if an error occurred, false otherwise. +bool +Sema::InstantiateClass(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK, + bool Complain) { + bool Invalid = false; + + CXXRecordDecl *PatternDef + = cast_or_null<CXXRecordDecl>(Pattern->getDefinition()); + if (!PatternDef || PatternDef->isBeingDefined()) { + if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) { + // Say nothing + } else if (PatternDef) { + assert(PatternDef->isBeingDefined()); + Diag(PointOfInstantiation, + diag::err_template_instantiate_within_definition) + << (TSK != TSK_ImplicitInstantiation) + << Context.getTypeDeclType(Instantiation); + // Not much point in noting the template declaration here, since + // we're lexically inside it. + Instantiation->setInvalidDecl(); + } else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) { + Diag(PointOfInstantiation, + diag::err_implicit_instantiate_member_undefined) + << Context.getTypeDeclType(Instantiation); + Diag(Pattern->getLocation(), diag::note_member_of_template_here); + } else { + Diag(PointOfInstantiation, diag::err_template_instantiate_undefined) + << (TSK != TSK_ImplicitInstantiation) + << Context.getTypeDeclType(Instantiation); + Diag(Pattern->getLocation(), diag::note_template_decl_here); + } + return true; + } + Pattern = PatternDef; + + // \brief Record the point of instantiation. + if (MemberSpecializationInfo *MSInfo + = Instantiation->getMemberSpecializationInfo()) { + MSInfo->setTemplateSpecializationKind(TSK); + MSInfo->setPointOfInstantiation(PointOfInstantiation); + } else if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) { + Spec->setTemplateSpecializationKind(TSK); + Spec->setPointOfInstantiation(PointOfInstantiation); + } + + InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); + if (Inst) + return true; + + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + ContextRAII SavedContext(*this, Instantiation); + EnterExpressionEvaluationContext EvalContext(*this, + Sema::PotentiallyEvaluated); + + // If this is an instantiation of a local class, merge this local + // instantiation scope with the enclosing scope. Otherwise, every + // instantiation of a class has its own local instantiation scope. + bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod(); + LocalInstantiationScope Scope(*this, MergeWithParentScope); + + // Pull attributes from the pattern onto the instantiation. + InstantiateAttrs(TemplateArgs, Pattern, Instantiation); + + // Start the definition of this instantiation. + Instantiation->startDefinition(); + + Instantiation->setTagKind(Pattern->getTagKind()); + + // Do substitution on the base class specifiers. + if (SubstBaseSpecifiers(Instantiation, Pattern, TemplateArgs)) + Invalid = true; + + TemplateDeclInstantiator Instantiator(*this, Instantiation, TemplateArgs); + llvm::SmallVector<Decl*, 4> Fields; + llvm::SmallVector<std::pair<FieldDecl*, FieldDecl*>, 4> + FieldsWithMemberInitializers; + for (RecordDecl::decl_iterator Member = Pattern->decls_begin(), + MemberEnd = Pattern->decls_end(); + Member != MemberEnd; ++Member) { + // Don't instantiate members not belonging in this semantic context. + // e.g. for: + // @code + // template <int i> class A { + // class B *g; + // }; + // @endcode + // 'class B' has the template as lexical context but semantically it is + // introduced in namespace scope. + if ((*Member)->getDeclContext() != Pattern) + continue; + + if ((*Member)->isInvalidDecl()) { + Invalid = true; + continue; + } + + Decl *NewMember = Instantiator.Visit(*Member); + if (NewMember) { + if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) { + Fields.push_back(Field); + FieldDecl *OldField = cast<FieldDecl>(*Member); + if (OldField->getInClassInitializer()) + FieldsWithMemberInitializers.push_back(std::make_pair(OldField, + Field)); + } else if (NewMember->isInvalidDecl()) + Invalid = true; + } else { + // FIXME: Eventually, a NULL return will mean that one of the + // instantiations was a semantic disaster, and we'll want to set Invalid = + // true. For now, we expect to skip some members that we can't yet handle. + } + } + + // Finish checking fields. + ActOnFields(0, Instantiation->getLocation(), Instantiation, + Fields.data(), Fields.size(), SourceLocation(), SourceLocation(), + 0); + CheckCompletedCXXClass(Instantiation); + + // Attach any in-class member initializers now the class is complete. + for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) { + FieldDecl *OldField = FieldsWithMemberInitializers[I].first; + FieldDecl *NewField = FieldsWithMemberInitializers[I].second; + Expr *OldInit = OldField->getInClassInitializer(); + ExprResult NewInit = SubstExpr(OldInit, TemplateArgs); + + // If the initialization is no longer dependent, check it now. + if ((OldField->getType()->isDependentType() || OldInit->isTypeDependent()) + && !NewField->getType()->isDependentType() + && !NewInit.get()->isTypeDependent()) { + // FIXME: handle list-initialization + SourceLocation EqualLoc = NewField->getLocation(); + NewInit = PerformCopyInitialization( + InitializedEntity::InitializeMember(NewField), EqualLoc, + NewInit.release()); + + if (!NewInit.isInvalid()) { + CheckImplicitConversions(NewInit.get(), EqualLoc); + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + NewInit = MaybeCreateExprWithCleanups(NewInit); + } + } + + if (NewInit.isInvalid()) + NewField->setInvalidDecl(); + else + NewField->setInClassInitializer(NewInit.release()); + } + + if (!FieldsWithMemberInitializers.empty()) + ActOnFinishDelayedMemberInitializers(Instantiation); + + if (Instantiation->isInvalidDecl()) + Invalid = true; + else { + // Instantiate any out-of-line class template partial + // specializations now. + for (TemplateDeclInstantiator::delayed_partial_spec_iterator + P = Instantiator.delayed_partial_spec_begin(), + PEnd = Instantiator.delayed_partial_spec_end(); + P != PEnd; ++P) { + if (!Instantiator.InstantiateClassTemplatePartialSpecialization( + P->first, + P->second)) { + Invalid = true; + break; + } + } + } + + // Exit the scope of this instantiation. + SavedContext.pop(); + + if (!Invalid) { + Consumer.HandleTagDeclDefinition(Instantiation); + + // Always emit the vtable for an explicit instantiation definition + // of a polymorphic class template specialization. + if (TSK == TSK_ExplicitInstantiationDefinition) + MarkVTableUsed(PointOfInstantiation, Instantiation, true); + } + + return Invalid; +} + +namespace { + /// \brief A partial specialization whose template arguments have matched + /// a given template-id. + struct PartialSpecMatchResult { + ClassTemplatePartialSpecializationDecl *Partial; + TemplateArgumentList *Args; + }; +} + +bool +Sema::InstantiateClassTemplateSpecialization( + SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK, + bool Complain) { + // Perform the actual instantiation on the canonical declaration. + ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>( + ClassTemplateSpec->getCanonicalDecl()); + + // Check whether we have already instantiated or specialized this class + // template specialization. + if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared) { + if (ClassTemplateSpec->getSpecializationKind() == + TSK_ExplicitInstantiationDeclaration && + TSK == TSK_ExplicitInstantiationDefinition) { + // An explicit instantiation definition follows an explicit instantiation + // declaration (C++0x [temp.explicit]p10); go ahead and perform the + // explicit instantiation. + ClassTemplateSpec->setSpecializationKind(TSK); + + // If this is an explicit instantiation definition, mark the + // vtable as used. + if (TSK == TSK_ExplicitInstantiationDefinition) + MarkVTableUsed(PointOfInstantiation, ClassTemplateSpec, true); + + return false; + } + + // We can only instantiate something that hasn't already been + // instantiated or specialized. Fail without any diagnostics: our + // caller will provide an error message. + return true; + } + + if (ClassTemplateSpec->isInvalidDecl()) + return true; + + ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate(); + CXXRecordDecl *Pattern = 0; + + // C++ [temp.class.spec.match]p1: + // When a class template is used in a context that requires an + // instantiation of the class, it is necessary to determine + // whether the instantiation is to be generated using the primary + // template or one of the partial specializations. This is done by + // matching the template arguments of the class template + // specialization with the template argument lists of the partial + // specializations. + typedef PartialSpecMatchResult MatchResult; + llvm::SmallVector<MatchResult, 4> Matched; + llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; + Template->getPartialSpecializations(PartialSpecs); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { + ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; + TemplateDeductionInfo Info(Context, PointOfInstantiation); + if (TemplateDeductionResult Result + = DeduceTemplateArguments(Partial, + ClassTemplateSpec->getTemplateArgs(), + Info)) { + // FIXME: Store the failed-deduction information for use in + // diagnostics, later. + (void)Result; + } else { + Matched.push_back(PartialSpecMatchResult()); + Matched.back().Partial = Partial; + Matched.back().Args = Info.take(); + } + } + + // If we're dealing with a member template where the template parameters + // have been instantiated, this provides the original template parameters + // from which the member template's parameters were instantiated. + llvm::SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters; + + if (Matched.size() >= 1) { + llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); + if (Matched.size() == 1) { + // -- If exactly one matching specialization is found, the + // instantiation is generated from that specialization. + // We don't need to do anything for this. + } else { + // -- If more than one matching specialization is found, the + // partial order rules (14.5.4.2) are used to determine + // whether one of the specializations is more specialized + // than the others. If none of the specializations is more + // specialized than all of the other matching + // specializations, then the use of the class template is + // ambiguous and the program is ill-formed. + for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1, + PEnd = Matched.end(); + P != PEnd; ++P) { + if (getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, + PointOfInstantiation) + == P->Partial) + Best = P; + } + + // Determine if the best partial specialization is more specialized than + // the others. + bool Ambiguous = false; + for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(), + PEnd = Matched.end(); + P != PEnd; ++P) { + if (P != Best && + getMoreSpecializedPartialSpecialization(P->Partial, Best->Partial, + PointOfInstantiation) + != Best->Partial) { + Ambiguous = true; + break; + } + } + + if (Ambiguous) { + // Partial ordering did not produce a clear winner. Complain. + ClassTemplateSpec->setInvalidDecl(); + Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous) + << ClassTemplateSpec; + + // Print the matching partial specializations. + for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(), + PEnd = Matched.end(); + P != PEnd; ++P) + Diag(P->Partial->getLocation(), diag::note_partial_spec_match) + << getTemplateArgumentBindingsText( + P->Partial->getTemplateParameters(), + *P->Args); + + return true; + } + } + + // Instantiate using the best class template partial specialization. + ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->Partial; + while (OrigPartialSpec->getInstantiatedFromMember()) { + // If we've found an explicit specialization of this class template, + // stop here and use that as the pattern. + if (OrigPartialSpec->isMemberSpecialization()) + break; + + OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember(); + } + + Pattern = OrigPartialSpec; + ClassTemplateSpec->setInstantiationOf(Best->Partial, Best->Args); + } else { + // -- If no matches are found, the instantiation is generated + // from the primary template. + ClassTemplateDecl *OrigTemplate = Template; + while (OrigTemplate->getInstantiatedFromMemberTemplate()) { + // If we've found an explicit specialization of this class template, + // stop here and use that as the pattern. + if (OrigTemplate->isMemberSpecialization()) + break; + + OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate(); + } + + Pattern = OrigTemplate->getTemplatedDecl(); + } + + bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec, + Pattern, + getTemplateInstantiationArgs(ClassTemplateSpec), + TSK, + Complain); + + return Result; +} + +/// \brief Instantiates the definitions of all of the member +/// of the given class, which is an instantiation of a class template +/// or a member class of a template. +void +Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, + CXXRecordDecl *Instantiation, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateSpecializationKind TSK) { + for (DeclContext::decl_iterator D = Instantiation->decls_begin(), + DEnd = Instantiation->decls_end(); + D != DEnd; ++D) { + bool SuppressNew = false; + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) { + if (FunctionDecl *Pattern + = Function->getInstantiatedFromMemberFunction()) { + MemberSpecializationInfo *MSInfo + = Function->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information?"); + if (MSInfo->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) + continue; + + if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, + Function, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + SuppressNew) || + SuppressNew) + continue; + + if (Function->isDefined()) + continue; + + if (TSK == TSK_ExplicitInstantiationDefinition) { + // C++0x [temp.explicit]p8: + // An explicit instantiation definition that names a class template + // specialization explicitly instantiates the class template + // specialization and is only an explicit instantiation definition + // of members whose definition is visible at the point of + // instantiation. + if (!Pattern->isDefined()) + continue; + + Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); + + InstantiateFunctionDefinition(PointOfInstantiation, Function); + } else { + Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); + } + } + } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) { + if (Var->isStaticDataMember()) { + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information?"); + if (MSInfo->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) + continue; + + if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, + Var, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + SuppressNew) || + SuppressNew) + continue; + + if (TSK == TSK_ExplicitInstantiationDefinition) { + // C++0x [temp.explicit]p8: + // An explicit instantiation definition that names a class template + // specialization explicitly instantiates the class template + // specialization and is only an explicit instantiation definition + // of members whose definition is visible at the point of + // instantiation. + if (!Var->getInstantiatedFromStaticDataMember() + ->getOutOfLineDefinition()) + continue; + + Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); + InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var); + } else { + Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); + } + } + } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) { + // Always skip the injected-class-name, along with any + // redeclarations of nested classes, since both would cause us + // to try to instantiate the members of a class twice. + if (Record->isInjectedClassName() || Record->getPreviousDeclaration()) + continue; + + MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information?"); + + if (MSInfo->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) + continue; + + if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, + Record, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + SuppressNew) || + SuppressNew) + continue; + + CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass(); + assert(Pattern && "Missing instantiated-from-template information"); + + if (!Record->getDefinition()) { + if (!Pattern->getDefinition()) { + // C++0x [temp.explicit]p8: + // An explicit instantiation definition that names a class template + // specialization explicitly instantiates the class template + // specialization and is only an explicit instantiation definition + // of members whose definition is visible at the point of + // instantiation. + if (TSK == TSK_ExplicitInstantiationDeclaration) { + MSInfo->setTemplateSpecializationKind(TSK); + MSInfo->setPointOfInstantiation(PointOfInstantiation); + } + + continue; + } + + InstantiateClass(PointOfInstantiation, Record, Pattern, + TemplateArgs, + TSK); + } else { + if (TSK == TSK_ExplicitInstantiationDefinition && + Record->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration) { + Record->setTemplateSpecializationKind(TSK); + MarkVTableUsed(PointOfInstantiation, Record, true); + } + } + + Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition()); + if (Pattern) + InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs, + TSK); + } + } +} + +/// \brief Instantiate the definitions of all of the members of the +/// given class template specialization, which was named as part of an +/// explicit instantiation. +void +Sema::InstantiateClassTemplateSpecializationMembers( + SourceLocation PointOfInstantiation, + ClassTemplateSpecializationDecl *ClassTemplateSpec, + TemplateSpecializationKind TSK) { + // C++0x [temp.explicit]p7: + // An explicit instantiation that names a class template + // specialization is an explicit instantion of the same kind + // (declaration or definition) of each of its members (not + // including members inherited from base classes) that has not + // been previously explicitly specialized in the translation unit + // containing the explicit instantiation, except as described + // below. + InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec, + getTemplateInstantiationArgs(ClassTemplateSpec), + TSK); +} + +StmtResult +Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) { + if (!S) + return Owned(S); + + TemplateInstantiator Instantiator(*this, TemplateArgs, + SourceLocation(), + DeclarationName()); + return Instantiator.TransformStmt(S); +} + +ExprResult +Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { + if (!E) + return Owned(E); + + TemplateInstantiator Instantiator(*this, TemplateArgs, + SourceLocation(), + DeclarationName()); + return Instantiator.TransformExpr(E); +} + +bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall, + const MultiLevelTemplateArgumentList &TemplateArgs, + llvm::SmallVectorImpl<Expr *> &Outputs) { + if (NumExprs == 0) + return false; + + TemplateInstantiator Instantiator(*this, TemplateArgs, + SourceLocation(), + DeclarationName()); + return Instantiator.TransformExprs(Exprs, NumExprs, IsCall, Outputs); +} + +NestedNameSpecifierLoc +Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, + const MultiLevelTemplateArgumentList &TemplateArgs) { + if (!NNS) + return NestedNameSpecifierLoc(); + + TemplateInstantiator Instantiator(*this, TemplateArgs, NNS.getBeginLoc(), + DeclarationName()); + return Instantiator.TransformNestedNameSpecifierLoc(NNS); +} + +/// \brief Do template substitution on declaration name info. +DeclarationNameInfo +Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, + const MultiLevelTemplateArgumentList &TemplateArgs) { + TemplateInstantiator Instantiator(*this, TemplateArgs, NameInfo.getLoc(), + NameInfo.getName()); + return Instantiator.TransformDeclarationNameInfo(NameInfo); +} + +TemplateName +Sema::SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, + TemplateName Name, SourceLocation Loc, + const MultiLevelTemplateArgumentList &TemplateArgs) { + TemplateInstantiator Instantiator(*this, TemplateArgs, Loc, + DeclarationName()); + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + return Instantiator.TransformTemplateName(SS, Name, Loc); +} + +bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, + TemplateArgumentListInfo &Result, + const MultiLevelTemplateArgumentList &TemplateArgs) { + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), + DeclarationName()); + + return Instantiator.TransformTemplateArguments(Args, NumArgs, Result); +} + +llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> * +LocalInstantiationScope::findInstantiationOf(const Decl *D) { + for (LocalInstantiationScope *Current = this; Current; + Current = Current->Outer) { + + // Check if we found something within this scope. + const Decl *CheckD = D; + do { + LocalDeclsMap::iterator Found = Current->LocalDecls.find(CheckD); + if (Found != Current->LocalDecls.end()) + return &Found->second; + + // If this is a tag declaration, it's possible that we need to look for + // a previous declaration. + if (const TagDecl *Tag = dyn_cast<TagDecl>(CheckD)) + CheckD = Tag->getPreviousDeclaration(); + else + CheckD = 0; + } while (CheckD); + + // If we aren't combined with our outer scope, we're done. + if (!Current->CombineWithOuterScope) + break; + } + + // If we didn't find the decl, then we either have a sema bug, or we have a + // forward reference to a label declaration. Return null to indicate that + // we have an uninstantiated label. + assert(isa<LabelDecl>(D) && "declaration not instantiated in this scope"); + return 0; +} + +void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) { + llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D]; + if (Stored.isNull()) + Stored = Inst; + else if (Stored.is<Decl *>()) { + assert(Stored.get<Decl *>() == Inst && "Already instantiated this local"); + Stored = Inst; + } else + LocalDecls[D].get<DeclArgumentPack *>()->push_back(Inst); +} + +void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D, + Decl *Inst) { + DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>(); + Pack->push_back(Inst); +} + +void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) { + llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D]; + assert(Stored.isNull() && "Already instantiated this local"); + DeclArgumentPack *Pack = new DeclArgumentPack; + Stored = Pack; + ArgumentPacks.push_back(Pack); +} + +void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack, + const TemplateArgument *ExplicitArgs, + unsigned NumExplicitArgs) { + assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) && + "Already have a partially-substituted pack"); + assert((!PartiallySubstitutedPack + || NumArgsInPartiallySubstitutedPack == NumExplicitArgs) && + "Wrong number of arguments in partially-substituted pack"); + PartiallySubstitutedPack = Pack; + ArgsInPartiallySubstitutedPack = ExplicitArgs; + NumArgsInPartiallySubstitutedPack = NumExplicitArgs; +} + +NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack( + const TemplateArgument **ExplicitArgs, + unsigned *NumExplicitArgs) const { + if (ExplicitArgs) + *ExplicitArgs = 0; + if (NumExplicitArgs) + *NumExplicitArgs = 0; + + for (const LocalInstantiationScope *Current = this; Current; + Current = Current->Outer) { + if (Current->PartiallySubstitutedPack) { + if (ExplicitArgs) + *ExplicitArgs = Current->ArgsInPartiallySubstitutedPack; + if (NumExplicitArgs) + *NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack; + + return Current->PartiallySubstitutedPack; + } + + if (!Current->CombineWithOuterScope) + break; + } + + return 0; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp new file mode 100644 index 0000000..e78aa29 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -0,0 +1,3281 @@ +//===--- SemaTemplateInstantiateDecl.cpp - C++ Template Decl Instantiation ===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements C++ template instantiation for declarations. +// +//===----------------------------------------------------------------------===/ +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/PrettyDeclStackTrace.h" +#include "clang/Sema/Template.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/DependentDiagnostic.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" + +using namespace clang; + +bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, + DeclaratorDecl *NewDecl) { + if (!OldDecl->getQualifierLoc()) + return false; + + NestedNameSpecifierLoc NewQualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), + TemplateArgs); + + if (!NewQualifierLoc) + return true; + + NewDecl->setQualifierInfo(NewQualifierLoc); + return false; +} + +bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, + TagDecl *NewDecl) { + if (!OldDecl->getQualifierLoc()) + return false; + + NestedNameSpecifierLoc NewQualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(), + TemplateArgs); + + if (!NewQualifierLoc) + return true; + + NewDecl->setQualifierInfo(NewQualifierLoc); + return false; +} + +// FIXME: Is this still too simple? +void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, + Decl *Tmpl, Decl *New) { + for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end(); + i != e; ++i) { + const Attr *TmplAttr = *i; + // FIXME: This should be generalized to more than just the AlignedAttr. + if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) { + if (Aligned->isAlignmentDependent()) { + // The alignment expression is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(*this, + Sema::Unevaluated); + + if (Aligned->isAlignmentExpr()) { + ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(), + TemplateArgs); + if (!Result.isInvalid()) + AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>()); + } + else { + TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(), + TemplateArgs, + Aligned->getLocation(), + DeclarationName()); + if (Result) + AddAlignedAttr(Aligned->getLocation(), New, Result); + } + continue; + } + } + + // FIXME: Is cloning correct for all attributes? + Attr *NewAttr = TmplAttr->clone(Context); + New->addAttr(NewAttr); + } +} + +Decl * +TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { + assert(false && "Translation units cannot be instantiated"); + return D; +} + +Decl * +TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { + LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier()); + Owner->addDecl(Inst); + return Inst; +} + +Decl * +TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { + assert(false && "Namespaces cannot be instantiated"); + return D; +} + +Decl * +TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + NamespaceAliasDecl *Inst + = NamespaceAliasDecl::Create(SemaRef.Context, Owner, + D->getNamespaceLoc(), + D->getAliasLoc(), + D->getIdentifier(), + D->getQualifierLoc(), + D->getTargetNameLoc(), + D->getNamespace()); + Owner->addDecl(Inst); + return Inst; +} + +Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, + bool IsTypeAlias) { + bool Invalid = false; + TypeSourceInfo *DI = D->getTypeSourceInfo(); + if (DI->getType()->isDependentType() || + DI->getType()->isVariablyModifiedType()) { + DI = SemaRef.SubstType(DI, TemplateArgs, + D->getLocation(), D->getDeclName()); + if (!DI) { + Invalid = true; + DI = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.Context.IntTy); + } + } else { + SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); + } + + // Create the new typedef + TypedefNameDecl *Typedef; + if (IsTypeAlias) + Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); + else + Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); + if (Invalid) + Typedef->setInvalidDecl(); + + // If the old typedef was the name for linkage purposes of an anonymous + // tag decl, re-establish that relationship for the new typedef. + if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) { + TagDecl *oldTag = oldTagType->getDecl(); + if (oldTag->getTypedefNameForAnonDecl() == D) { + TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl(); + assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl()); + newTag->setTypedefNameForAnonDecl(Typedef); + } + } + + if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) { + NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, + TemplateArgs); + if (!InstPrev) + return 0; + + Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev)); + } + + SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); + + Typedef->setAccess(D->getAccess()); + + return Typedef; +} + +Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { + Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/false); + Owner->addDecl(Typedef); + return Typedef; +} + +Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { + Decl *Typedef = InstantiateTypedefNameDecl(D, /*IsTypeAlias=*/true); + Owner->addDecl(Typedef); + return Typedef; +} + +Decl * +TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { + // Create a local instantiation scope for this type alias template, which + // will contain the instantiations of the template parameters. + LocalInstantiationScope Scope(SemaRef); + + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return 0; + + TypeAliasDecl *Pattern = D->getTemplatedDecl(); + + TypeAliasTemplateDecl *PrevAliasTemplate = 0; + if (Pattern->getPreviousDeclaration()) { + DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); + if (Found.first != Found.second) { + PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first); + } + } + + TypeAliasDecl *AliasInst = cast_or_null<TypeAliasDecl>( + InstantiateTypedefNameDecl(Pattern, /*IsTypeAlias=*/true)); + if (!AliasInst) + return 0; + + TypeAliasTemplateDecl *Inst + = TypeAliasTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getDeclName(), InstParams, AliasInst); + if (PrevAliasTemplate) + Inst->setPreviousDeclaration(PrevAliasTemplate); + + Inst->setAccess(D->getAccess()); + + if (!PrevAliasTemplate) + Inst->setInstantiatedFromMemberTemplate(D); + + Owner->addDecl(Inst); + + return Inst; +} + +/// \brief Instantiate an initializer, breaking it into separate +/// initialization arguments. +/// +/// \param S The semantic analysis object. +/// +/// \param Init The initializer to instantiate. +/// +/// \param TemplateArgs Template arguments to be substituted into the +/// initializer. +/// +/// \param NewArgs Will be filled in with the instantiation arguments. +/// +/// \returns true if an error occurred, false otherwise +static bool InstantiateInitializer(Sema &S, Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + SourceLocation &LParenLoc, + ASTOwningVector<Expr*> &NewArgs, + SourceLocation &RParenLoc) { + NewArgs.clear(); + LParenLoc = SourceLocation(); + RParenLoc = SourceLocation(); + + if (!Init) + return false; + + if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) + Init = ExprTemp->getSubExpr(); + + while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) + Init = Binder->getSubExpr(); + + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) + Init = ICE->getSubExprAsWritten(); + + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + LParenLoc = ParenList->getLParenLoc(); + RParenLoc = ParenList->getRParenLoc(); + return S.SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(), + true, TemplateArgs, NewArgs); + } + + if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { + if (!isa<CXXTemporaryObjectExpr>(Construct)) { + if (S.SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, + TemplateArgs, NewArgs)) + return true; + + // FIXME: Fake locations! + LParenLoc = S.PP.getLocForEndOfToken(Init->getLocStart()); + RParenLoc = LParenLoc; + return false; + } + } + + ExprResult Result = S.SubstExpr(Init, TemplateArgs); + if (Result.isInvalid()) + return true; + + NewArgs.push_back(Result.takeAs<Expr>()); + return false; +} + +Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { + // If this is the variable for an anonymous struct or union, + // instantiate the anonymous struct/union type first. + if (const RecordType *RecordTy = D->getType()->getAs<RecordType>()) + if (RecordTy->getDecl()->isAnonymousStructOrUnion()) + if (!VisitCXXRecordDecl(cast<CXXRecordDecl>(RecordTy->getDecl()))) + return 0; + + // Do substitution on the type of the declaration + TypeSourceInfo *DI = SemaRef.SubstType(D->getTypeSourceInfo(), + TemplateArgs, + D->getTypeSpecStartLoc(), + D->getDeclName()); + if (!DI) + return 0; + + if (DI->getType()->isFunctionType()) { + SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function) + << D->isStaticDataMember() << DI->getType(); + return 0; + } + + // Build the instantiated declaration + VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, + D->getInnerLocStart(), + D->getLocation(), D->getIdentifier(), + DI->getType(), DI, + D->getStorageClass(), + D->getStorageClassAsWritten()); + Var->setThreadSpecified(D->isThreadSpecified()); + Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); + Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Var)) + return 0; + + // If we are instantiating a static data member defined + // out-of-line, the instantiation will have the same lexical + // context (which will be a namespace scope) as the template. + if (D->isOutOfLine()) + Var->setLexicalDeclContext(D->getLexicalDeclContext()); + + Var->setAccess(D->getAccess()); + + if (!D->isStaticDataMember()) { + Var->setUsed(D->isUsed(false)); + Var->setReferenced(D->isReferenced()); + } + + // FIXME: In theory, we could have a previous declaration for variables that + // are not static data members. + bool Redeclaration = false; + // FIXME: having to fake up a LookupResult is dumb. + LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + if (D->isStaticDataMember()) + SemaRef.LookupQualifiedName(Previous, Owner, false); + SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration); + + if (D->isOutOfLine()) { + if (!D->isStaticDataMember()) + D->getLexicalDeclContext()->addDecl(Var); + Owner->makeDeclVisibleInContext(Var); + } else { + Owner->addDecl(Var); + if (Owner->isFunctionOrMethod()) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var); + } + SemaRef.InstantiateAttrs(TemplateArgs, D, Var); + + // Link instantiations of static data members back to the template from + // which they were instantiated. + if (Var->isStaticDataMember()) + SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, + TSK_ImplicitInstantiation); + + if (Var->getAnyInitializer()) { + // We already have an initializer in the class. + } else if (D->getInit()) { + if (Var->isStaticDataMember() && !D->isOutOfLine()) + SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated); + else + SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + + // Instantiate the initializer. + SourceLocation LParenLoc, RParenLoc; + ASTOwningVector<Expr*> InitArgs(SemaRef); + if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc, + InitArgs, RParenLoc)) { + bool TypeMayContainAuto = true; + // Attach the initializer to the declaration, if we have one. + if (InitArgs.size() == 0) + SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto); + else if (D->hasCXXDirectInitializer()) { + // Add the direct initializer to the declaration. + SemaRef.AddCXXDirectInitializerToDecl(Var, + LParenLoc, + move_arg(InitArgs), + RParenLoc, + TypeMayContainAuto); + } else { + assert(InitArgs.size() == 1); + Expr *Init = InitArgs.take()[0]; + SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto); + } + } else { + // FIXME: Not too happy about invalidating the declaration + // because of a bogus initializer. + Var->setInvalidDecl(); + } + + SemaRef.PopExpressionEvaluationContext(); + } else if ((!Var->isStaticDataMember() || Var->isOutOfLine()) && + !Var->isCXXForRangeDecl()) + SemaRef.ActOnUninitializedDecl(Var, false); + + // Diagnose unused local variables. + if (!Var->isInvalidDecl() && Owner->isFunctionOrMethod() && !Var->isUsed()) + SemaRef.DiagnoseUnusedDecl(Var); + + return Var; +} + +Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) { + AccessSpecDecl* AD + = AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner, + D->getAccessSpecifierLoc(), D->getColonLoc()); + Owner->addHiddenDecl(AD); + return AD; +} + +Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { + bool Invalid = false; + TypeSourceInfo *DI = D->getTypeSourceInfo(); + if (DI->getType()->isDependentType() || + DI->getType()->isVariablyModifiedType()) { + DI = SemaRef.SubstType(DI, TemplateArgs, + D->getLocation(), D->getDeclName()); + if (!DI) { + DI = D->getTypeSourceInfo(); + Invalid = true; + } else if (DI->getType()->isFunctionType()) { + // C++ [temp.arg.type]p3: + // If a declaration acquires a function type through a type + // dependent on a template-parameter and this causes a + // declaration that does not use the syntactic form of a + // function declarator to have function type, the program is + // ill-formed. + SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) + << DI->getType(); + Invalid = true; + } + } else { + SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); + } + + Expr *BitWidth = D->getBitWidth(); + if (Invalid) + BitWidth = 0; + else if (BitWidth) { + // The bit-width expression is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult InstantiatedBitWidth + = SemaRef.SubstExpr(BitWidth, TemplateArgs); + if (InstantiatedBitWidth.isInvalid()) { + Invalid = true; + BitWidth = 0; + } else + BitWidth = InstantiatedBitWidth.takeAs<Expr>(); + } + + FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), + DI->getType(), DI, + cast<RecordDecl>(Owner), + D->getLocation(), + D->isMutable(), + BitWidth, + D->hasInClassInitializer(), + D->getTypeSpecStartLoc(), + D->getAccess(), + 0); + if (!Field) { + cast<Decl>(Owner)->setInvalidDecl(); + return 0; + } + + SemaRef.InstantiateAttrs(TemplateArgs, D, Field); + + if (Invalid) + Field->setInvalidDecl(); + + if (!Field->getDeclName()) { + // Keep track of where this decl came from. + SemaRef.Context.setInstantiatedFromUnnamedFieldDecl(Field, D); + } + if (CXXRecordDecl *Parent= dyn_cast<CXXRecordDecl>(Field->getDeclContext())) { + if (Parent->isAnonymousStructOrUnion() && + Parent->getRedeclContext()->isFunctionOrMethod()) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Field); + } + + Field->setImplicit(D->isImplicit()); + Field->setAccess(D->getAccess()); + Owner->addDecl(Field); + + return Field; +} + +Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { + NamedDecl **NamedChain = + new (SemaRef.Context)NamedDecl*[D->getChainingSize()]; + + int i = 0; + for (IndirectFieldDecl::chain_iterator PI = + D->chain_begin(), PE = D->chain_end(); + PI != PE; ++PI) { + NamedDecl *Next = SemaRef.FindInstantiatedDecl(D->getLocation(), *PI, + TemplateArgs); + if (!Next) + return 0; + + NamedChain[i++] = Next; + } + + QualType T = cast<FieldDecl>(NamedChain[i-1])->getType(); + IndirectFieldDecl* IndirectField + = IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier(), T, + NamedChain, D->getChainingSize()); + + + IndirectField->setImplicit(D->isImplicit()); + IndirectField->setAccess(D->getAccess()); + Owner->addDecl(IndirectField); + return IndirectField; +} + +Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { + // Handle friend type expressions by simply substituting template + // parameters into the pattern type and checking the result. + if (TypeSourceInfo *Ty = D->getFriendType()) { + TypeSourceInfo *InstTy; + // If this is an unsupported friend, don't bother substituting template + // arguments into it. The actual type referred to won't be used by any + // parts of Clang, and may not be valid for instantiating. Just use the + // same info for the instantiated friend. + if (D->isUnsupportedFriend()) { + InstTy = Ty; + } else { + InstTy = SemaRef.SubstType(Ty, TemplateArgs, + D->getLocation(), DeclarationName()); + } + if (!InstTy) + return 0; + + FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy); + if (!FD) + return 0; + + FD->setAccess(AS_public); + FD->setUnsupportedFriend(D->isUnsupportedFriend()); + Owner->addDecl(FD); + return FD; + } + + NamedDecl *ND = D->getFriendDecl(); + assert(ND && "friend decl must be a decl or a type!"); + + // All of the Visit implementations for the various potential friend + // declarations have to be carefully written to work for friend + // objects, with the most important detail being that the target + // decl should almost certainly not be placed in Owner. + Decl *NewND = Visit(ND); + if (!NewND) return 0; + + FriendDecl *FD = + FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), + cast<NamedDecl>(NewND), D->getFriendLoc()); + FD->setAccess(AS_public); + FD->setUnsupportedFriend(D->isUnsupportedFriend()); + Owner->addDecl(FD); + return FD; +} + +Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { + Expr *AssertExpr = D->getAssertExpr(); + + // The expression in a static assertion is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult InstantiatedAssertExpr + = SemaRef.SubstExpr(AssertExpr, TemplateArgs); + if (InstantiatedAssertExpr.isInvalid()) + return 0; + + ExprResult Message(D->getMessage()); + D->getMessage(); + return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(), + InstantiatedAssertExpr.get(), + Message.get(), + D->getRParenLoc()); +} + +Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { + EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), + /*PrevDecl=*/0, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed()); + if (D->isFixed()) { + if (TypeSourceInfo* TI = D->getIntegerTypeSourceInfo()) { + // If we have type source information for the underlying type, it means it + // has been explicitly set by the user. Perform substitution on it before + // moving on. + SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); + Enum->setIntegerTypeSourceInfo(SemaRef.SubstType(TI, + TemplateArgs, + UnderlyingLoc, + DeclarationName())); + + if (!Enum->getIntegerTypeSourceInfo()) + Enum->setIntegerType(SemaRef.Context.IntTy); + } + else { + assert(!D->getIntegerType()->isDependentType() + && "Dependent type without type source info"); + Enum->setIntegerType(D->getIntegerType()); + } + } + + SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); + + Enum->setInstantiationOfMemberEnum(D); + Enum->setAccess(D->getAccess()); + if (SubstQualifier(D, Enum)) return 0; + Owner->addDecl(Enum); + Enum->startDefinition(); + + if (D->getDeclContext()->isFunctionOrMethod()) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); + + llvm::SmallVector<Decl*, 4> Enumerators; + + EnumConstantDecl *LastEnumConst = 0; + for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(), + ECEnd = D->enumerator_end(); + EC != ECEnd; ++EC) { + // The specified value for the enumerator. + ExprResult Value = SemaRef.Owned((Expr *)0); + if (Expr *UninstValue = EC->getInitExpr()) { + // The enumerator's value expression is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::Unevaluated); + + Value = SemaRef.SubstExpr(UninstValue, TemplateArgs); + } + + // Drop the initial value and continue. + bool isInvalid = false; + if (Value.isInvalid()) { + Value = SemaRef.Owned((Expr *)0); + isInvalid = true; + } + + EnumConstantDecl *EnumConst + = SemaRef.CheckEnumConstant(Enum, LastEnumConst, + EC->getLocation(), EC->getIdentifier(), + Value.get()); + + if (isInvalid) { + if (EnumConst) + EnumConst->setInvalidDecl(); + Enum->setInvalidDecl(); + } + + if (EnumConst) { + SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst); + + EnumConst->setAccess(Enum->getAccess()); + Enum->addDecl(EnumConst); + Enumerators.push_back(EnumConst); + LastEnumConst = EnumConst; + + if (D->getDeclContext()->isFunctionOrMethod()) { + // If the enumeration is within a function or method, record the enum + // constant as a local. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst); + } + } + } + + // FIXME: Fixup LBraceLoc and RBraceLoc + // FIXME: Empty Scope and AttributeList (required to handle attribute packed). + SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), SourceLocation(), + Enum, + Enumerators.data(), Enumerators.size(), + 0, 0); + + return Enum; +} + +Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { + assert(false && "EnumConstantDecls can only occur within EnumDecls."); + return 0; +} + +Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { + bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); + + // Create a local instantiation scope for this class template, which + // will contain the instantiations of the template parameters. + LocalInstantiationScope Scope(SemaRef); + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + + CXXRecordDecl *Pattern = D->getTemplatedDecl(); + + // Instantiate the qualifier. We have to do this first in case + // we're a friend declaration, because if we are then we need to put + // the new declaration in the appropriate context. + NestedNameSpecifierLoc QualifierLoc = Pattern->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + TemplateArgs); + if (!QualifierLoc) + return 0; + } + + CXXRecordDecl *PrevDecl = 0; + ClassTemplateDecl *PrevClassTemplate = 0; + + if (!isFriend && Pattern->getPreviousDeclaration()) { + DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); + if (Found.first != Found.second) { + PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first); + if (PrevClassTemplate) + PrevDecl = PrevClassTemplate->getTemplatedDecl(); + } + } + + // If this isn't a friend, then it's a member template, in which + // case we just want to build the instantiation in the + // specialization. If it is a friend, we want to build it in + // the appropriate context. + DeclContext *DC = Owner; + if (isFriend) { + if (QualifierLoc) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + DC = SemaRef.computeDeclContext(SS); + if (!DC) return 0; + } else { + DC = SemaRef.FindInstantiatedContext(Pattern->getLocation(), + Pattern->getDeclContext(), + TemplateArgs); + } + + // Look for a previous declaration of the template in the owning + // context. + LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + SemaRef.LookupQualifiedName(R, DC); + + if (R.isSingleResult()) { + PrevClassTemplate = R.getAsSingle<ClassTemplateDecl>(); + if (PrevClassTemplate) + PrevDecl = PrevClassTemplate->getTemplatedDecl(); + } + + if (!PrevClassTemplate && QualifierLoc) { + SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) + << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC + << QualifierLoc.getSourceRange(); + return 0; + } + + bool AdoptedPreviousTemplateParams = false; + if (PrevClassTemplate) { + bool Complain = true; + + // HACK: libstdc++ 4.2.1 contains an ill-formed friend class + // template for struct std::tr1::__detail::_Map_base, where the + // template parameters of the friend declaration don't match the + // template parameters of the original declaration. In this one + // case, we don't complain about the ill-formed friend + // declaration. + if (isFriend && Pattern->getIdentifier() && + Pattern->getIdentifier()->isStr("_Map_base") && + DC->isNamespace() && + cast<NamespaceDecl>(DC)->getIdentifier() && + cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__detail")) { + DeclContext *DCParent = DC->getParent(); + if (DCParent->isNamespace() && + cast<NamespaceDecl>(DCParent)->getIdentifier() && + cast<NamespaceDecl>(DCParent)->getIdentifier()->isStr("tr1")) { + DeclContext *DCParent2 = DCParent->getParent(); + if (DCParent2->isNamespace() && + cast<NamespaceDecl>(DCParent2)->getIdentifier() && + cast<NamespaceDecl>(DCParent2)->getIdentifier()->isStr("std") && + DCParent2->getParent()->isTranslationUnit()) + Complain = false; + } + } + + TemplateParameterList *PrevParams + = PrevClassTemplate->getTemplateParameters(); + + // Make sure the parameter lists match. + if (!SemaRef.TemplateParameterListsAreEqual(InstParams, PrevParams, + Complain, + Sema::TPL_TemplateMatch)) { + if (Complain) + return 0; + + AdoptedPreviousTemplateParams = true; + InstParams = PrevParams; + } + + // Do some additional validation, then merge default arguments + // from the existing declarations. + if (!AdoptedPreviousTemplateParams && + SemaRef.CheckTemplateParameterList(InstParams, PrevParams, + Sema::TPC_ClassTemplate)) + return 0; + } + } + + CXXRecordDecl *RecordInst + = CXXRecordDecl::Create(SemaRef.Context, Pattern->getTagKind(), DC, + Pattern->getLocStart(), Pattern->getLocation(), + Pattern->getIdentifier(), PrevDecl, + /*DelayTypeCreation=*/true); + + if (QualifierLoc) + RecordInst->setQualifierInfo(QualifierLoc); + + ClassTemplateDecl *Inst + = ClassTemplateDecl::Create(SemaRef.Context, DC, D->getLocation(), + D->getIdentifier(), InstParams, RecordInst, + PrevClassTemplate); + RecordInst->setDescribedClassTemplate(Inst); + + if (isFriend) { + if (PrevClassTemplate) + Inst->setAccess(PrevClassTemplate->getAccess()); + else + Inst->setAccess(D->getAccess()); + + Inst->setObjectOfFriendDecl(PrevClassTemplate != 0); + // TODO: do we want to track the instantiation progeny of this + // friend target decl? + } else { + Inst->setAccess(D->getAccess()); + if (!PrevClassTemplate) + Inst->setInstantiatedFromMemberTemplate(D); + } + + // Trigger creation of the type for the instantiation. + SemaRef.Context.getInjectedClassNameType(RecordInst, + Inst->getInjectedClassNameSpecialization()); + + // Finish handling of friends. + if (isFriend) { + DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false); + return Inst; + } + + Owner->addDecl(Inst); + + if (!PrevClassTemplate) { + // Queue up any out-of-line partial specializations of this member + // class template; the client will force their instantiation once + // the enclosing class has been instantiated. + llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; + D->getPartialSpecializations(PartialSpecs); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) + if (PartialSpecs[I]->isOutOfLine()) + OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I])); + } + + return Inst; +} + +Decl * +TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D) { + ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); + + // Lookup the already-instantiated declaration in the instantiation + // of the class template and return that. + DeclContext::lookup_result Found + = Owner->lookup(ClassTemplate->getDeclName()); + if (Found.first == Found.second) + return 0; + + ClassTemplateDecl *InstClassTemplate + = dyn_cast<ClassTemplateDecl>(*Found.first); + if (!InstClassTemplate) + return 0; + + if (ClassTemplatePartialSpecializationDecl *Result + = InstClassTemplate->findPartialSpecInstantiatedFromMember(D)) + return Result; + + return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D); +} + +Decl * +TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + // Create a local instantiation scope for this function template, which + // will contain the instantiations of the template parameters and then get + // merged with the local instantiation scope for the function template + // itself. + LocalInstantiationScope Scope(SemaRef); + + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + + FunctionDecl *Instantiated = 0; + if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl())) + Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod, + InstParams)); + else + Instantiated = cast_or_null<FunctionDecl>(VisitFunctionDecl( + D->getTemplatedDecl(), + InstParams)); + + if (!Instantiated) + return 0; + + Instantiated->setAccess(D->getAccess()); + + // Link the instantiated function template declaration to the function + // template from which it was instantiated. + FunctionTemplateDecl *InstTemplate + = Instantiated->getDescribedFunctionTemplate(); + InstTemplate->setAccess(D->getAccess()); + assert(InstTemplate && + "VisitFunctionDecl/CXXMethodDecl didn't create a template!"); + + bool isFriend = (InstTemplate->getFriendObjectKind() != Decl::FOK_None); + + // Link the instantiation back to the pattern *unless* this is a + // non-definition friend declaration. + if (!InstTemplate->getInstantiatedFromMemberTemplate() && + !(isFriend && !D->getTemplatedDecl()->isThisDeclarationADefinition())) + InstTemplate->setInstantiatedFromMemberTemplate(D); + + // Make declarations visible in the appropriate context. + if (!isFriend) + Owner->addDecl(InstTemplate); + + return InstTemplate; +} + +Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { + CXXRecordDecl *PrevDecl = 0; + if (D->isInjectedClassName()) + PrevDecl = cast<CXXRecordDecl>(Owner); + else if (D->getPreviousDeclaration()) { + NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), + D->getPreviousDeclaration(), + TemplateArgs); + if (!Prev) return 0; + PrevDecl = cast<CXXRecordDecl>(Prev); + } + + CXXRecordDecl *Record + = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner, + D->getLocStart(), D->getLocation(), + D->getIdentifier(), PrevDecl); + + // Substitute the nested name specifier, if any. + if (SubstQualifier(D, Record)) + return 0; + + Record->setImplicit(D->isImplicit()); + // FIXME: Check against AS_none is an ugly hack to work around the issue that + // the tag decls introduced by friend class declarations don't have an access + // specifier. Remove once this area of the code gets sorted out. + if (D->getAccess() != AS_none) + Record->setAccess(D->getAccess()); + if (!D->isInjectedClassName()) + Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); + + // If the original function was part of a friend declaration, + // inherit its namespace state. + if (Decl::FriendObjectKind FOK = D->getFriendObjectKind()) + Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared); + + // Make sure that anonymous structs and unions are recorded. + if (D->isAnonymousStructOrUnion()) { + Record->setAnonymousStructOrUnion(true); + if (Record->getDeclContext()->getRedeclContext()->isFunctionOrMethod()) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Record); + } + + Owner->addDecl(Record); + return Record; +} + +/// Normal class members are of more specific types and therefore +/// don't make it here. This function serves two purposes: +/// 1) instantiating function templates +/// 2) substituting friend declarations +/// FIXME: preserve function definitions in case #2 +Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, + TemplateParameterList *TemplateParams) { + // Check whether there is already a function template specialization for + // this declaration. + FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); + void *InsertPos = 0; + if (FunctionTemplate && !TemplateParams) { + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); + + FunctionDecl *SpecFunc + = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, + InsertPos); + + // If we already have a function template specialization, return it. + if (SpecFunc) + return SpecFunc; + } + + bool isFriend; + if (FunctionTemplate) + isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None); + else + isFriend = (D->getFriendObjectKind() != Decl::FOK_None); + + bool MergeWithParentScope = (TemplateParams != 0) || + Owner->isFunctionOrMethod() || + !(isa<Decl>(Owner) && + cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); + LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); + + llvm::SmallVector<ParmVarDecl *, 4> Params; + TypeSourceInfo *TInfo = D->getTypeSourceInfo(); + TInfo = SubstFunctionType(D, Params); + if (!TInfo) + return 0; + QualType T = TInfo->getType(); + + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + TemplateArgs); + if (!QualifierLoc) + return 0; + } + + // If we're instantiating a local function declaration, put the result + // in the owner; otherwise we need to find the instantiated context. + DeclContext *DC; + if (D->getDeclContext()->isFunctionOrMethod()) + DC = Owner; + else if (isFriend && QualifierLoc) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + DC = SemaRef.computeDeclContext(SS); + if (!DC) return 0; + } else { + DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), + TemplateArgs); + } + + FunctionDecl *Function = + FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), + D->getLocation(), D->getDeclName(), T, TInfo, + D->getStorageClass(), D->getStorageClassAsWritten(), + D->isInlineSpecified(), D->hasWrittenPrototype()); + + if (QualifierLoc) + Function->setQualifierInfo(QualifierLoc); + + DeclContext *LexicalDC = Owner; + if (!isFriend && D->isOutOfLine()) { + assert(D->getDeclContext()->isFileContext()); + LexicalDC = D->getDeclContext(); + } + + Function->setLexicalDeclContext(LexicalDC); + + // Attach the parameters + for (unsigned P = 0; P < Params.size(); ++P) + if (Params[P]) + Params[P]->setOwningFunction(Function); + Function->setParams(Params.data(), Params.size()); + + SourceLocation InstantiateAtPOI; + if (TemplateParams) { + // Our resulting instantiation is actually a function template, since we + // are substituting only the outer template parameters. For example, given + // + // template<typename T> + // struct X { + // template<typename U> friend void f(T, U); + // }; + // + // X<int> x; + // + // We are instantiating the friend function template "f" within X<int>, + // which means substituting int for T, but leaving "f" as a friend function + // template. + // Build the function template itself. + FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, DC, + Function->getLocation(), + Function->getDeclName(), + TemplateParams, Function); + Function->setDescribedFunctionTemplate(FunctionTemplate); + + FunctionTemplate->setLexicalDeclContext(LexicalDC); + + if (isFriend && D->isThisDeclarationADefinition()) { + // TODO: should we remember this connection regardless of whether + // the friend declaration provided a body? + FunctionTemplate->setInstantiatedFromMemberTemplate( + D->getDescribedFunctionTemplate()); + } + } else if (FunctionTemplate) { + // Record this function template specialization. + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); + Function->setFunctionTemplateSpecialization(FunctionTemplate, + TemplateArgumentList::CreateCopy(SemaRef.Context, + Innermost.first, + Innermost.second), + InsertPos); + } else if (isFriend && D->isThisDeclarationADefinition()) { + // TODO: should we remember this connection regardless of whether + // the friend declaration provided a body? + Function->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); + } + + if (InitFunctionInstantiation(Function, D)) + Function->setInvalidDecl(); + + bool Redeclaration = false; + bool isExplicitSpecialization = false; + + LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(), + Sema::LookupOrdinaryName, Sema::ForRedeclaration); + + if (DependentFunctionTemplateSpecializationInfo *Info + = D->getDependentSpecializationInfo()) { + assert(isFriend && "non-friend has dependent specialization info?"); + + // This needs to be set now for future sanity. + Function->setObjectOfFriendDecl(/*HasPrevious*/ true); + + // Instantiate the explicit template arguments. + TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), + Info->getRAngleLoc()); + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return 0; + + // Map the candidate templates to their instantiations. + for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { + Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(), + Info->getTemplate(I), + TemplateArgs); + if (!Temp) return 0; + + Previous.addDecl(cast<FunctionTemplateDecl>(Temp)); + } + + if (SemaRef.CheckFunctionTemplateSpecialization(Function, + &ExplicitArgs, + Previous)) + Function->setInvalidDecl(); + + isExplicitSpecialization = true; + + } else if (TemplateParams || !FunctionTemplate) { + // Look only into the namespace where the friend would be declared to + // find a previous declaration. This is the innermost enclosing namespace, + // as described in ActOnFriendFunctionDecl. + SemaRef.LookupQualifiedName(Previous, DC); + + // In C++, the previous declaration we find might be a tag type + // (class or enum). In this case, the new declaration will hide the + // tag type. Note that this does does not apply if we're declaring a + // typedef (C++ [dcl.typedef]p4). + if (Previous.isSingleTagDecl()) + Previous.clear(); + } + + SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous, + isExplicitSpecialization, Redeclaration); + + NamedDecl *PrincipalDecl = (TemplateParams + ? cast<NamedDecl>(FunctionTemplate) + : Function); + + // If the original function was part of a friend declaration, + // inherit its namespace state and add it to the owner. + if (isFriend) { + NamedDecl *PrevDecl; + if (TemplateParams) + PrevDecl = FunctionTemplate->getPreviousDeclaration(); + else + PrevDecl = Function->getPreviousDeclaration(); + + PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0); + DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false); + + bool queuedInstantiation = false; + + if (!SemaRef.getLangOptions().CPlusPlus0x && + D->isThisDeclarationADefinition()) { + // Check for a function body. + const FunctionDecl *Definition = 0; + if (Function->isDefined(Definition) && + Definition->getTemplateSpecializationKind() == TSK_Undeclared) { + SemaRef.Diag(Function->getLocation(), diag::err_redefinition) + << Function->getDeclName(); + SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition); + Function->setInvalidDecl(); + } + // Check for redefinitions due to other instantiations of this or + // a similar friend function. + else for (FunctionDecl::redecl_iterator R = Function->redecls_begin(), + REnd = Function->redecls_end(); + R != REnd; ++R) { + if (*R == Function) + continue; + switch (R->getFriendObjectKind()) { + case Decl::FOK_None: + if (!queuedInstantiation && R->isUsed(false)) { + if (MemberSpecializationInfo *MSInfo + = Function->getMemberSpecializationInfo()) { + if (MSInfo->getPointOfInstantiation().isInvalid()) { + SourceLocation Loc = R->getLocation(); // FIXME + MSInfo->setPointOfInstantiation(Loc); + SemaRef.PendingLocalImplicitInstantiations.push_back( + std::make_pair(Function, Loc)); + queuedInstantiation = true; + } + } + } + break; + default: + if (const FunctionDecl *RPattern + = R->getTemplateInstantiationPattern()) + if (RPattern->isDefined(RPattern)) { + SemaRef.Diag(Function->getLocation(), diag::err_redefinition) + << Function->getDeclName(); + SemaRef.Diag(R->getLocation(), diag::note_previous_definition); + Function->setInvalidDecl(); + break; + } + } + } + } + } + + if (Function->isOverloadedOperator() && !DC->isRecord() && + PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) + PrincipalDecl->setNonMemberOperator(); + + assert(!D->isDefaulted() && "only methods should be defaulted"); + return Function; +} + +Decl * +TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, + TemplateParameterList *TemplateParams) { + FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); + void *InsertPos = 0; + if (FunctionTemplate && !TemplateParams) { + // We are creating a function template specialization from a function + // template. Check whether there is already a function template + // specialization for this particular set of template arguments. + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); + + FunctionDecl *SpecFunc + = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, + InsertPos); + + // If we already have a function template specialization, return it. + if (SpecFunc) + return SpecFunc; + } + + bool isFriend; + if (FunctionTemplate) + isFriend = (FunctionTemplate->getFriendObjectKind() != Decl::FOK_None); + else + isFriend = (D->getFriendObjectKind() != Decl::FOK_None); + + bool MergeWithParentScope = (TemplateParams != 0) || + !(isa<Decl>(Owner) && + cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); + LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); + + // Instantiate enclosing template arguments for friends. + llvm::SmallVector<TemplateParameterList *, 4> TempParamLists; + unsigned NumTempParamLists = 0; + if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) { + TempParamLists.set_size(NumTempParamLists); + for (unsigned I = 0; I != NumTempParamLists; ++I) { + TemplateParameterList *TempParams = D->getTemplateParameterList(I); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + TempParamLists[I] = InstParams; + } + } + + llvm::SmallVector<ParmVarDecl *, 4> Params; + TypeSourceInfo *TInfo = D->getTypeSourceInfo(); + TInfo = SubstFunctionType(D, Params); + if (!TInfo) + return 0; + QualType T = TInfo->getType(); + + // \brief If the type of this function, after ignoring parentheses, + // is not *directly* a function type, then we're instantiating a function + // that was declared via a typedef, e.g., + // + // typedef int functype(int, int); + // functype func; + // + // In this case, we'll just go instantiate the ParmVarDecls that we + // synthesized in the method declaration. + if (!isa<FunctionProtoType>(T.IgnoreParens())) { + assert(!Params.size() && "Instantiating type could not yield parameters"); + llvm::SmallVector<QualType, 4> ParamTypes; + if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(), + D->getNumParams(), TemplateArgs, ParamTypes, + &Params)) + return 0; + } + + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, + TemplateArgs); + if (!QualifierLoc) + return 0; + } + + DeclContext *DC = Owner; + if (isFriend) { + if (QualifierLoc) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + DC = SemaRef.computeDeclContext(SS); + + if (DC && SemaRef.RequireCompleteDeclContext(SS, DC)) + return 0; + } else { + DC = SemaRef.FindInstantiatedContext(D->getLocation(), + D->getDeclContext(), + TemplateArgs); + } + if (!DC) return 0; + } + + // Build the instantiated method declaration. + CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); + CXXMethodDecl *Method = 0; + + SourceLocation StartLoc = D->getInnerLocStart(); + DeclarationNameInfo NameInfo + = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { + Method = CXXConstructorDecl::Create(SemaRef.Context, Record, + StartLoc, NameInfo, T, TInfo, + Constructor->isExplicit(), + Constructor->isInlineSpecified(), + false); + } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { + Method = CXXDestructorDecl::Create(SemaRef.Context, Record, + StartLoc, NameInfo, T, TInfo, + Destructor->isInlineSpecified(), + false); + } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { + Method = CXXConversionDecl::Create(SemaRef.Context, Record, + StartLoc, NameInfo, T, TInfo, + Conversion->isInlineSpecified(), + Conversion->isExplicit(), + Conversion->getLocEnd()); + } else { + Method = CXXMethodDecl::Create(SemaRef.Context, Record, + StartLoc, NameInfo, T, TInfo, + D->isStatic(), + D->getStorageClassAsWritten(), + D->isInlineSpecified(), + D->getLocEnd()); + } + + if (QualifierLoc) + Method->setQualifierInfo(QualifierLoc); + + if (TemplateParams) { + // Our resulting instantiation is actually a function template, since we + // are substituting only the outer template parameters. For example, given + // + // template<typename T> + // struct X { + // template<typename U> void f(T, U); + // }; + // + // X<int> x; + // + // We are instantiating the member template "f" within X<int>, which means + // substituting int for T, but leaving "f" as a member function template. + // Build the function template itself. + FunctionTemplate = FunctionTemplateDecl::Create(SemaRef.Context, Record, + Method->getLocation(), + Method->getDeclName(), + TemplateParams, Method); + if (isFriend) { + FunctionTemplate->setLexicalDeclContext(Owner); + FunctionTemplate->setObjectOfFriendDecl(true); + } else if (D->isOutOfLine()) + FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); + Method->setDescribedFunctionTemplate(FunctionTemplate); + } else if (FunctionTemplate) { + // Record this function template specialization. + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); + Method->setFunctionTemplateSpecialization(FunctionTemplate, + TemplateArgumentList::CreateCopy(SemaRef.Context, + Innermost.first, + Innermost.second), + InsertPos); + } else if (!isFriend) { + // Record that this is an instantiation of a member function. + Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); + } + + // If we are instantiating a member function defined + // out-of-line, the instantiation will have the same lexical + // context (which will be a namespace scope) as the template. + if (isFriend) { + if (NumTempParamLists) + Method->setTemplateParameterListsInfo(SemaRef.Context, + NumTempParamLists, + TempParamLists.data()); + + Method->setLexicalDeclContext(Owner); + Method->setObjectOfFriendDecl(true); + } else if (D->isOutOfLine()) + Method->setLexicalDeclContext(D->getLexicalDeclContext()); + + // Attach the parameters + for (unsigned P = 0; P < Params.size(); ++P) + Params[P]->setOwningFunction(Method); + Method->setParams(Params.data(), Params.size()); + + if (InitMethodInstantiation(Method, D)) + Method->setInvalidDecl(); + + LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName, + Sema::ForRedeclaration); + + if (!FunctionTemplate || TemplateParams || isFriend) { + SemaRef.LookupQualifiedName(Previous, Record); + + // In C++, the previous declaration we find might be a tag type + // (class or enum). In this case, the new declaration will hide the + // tag type. Note that this does does not apply if we're declaring a + // typedef (C++ [dcl.typedef]p4). + if (Previous.isSingleTagDecl()) + Previous.clear(); + } + + bool Redeclaration = false; + SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration); + + if (D->isPure()) + SemaRef.CheckPureMethod(Method, SourceRange()); + + Method->setAccess(D->getAccess()); + + SemaRef.CheckOverrideControl(Method); + + if (FunctionTemplate) { + // If there's a function template, let our caller handle it. + } else if (Method->isInvalidDecl() && !Previous.empty()) { + // Don't hide a (potentially) valid declaration with an invalid one. + } else { + NamedDecl *DeclToAdd = (TemplateParams + ? cast<NamedDecl>(FunctionTemplate) + : Method); + if (isFriend) + Record->makeDeclVisibleInContext(DeclToAdd); + else + Owner->addDecl(DeclToAdd); + } + + if (D->isExplicitlyDefaulted()) { + SemaRef.SetDeclDefaulted(Method, Method->getLocation()); + } else { + assert(!D->isDefaulted() && + "should not implicitly default uninstantiated function"); + } + + return Method; +} + +Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) { + return VisitCXXMethodDecl(D); +} + +Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) { + return VisitCXXMethodDecl(D); +} + +Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { + return VisitCXXMethodDecl(D); +} + +ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { + return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, + llvm::Optional<unsigned>()); +} + +Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( + TemplateTypeParmDecl *D) { + // TODO: don't always clone when decls are refcounted. + assert(D->getTypeForDecl()->isTemplateTypeParmType()); + + TemplateTypeParmDecl *Inst = + TemplateTypeParmDecl::Create(SemaRef.Context, Owner, + D->getLocStart(), D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getIndex(), D->getIdentifier(), + D->wasDeclaredWithTypename(), + D->isParameterPack()); + Inst->setAccess(AS_public); + + if (D->hasDefaultArgument()) + Inst->setDefaultArgument(D->getDefaultArgumentInfo(), false); + + // Introduce this template parameter's instantiation into the instantiation + // scope. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst); + + return Inst; +} + +Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( + NonTypeTemplateParmDecl *D) { + // Substitute into the type of the non-type template parameter. + TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc(); + llvm::SmallVector<TypeSourceInfo *, 4> ExpandedParameterPackTypesAsWritten; + llvm::SmallVector<QualType, 4> ExpandedParameterPackTypes; + bool IsExpandedParameterPack = false; + TypeSourceInfo *DI; + QualType T; + bool Invalid = false; + + if (D->isExpandedParameterPack()) { + // The non-type template parameter pack is an already-expanded pack + // expansion of types. Substitute into each of the expanded types. + ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes()); + ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes()); + for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { + TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I), + TemplateArgs, + D->getLocation(), + D->getDeclName()); + if (!NewDI) + return 0; + + ExpandedParameterPackTypesAsWritten.push_back(NewDI); + QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(), + D->getLocation()); + if (NewT.isNull()) + return 0; + ExpandedParameterPackTypes.push_back(NewT); + } + + IsExpandedParameterPack = true; + DI = D->getTypeSourceInfo(); + T = DI->getType(); + } else if (isa<PackExpansionTypeLoc>(TL)) { + // The non-type template parameter pack's type is a pack expansion of types. + // Determine whether we need to expand this parameter pack into separate + // types. + PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(TL); + TypeLoc Pattern = Expansion.getPatternLoc(); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional<unsigned> OrigNumExpansions + = Expansion.getTypePtr()->getNumExpansions(); + llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(), + Pattern.getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + TemplateArgs, + Expand, RetainExpansion, + NumExpansions)) + return 0; + + if (Expand) { + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); + TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs, + D->getLocation(), + D->getDeclName()); + if (!NewDI) + return 0; + + ExpandedParameterPackTypesAsWritten.push_back(NewDI); + QualType NewT = SemaRef.CheckNonTypeTemplateParameterType( + NewDI->getType(), + D->getLocation()); + if (NewT.isNull()) + return 0; + ExpandedParameterPackTypes.push_back(NewT); + } + + // Note that we have an expanded parameter pack. The "type" of this + // expanded parameter pack is the original expansion type, but callers + // will end up using the expanded parameter pack types for type-checking. + IsExpandedParameterPack = true; + DI = D->getTypeSourceInfo(); + T = DI->getType(); + } else { + // We cannot fully expand the pack expansion now, so substitute into the + // pattern and create a new pack expansion type. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); + TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs, + D->getLocation(), + D->getDeclName()); + if (!NewPattern) + return 0; + + DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(), + NumExpansions); + if (!DI) + return 0; + + T = DI->getType(); + } + } else { + // Simple case: substitution into a parameter that is not a parameter pack. + DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, + D->getLocation(), D->getDeclName()); + if (!DI) + return 0; + + // Check that this type is acceptable for a non-type template parameter. + T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(), + D->getLocation()); + if (T.isNull()) { + T = SemaRef.Context.IntTy; + Invalid = true; + } + } + + NonTypeTemplateParmDecl *Param; + if (IsExpandedParameterPack) + Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getInnerLocStart(), + D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getPosition(), + D->getIdentifier(), T, + DI, + ExpandedParameterPackTypes.data(), + ExpandedParameterPackTypes.size(), + ExpandedParameterPackTypesAsWritten.data()); + else + Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getInnerLocStart(), + D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getPosition(), + D->getIdentifier(), T, + D->isParameterPack(), DI); + + Param->setAccess(AS_public); + if (Invalid) + Param->setInvalidDecl(); + + Param->setDefaultArgument(D->getDefaultArgument(), false); + + // Introduce this template parameter's instantiation into the instantiation + // scope. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); + return Param; +} + +Decl * +TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( + TemplateTemplateParmDecl *D) { + // Instantiate the template parameter list of the template template parameter. + TemplateParameterList *TempParams = D->getTemplateParameters(); + TemplateParameterList *InstParams; + { + // Perform the actual substitution of template parameters within a new, + // local instantiation scope. + LocalInstantiationScope Scope(SemaRef); + InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + } + + // Build the template template parameter. + TemplateTemplateParmDecl *Param + = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getPosition(), D->isParameterPack(), + D->getIdentifier(), InstParams); + Param->setDefaultArgument(D->getDefaultArgument(), false); + Param->setAccess(AS_public); + + // Introduce this template parameter's instantiation into the instantiation + // scope. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); + + return Param; +} + +Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { + // Using directives are never dependent (and never contain any types or + // expressions), so they require no explicit instantiation work. + + UsingDirectiveDecl *Inst + = UsingDirectiveDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getNamespaceKeyLocation(), + D->getQualifierLoc(), + D->getIdentLocation(), + D->getNominatedNamespace(), + D->getCommonAncestor()); + Owner->addDecl(Inst); + return Inst; +} + +Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { + + // The nested name specifier may be dependent, for example + // template <typename T> struct t { + // struct s1 { T f1(); }; + // struct s2 : s1 { using s1::f1; }; + // }; + // template struct t<int>; + // Here, in using s1::f1, s1 refers to t<T>::s1; + // we need to substitute for t<int>::s1. + NestedNameSpecifierLoc QualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), + TemplateArgs); + if (!QualifierLoc) + return 0; + + // The name info is non-dependent, so no transformation + // is required. + DeclarationNameInfo NameInfo = D->getNameInfo(); + + // We only need to do redeclaration lookups if we're in a class + // scope (in fact, it's not really even possible in non-class + // scopes). + bool CheckRedeclaration = Owner->isRecord(); + + LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName, + Sema::ForRedeclaration); + + UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, + D->getUsingLocation(), + QualifierLoc, + NameInfo, + D->isTypeName()); + + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + if (CheckRedeclaration) { + Prev.setHideTags(false); + SemaRef.LookupQualifiedName(Prev, Owner); + + // Check for invalid redeclarations. + if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(), + D->isTypeName(), SS, + D->getLocation(), Prev)) + NewUD->setInvalidDecl(); + + } + + if (!NewUD->isInvalidDecl() && + SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS, + D->getLocation())) + NewUD->setInvalidDecl(); + + SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D); + NewUD->setAccess(D->getAccess()); + Owner->addDecl(NewUD); + + // Don't process the shadow decls for an invalid decl. + if (NewUD->isInvalidDecl()) + return NewUD; + + bool isFunctionScope = Owner->isFunctionOrMethod(); + + // Process the shadow decls. + for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end(); + I != E; ++I) { + UsingShadowDecl *Shadow = *I; + NamedDecl *InstTarget = + cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), + Shadow->getTargetDecl(), + TemplateArgs)); + if (!InstTarget) + return 0; + + if (CheckRedeclaration && + SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev)) + continue; + + UsingShadowDecl *InstShadow + = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget); + SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); + + if (isFunctionScope) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(Shadow, InstShadow); + } + + return NewUD; +} + +Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) { + // Ignore these; we handle them in bulk when processing the UsingDecl. + return 0; +} + +Decl * TemplateDeclInstantiator + ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { + NestedNameSpecifierLoc QualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), + TemplateArgs); + if (!QualifierLoc) + return 0; + + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + // Since NameInfo refers to a typename, it cannot be a C++ special name. + // Hence, no tranformation is required for it. + DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation()); + NamedDecl *UD = + SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), + D->getUsingLoc(), SS, NameInfo, 0, + /*instantiation*/ true, + /*typename*/ true, D->getTypenameLoc()); + if (UD) + SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D); + + return UD; +} + +Decl * TemplateDeclInstantiator + ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { + NestedNameSpecifierLoc QualifierLoc + = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs); + if (!QualifierLoc) + return 0; + + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + DeclarationNameInfo NameInfo + = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); + + NamedDecl *UD = + SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), + D->getUsingLoc(), SS, NameInfo, 0, + /*instantiation*/ true, + /*typename*/ false, SourceLocation()); + if (UD) + SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D); + + return UD; +} + +Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, + const MultiLevelTemplateArgumentList &TemplateArgs) { + TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); + if (D->isInvalidDecl()) + return 0; + + return Instantiator.Visit(D); +} + +/// \brief Instantiates a nested template parameter list in the current +/// instantiation context. +/// +/// \param L The parameter list to instantiate +/// +/// \returns NULL if there was an error +TemplateParameterList * +TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { + // Get errors for all the parameters before bailing out. + bool Invalid = false; + + unsigned N = L->size(); + typedef llvm::SmallVector<NamedDecl *, 8> ParamVector; + ParamVector Params; + Params.reserve(N); + for (TemplateParameterList::iterator PI = L->begin(), PE = L->end(); + PI != PE; ++PI) { + NamedDecl *D = cast_or_null<NamedDecl>(Visit(*PI)); + Params.push_back(D); + Invalid = Invalid || !D || D->isInvalidDecl(); + } + + // Clean up if we had an error. + if (Invalid) + return NULL; + + TemplateParameterList *InstL + = TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(), + L->getLAngleLoc(), &Params.front(), N, + L->getRAngleLoc()); + return InstL; +} + +/// \brief Instantiate the declaration of a class template partial +/// specialization. +/// +/// \param ClassTemplate the (instantiated) class template that is partially +// specialized by the instantiation of \p PartialSpec. +/// +/// \param PartialSpec the (uninstantiated) class template partial +/// specialization that we are instantiating. +/// +/// \returns The instantiated partial specialization, if successful; otherwise, +/// NULL to indicate an error. +ClassTemplatePartialSpecializationDecl * +TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( + ClassTemplateDecl *ClassTemplate, + ClassTemplatePartialSpecializationDecl *PartialSpec) { + // Create a local instantiation scope for this class template partial + // specialization, which will contain the instantiations of the template + // parameters. + LocalInstantiationScope Scope(SemaRef); + + // Substitute into the template parameters of the class template partial + // specialization. + TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return 0; + + // Substitute into the template arguments of the class template partial + // specialization. + TemplateArgumentListInfo InstTemplateArgs; // no angle locations + if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(), + PartialSpec->getNumTemplateArgsAsWritten(), + InstTemplateArgs, TemplateArgs)) + return 0; + + // Check that the template argument list is well-formed for this + // class template. + llvm::SmallVector<TemplateArgument, 4> Converted; + if (SemaRef.CheckTemplateArgumentList(ClassTemplate, + PartialSpec->getLocation(), + InstTemplateArgs, + false, + Converted)) + return 0; + + // Figure out where to insert this class template partial specialization + // in the member template's set of class template partial specializations. + void *InsertPos = 0; + ClassTemplateSpecializationDecl *PrevDecl + = ClassTemplate->findPartialSpecialization(Converted.data(), + Converted.size(), InsertPos); + + // Build the canonical type that describes the converted template + // arguments of the class template partial specialization. + QualType CanonType + = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), + Converted.data(), + Converted.size()); + + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + TypeSourceInfo *WrittenTy + = SemaRef.Context.getTemplateSpecializationTypeInfo( + TemplateName(ClassTemplate), + PartialSpec->getLocation(), + InstTemplateArgs, + CanonType); + + if (PrevDecl) { + // We've already seen a partial specialization with the same template + // parameters and template arguments. This can happen, for example, when + // substituting the outer template arguments ends up causing two + // class template partial specializations of a member class template + // to have identical forms, e.g., + // + // template<typename T, typename U> + // struct Outer { + // template<typename X, typename Y> struct Inner; + // template<typename Y> struct Inner<T, Y>; + // template<typename Y> struct Inner<U, Y>; + // }; + // + // Outer<int, int> outer; // error: the partial specializations of Inner + // // have the same signature. + SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) + << WrittenTy->getType(); + SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) + << SemaRef.Context.getTypeDeclType(PrevDecl); + return 0; + } + + + // Create the class template partial specialization declaration. + ClassTemplatePartialSpecializationDecl *InstPartialSpec + = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, + PartialSpec->getTagKind(), + Owner, + PartialSpec->getLocStart(), + PartialSpec->getLocation(), + InstParams, + ClassTemplate, + Converted.data(), + Converted.size(), + InstTemplateArgs, + CanonType, + 0, + ClassTemplate->getNextPartialSpecSequenceNumber()); + // Substitute the nested name specifier, if any. + if (SubstQualifier(PartialSpec, InstPartialSpec)) + return 0; + + InstPartialSpec->setInstantiatedFromMember(PartialSpec); + InstPartialSpec->setTypeAsWritten(WrittenTy); + + // Add this partial specialization to the set of class template partial + // specializations. + ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos); + return InstPartialSpec; +} + +TypeSourceInfo* +TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, + llvm::SmallVectorImpl<ParmVarDecl *> &Params) { + TypeSourceInfo *OldTInfo = D->getTypeSourceInfo(); + assert(OldTInfo && "substituting function without type source info"); + assert(Params.empty() && "parameter vector is non-empty at start"); + TypeSourceInfo *NewTInfo + = SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs, + D->getTypeSpecStartLoc(), + D->getDeclName()); + if (!NewTInfo) + return 0; + + if (NewTInfo != OldTInfo) { + // Get parameters from the new type info. + TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); + if (FunctionProtoTypeLoc *OldProtoLoc + = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) { + TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens(); + FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL); + assert(NewProtoLoc && "Missing prototype?"); + unsigned NewIdx = 0, NumNewParams = NewProtoLoc->getNumArgs(); + for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs(); + OldIdx != NumOldParams; ++OldIdx) { + ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx); + if (!OldParam->isParameterPack() || + (NewIdx < NumNewParams && + NewProtoLoc->getArg(NewIdx)->isParameterPack())) { + // Simple case: normal parameter, or a parameter pack that's + // instantiated to a (still-dependent) parameter pack. + ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); + Params.push_back(NewParam); + SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, + NewParam); + continue; + } + + // Parameter pack: make the instantiation an argument pack. + SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack( + OldParam); + unsigned NumArgumentsInExpansion + = SemaRef.getNumArgumentsInExpansion(OldParam->getType(), + TemplateArgs); + while (NumArgumentsInExpansion--) { + ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); + Params.push_back(NewParam); + SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam, + NewParam); + } + } + } + } else { + // The function type itself was not dependent and therefore no + // substitution occurred. However, we still need to instantiate + // the function parameters themselves. + TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); + if (FunctionProtoTypeLoc *OldProtoLoc + = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) { + for (unsigned i = 0, i_end = OldProtoLoc->getNumArgs(); i != i_end; ++i) { + ParmVarDecl *Parm = VisitParmVarDecl(OldProtoLoc->getArg(i)); + if (!Parm) + return 0; + Params.push_back(Parm); + } + } + } + return NewTInfo; +} + +/// \brief Initializes the common fields of an instantiation function +/// declaration (New) from the corresponding fields of its template (Tmpl). +/// +/// \returns true if there was an error +bool +TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, + FunctionDecl *Tmpl) { + if (Tmpl->isDeletedAsWritten()) + New->setDeletedAsWritten(); + + // If we are performing substituting explicitly-specified template arguments + // or deduced template arguments into a function template and we reach this + // point, we are now past the point where SFINAE applies and have committed + // to keeping the new function template specialization. We therefore + // convert the active template instantiation for the function template + // into a template instantiation for this specific function template + // specialization, which is not a SFINAE context, so that we diagnose any + // further errors in the declaration itself. + typedef Sema::ActiveTemplateInstantiation ActiveInstType; + ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back(); + if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || + ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) { + assert(FunTmpl->getTemplatedDecl() == Tmpl && + "Deduction from the wrong function template?"); + (void) FunTmpl; + ActiveInst.Kind = ActiveInstType::TemplateInstantiation; + ActiveInst.Entity = reinterpret_cast<uintptr_t>(New); + --SemaRef.NonInstantiationEntries; + } + } + + const FunctionProtoType *Proto = Tmpl->getType()->getAs<FunctionProtoType>(); + assert(Proto && "Function template without prototype?"); + + if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) { + // The function has an exception specification or a "noreturn" + // attribute. Substitute into each of the exception types. + llvm::SmallVector<QualType, 4> Exceptions; + for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) { + // FIXME: Poor location information! + if (const PackExpansionType *PackExpansion + = Proto->getExceptionType(I)->getAs<PackExpansionType>()) { + // We have a pack expansion. Instantiate it. + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(), + Unexpanded); + assert(!Unexpanded.empty() && + "Pack expansion without parameter packs?"); + + bool Expand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions + = PackExpansion->getNumExpansions(); + if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), + SourceRange(), + Unexpanded.data(), + Unexpanded.size(), + TemplateArgs, + Expand, + RetainExpansion, + NumExpansions)) + break; + + if (!Expand) { + // We can't expand this pack expansion into separate arguments yet; + // just substitute into the pattern and create a new pack expansion + // type. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); + QualType T = SemaRef.SubstType(PackExpansion->getPattern(), + TemplateArgs, + New->getLocation(), New->getDeclName()); + if (T.isNull()) + break; + + T = SemaRef.Context.getPackExpansionType(T, NumExpansions); + Exceptions.push_back(T); + continue; + } + + // Substitute into the pack expansion pattern for each template + bool Invalid = false; + for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx); + + QualType T = SemaRef.SubstType(PackExpansion->getPattern(), + TemplateArgs, + New->getLocation(), New->getDeclName()); + if (T.isNull()) { + Invalid = true; + break; + } + + Exceptions.push_back(T); + } + + if (Invalid) + break; + + continue; + } + + QualType T + = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs, + New->getLocation(), New->getDeclName()); + if (T.isNull() || + SemaRef.CheckSpecifiedExceptionType(T, New->getLocation())) + continue; + + Exceptions.push_back(T); + } + Expr *NoexceptExpr = 0; + if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs); + if (E.isUsable()) + NoexceptExpr = E.take(); + } + + // Rebuild the function type + + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.ExceptionSpecType = Proto->getExceptionSpecType(); + EPI.NumExceptions = Exceptions.size(); + EPI.Exceptions = Exceptions.data(); + EPI.NoexceptExpr = NoexceptExpr; + EPI.ExtInfo = Proto->getExtInfo(); + + const FunctionProtoType *NewProto + = New->getType()->getAs<FunctionProtoType>(); + assert(NewProto && "Template instantiation without function prototype?"); + New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), + NewProto->arg_type_begin(), + NewProto->getNumArgs(), + EPI)); + } + + SemaRef.InstantiateAttrs(TemplateArgs, Tmpl, New); + + return false; +} + +/// \brief Initializes common fields of an instantiated method +/// declaration (New) from the corresponding fields of its template +/// (Tmpl). +/// +/// \returns true if there was an error +bool +TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, + CXXMethodDecl *Tmpl) { + if (InitFunctionInstantiation(New, Tmpl)) + return true; + + New->setAccess(Tmpl->getAccess()); + if (Tmpl->isVirtualAsWritten()) + New->setVirtualAsWritten(true); + + // FIXME: attributes + // FIXME: New needs a pointer to Tmpl + return false; +} + +/// \brief Instantiate the definition of the given function from its +/// template. +/// +/// \param PointOfInstantiation the point at which the instantiation was +/// required. Note that this is not precisely a "point of instantiation" +/// for the function, but it's close. +/// +/// \param Function the already-instantiated declaration of a +/// function template specialization or member function of a class template +/// specialization. +/// +/// \param Recursive if true, recursively instantiates any functions that +/// are required by this instantiation. +/// +/// \param DefinitionRequired if true, then we are performing an explicit +/// instantiation where the body of the function is required. Complain if +/// there is no such body. +void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, + FunctionDecl *Function, + bool Recursive, + bool DefinitionRequired) { + if (Function->isInvalidDecl() || Function->isDefined()) + return; + + // Never instantiate an explicit specialization. + if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return; + + // Find the function body that we'll be substituting. + const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); + assert(PatternDecl && "instantiating a non-template"); + + Stmt *Pattern = PatternDecl->getBody(PatternDecl); + assert(PatternDecl && "template definition is not a template"); + if (!Pattern) { + // Try to find a defaulted definition + PatternDecl->isDefined(PatternDecl); + } + assert(PatternDecl && "template definition is not a template"); + + // Postpone late parsed template instantiations. + if (PatternDecl->isLateTemplateParsed() && + !LateTemplateParser) { + PendingInstantiations.push_back( + std::make_pair(Function, PointOfInstantiation)); + return; + } + + // Call the LateTemplateParser callback if there a need to late parse + // a templated function definition. + if (!Pattern && PatternDecl->isLateTemplateParsed() && + LateTemplateParser) { + LateTemplateParser(OpaqueParser, PatternDecl); + Pattern = PatternDecl->getBody(PatternDecl); + } + + if (!Pattern && !PatternDecl->isDefaulted()) { + if (DefinitionRequired) { + if (Function->getPrimaryTemplate()) + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_func_template) + << Function->getPrimaryTemplate(); + else + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_member) + << 1 << Function->getDeclName() << Function->getDeclContext(); + + if (PatternDecl) + Diag(PatternDecl->getLocation(), + diag::note_explicit_instantiation_here); + Function->setInvalidDecl(); + } else if (Function->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDefinition) { + PendingInstantiations.push_back( + std::make_pair(Function, PointOfInstantiation)); + } + + return; + } + + // C++0x [temp.explicit]p9: + // Except for inline functions, other explicit instantiation declarations + // have the effect of suppressing the implicit instantiation of the entity + // to which they refer. + if (Function->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDeclaration && + !PatternDecl->isInlined()) + return; + + InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); + if (Inst) + return; + + // If we're performing recursive template instantiation, create our own + // queue of pending implicit instantiations that we will instantiate later, + // while we're still within our own instantiation context. + llvm::SmallVector<VTableUse, 16> SavedVTableUses; + std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; + if (Recursive) { + VTableUses.swap(SavedVTableUses); + PendingInstantiations.swap(SavedPendingInstantiations); + } + + EnterExpressionEvaluationContext EvalContext(*this, + Sema::PotentiallyEvaluated); + ActOnStartOfFunctionDef(0, Function); + + // Introduce a new scope where local variable instantiations will be + // recorded, unless we're actually a member function within a local + // class, in which case we need to merge our results with the parent + // scope (of the enclosing function). + bool MergeWithParentScope = false; + if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Function->getDeclContext())) + MergeWithParentScope = Rec->isLocalClass(); + + LocalInstantiationScope Scope(*this, MergeWithParentScope); + + // Introduce the instantiated function parameters into the local + // instantiation scope, and set the parameter names to those used + // in the template. + unsigned FParamIdx = 0; + for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { + const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); + if (!PatternParam->isParameterPack()) { + // Simple case: not a parameter pack. + assert(FParamIdx < Function->getNumParams()); + ParmVarDecl *FunctionParam = Function->getParamDecl(I); + FunctionParam->setDeclName(PatternParam->getDeclName()); + Scope.InstantiatedLocal(PatternParam, FunctionParam); + ++FParamIdx; + continue; + } + + // Expand the parameter pack. + Scope.MakeInstantiatedLocalArgPack(PatternParam); + for (unsigned NumFParams = Function->getNumParams(); + FParamIdx < NumFParams; + ++FParamIdx) { + ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); + FunctionParam->setDeclName(PatternParam->getDeclName()); + Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); + } + } + + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + Sema::ContextRAII savedContext(*this, Function); + + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(Function, 0, false, PatternDecl); + + if (PatternDecl->isDefaulted()) { + ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true); + + SetDeclDefaulted(Function, PatternDecl->getLocation()); + } else { + // If this is a constructor, instantiate the member initializers. + if (const CXXConstructorDecl *Ctor = + dyn_cast<CXXConstructorDecl>(PatternDecl)) { + InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor, + TemplateArgs); + } + + // Instantiate the function body. + StmtResult Body = SubstStmt(Pattern, TemplateArgs); + + if (Body.isInvalid()) + Function->setInvalidDecl(); + + ActOnFinishFunctionBody(Function, Body.get(), + /*IsInstantiation=*/true); + } + + PerformDependentDiagnostics(PatternDecl, TemplateArgs); + + savedContext.pop(); + + DeclGroupRef DG(Function); + Consumer.HandleTopLevelDecl(DG); + + // This class may have local implicit instantiations that need to be + // instantiation within this scope. + PerformPendingInstantiations(/*LocalOnly=*/true); + Scope.Exit(); + + if (Recursive) { + // Define any pending vtables. + DefineUsedVTables(); + + // Instantiate any pending implicit instantiations found during the + // instantiation of this template. + PerformPendingInstantiations(); + + // Restore the set of pending vtables. + assert(VTableUses.empty() && + "VTableUses should be empty before it is discarded."); + VTableUses.swap(SavedVTableUses); + + // Restore the set of pending implicit instantiations. + assert(PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded."); + PendingInstantiations.swap(SavedPendingInstantiations); + } +} + +/// \brief Instantiate the definition of the given variable from its +/// template. +/// +/// \param PointOfInstantiation the point at which the instantiation was +/// required. Note that this is not precisely a "point of instantiation" +/// for the function, but it's close. +/// +/// \param Var the already-instantiated declaration of a static member +/// variable of a class template specialization. +/// +/// \param Recursive if true, recursively instantiates any functions that +/// are required by this instantiation. +/// +/// \param DefinitionRequired if true, then we are performing an explicit +/// instantiation where an out-of-line definition of the member variable +/// is required. Complain if there is no such definition. +void Sema::InstantiateStaticDataMemberDefinition( + SourceLocation PointOfInstantiation, + VarDecl *Var, + bool Recursive, + bool DefinitionRequired) { + if (Var->isInvalidDecl()) + return; + + // Find the out-of-line definition of this static data member. + VarDecl *Def = Var->getInstantiatedFromStaticDataMember(); + assert(Def && "This data member was not instantiated from a template?"); + assert(Def->isStaticDataMember() && "Not a static data member?"); + Def = Def->getOutOfLineDefinition(); + + if (!Def) { + // We did not find an out-of-line definition of this static data member, + // so we won't perform any instantiation. Rather, we rely on the user to + // instantiate this definition (or provide a specialization for it) in + // another translation unit. + if (DefinitionRequired) { + Def = Var->getInstantiatedFromStaticDataMember(); + Diag(PointOfInstantiation, + diag::err_explicit_instantiation_undefined_member) + << 2 << Var->getDeclName() << Var->getDeclContext(); + Diag(Def->getLocation(), diag::note_explicit_instantiation_here); + } else if (Var->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDefinition) { + PendingInstantiations.push_back( + std::make_pair(Var, PointOfInstantiation)); + } + + return; + } + + // Never instantiate an explicit specialization. + if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return; + + // C++0x [temp.explicit]p9: + // Except for inline functions, other explicit instantiation declarations + // have the effect of suppressing the implicit instantiation of the entity + // to which they refer. + if (Var->getTemplateSpecializationKind() + == TSK_ExplicitInstantiationDeclaration) + return; + + // If we already have a definition, we're done. + if (Var->getDefinition()) + return; + + InstantiatingTemplate Inst(*this, PointOfInstantiation, Var); + if (Inst) + return; + + // If we're performing recursive template instantiation, create our own + // queue of pending implicit instantiations that we will instantiate later, + // while we're still within our own instantiation context. + llvm::SmallVector<VTableUse, 16> SavedVTableUses; + std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; + if (Recursive) { + VTableUses.swap(SavedVTableUses); + PendingInstantiations.swap(SavedPendingInstantiations); + } + + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + ContextRAII previousContext(*this, Var->getDeclContext()); + + VarDecl *OldVar = Var; + Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), + getTemplateInstantiationArgs(Var))); + + previousContext.pop(); + + if (Var) { + MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation()); + DeclGroupRef DG(Var); + Consumer.HandleTopLevelDecl(DG); + } + + if (Recursive) { + // Define any newly required vtables. + DefineUsedVTables(); + + // Instantiate any pending implicit instantiations found during the + // instantiation of this template. + PerformPendingInstantiations(); + + // Restore the set of pending vtables. + assert(VTableUses.empty() && + "VTableUses should be empty before it is discarded, " + "while instantiating static data member."); + VTableUses.swap(SavedVTableUses); + + // Restore the set of pending implicit instantiations. + assert(PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded, " + "while instantiating static data member."); + PendingInstantiations.swap(SavedPendingInstantiations); + } +} + +void +Sema::InstantiateMemInitializers(CXXConstructorDecl *New, + const CXXConstructorDecl *Tmpl, + const MultiLevelTemplateArgumentList &TemplateArgs) { + + llvm::SmallVector<MemInitTy*, 4> NewInits; + bool AnyErrors = false; + + // Instantiate all the initializers. + for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(), + InitsEnd = Tmpl->init_end(); + Inits != InitsEnd; ++Inits) { + CXXCtorInitializer *Init = *Inits; + + // Only instantiate written initializers, let Sema re-construct implicit + // ones. + if (!Init->isWritten()) + continue; + + SourceLocation LParenLoc, RParenLoc; + ASTOwningVector<Expr*> NewArgs(*this); + + SourceLocation EllipsisLoc; + + if (Init->isPackExpansion()) { + // This is a pack expansion. We should expand it now. + TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc(); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + collectUnexpandedParameterPacks(BaseTL, Unexpanded); + bool ShouldExpand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions; + if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), + BaseTL.getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + TemplateArgs, ShouldExpand, + RetainExpansion, + NumExpansions)) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + assert(ShouldExpand && "Partial instantiation of base initializer?"); + + // Loop over all of the arguments in the argument pack(s), + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); + + // Instantiate the initializer. + if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, + LParenLoc, NewArgs, RParenLoc)) { + AnyErrors = true; + break; + } + + // Instantiate the base type. + TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), + TemplateArgs, + Init->getSourceLocation(), + New->getDeclName()); + if (!BaseTInfo) { + AnyErrors = true; + break; + } + + // Build the initializer. + MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), + BaseTInfo, + (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getLParenLoc(), + Init->getRParenLoc(), + New->getParent(), + SourceLocation()); + if (NewInit.isInvalid()) { + AnyErrors = true; + break; + } + + NewInits.push_back(NewInit.get()); + NewArgs.clear(); + } + + continue; + } + + // Instantiate the initializer. + if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, + LParenLoc, NewArgs, RParenLoc)) { + AnyErrors = true; + continue; + } + + MemInitResult NewInit; + if (Init->isBaseInitializer()) { + TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), + TemplateArgs, + Init->getSourceLocation(), + New->getDeclName()); + if (!BaseTInfo) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + + NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, + (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getLParenLoc(), + Init->getRParenLoc(), + New->getParent(), + EllipsisLoc); + } else if (Init->isMemberInitializer()) { + FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl( + Init->getMemberLocation(), + Init->getMember(), + TemplateArgs)); + if (!Member) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + + NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getSourceLocation(), + Init->getLParenLoc(), + Init->getRParenLoc()); + } else if (Init->isIndirectMemberInitializer()) { + IndirectFieldDecl *IndirectMember = + cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl( + Init->getMemberLocation(), + Init->getIndirectMember(), TemplateArgs)); + + if (!IndirectMember) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + + NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getSourceLocation(), + Init->getLParenLoc(), + Init->getRParenLoc()); + } + + if (NewInit.isInvalid()) { + AnyErrors = true; + New->setInvalidDecl(); + } else { + // FIXME: It would be nice if ASTOwningVector had a release function. + NewArgs.take(); + + NewInits.push_back((MemInitTy *)NewInit.get()); + } + } + + // Assign all the initializers to the new constructor. + ActOnMemInitializers(New, + /*FIXME: ColonLoc */ + SourceLocation(), + NewInits.data(), NewInits.size(), + AnyErrors); +} + +// TODO: this could be templated if the various decl types used the +// same method name. +static bool isInstantiationOf(ClassTemplateDecl *Pattern, + ClassTemplateDecl *Instance) { + Pattern = Pattern->getCanonicalDecl(); + + do { + Instance = Instance->getCanonicalDecl(); + if (Pattern == Instance) return true; + Instance = Instance->getInstantiatedFromMemberTemplate(); + } while (Instance); + + return false; +} + +static bool isInstantiationOf(FunctionTemplateDecl *Pattern, + FunctionTemplateDecl *Instance) { + Pattern = Pattern->getCanonicalDecl(); + + do { + Instance = Instance->getCanonicalDecl(); + if (Pattern == Instance) return true; + Instance = Instance->getInstantiatedFromMemberTemplate(); + } while (Instance); + + return false; +} + +static bool +isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern, + ClassTemplatePartialSpecializationDecl *Instance) { + Pattern + = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl()); + do { + Instance = cast<ClassTemplatePartialSpecializationDecl>( + Instance->getCanonicalDecl()); + if (Pattern == Instance) + return true; + Instance = Instance->getInstantiatedFromMember(); + } while (Instance); + + return false; +} + +static bool isInstantiationOf(CXXRecordDecl *Pattern, + CXXRecordDecl *Instance) { + Pattern = Pattern->getCanonicalDecl(); + + do { + Instance = Instance->getCanonicalDecl(); + if (Pattern == Instance) return true; + Instance = Instance->getInstantiatedFromMemberClass(); + } while (Instance); + + return false; +} + +static bool isInstantiationOf(FunctionDecl *Pattern, + FunctionDecl *Instance) { + Pattern = Pattern->getCanonicalDecl(); + + do { + Instance = Instance->getCanonicalDecl(); + if (Pattern == Instance) return true; + Instance = Instance->getInstantiatedFromMemberFunction(); + } while (Instance); + + return false; +} + +static bool isInstantiationOf(EnumDecl *Pattern, + EnumDecl *Instance) { + Pattern = Pattern->getCanonicalDecl(); + + do { + Instance = Instance->getCanonicalDecl(); + if (Pattern == Instance) return true; + Instance = Instance->getInstantiatedFromMemberEnum(); + } while (Instance); + + return false; +} + +static bool isInstantiationOf(UsingShadowDecl *Pattern, + UsingShadowDecl *Instance, + ASTContext &C) { + return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern; +} + +static bool isInstantiationOf(UsingDecl *Pattern, + UsingDecl *Instance, + ASTContext &C) { + return C.getInstantiatedFromUsingDecl(Instance) == Pattern; +} + +static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern, + UsingDecl *Instance, + ASTContext &C) { + return C.getInstantiatedFromUsingDecl(Instance) == Pattern; +} + +static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern, + UsingDecl *Instance, + ASTContext &C) { + return C.getInstantiatedFromUsingDecl(Instance) == Pattern; +} + +static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, + VarDecl *Instance) { + assert(Instance->isStaticDataMember()); + + Pattern = Pattern->getCanonicalDecl(); + + do { + Instance = Instance->getCanonicalDecl(); + if (Pattern == Instance) return true; + Instance = Instance->getInstantiatedFromStaticDataMember(); + } while (Instance); + + return false; +} + +// Other is the prospective instantiation +// D is the prospective pattern +static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { + if (D->getKind() != Other->getKind()) { + if (UnresolvedUsingTypenameDecl *UUD + = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { + if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { + return isInstantiationOf(UUD, UD, Ctx); + } + } + + if (UnresolvedUsingValueDecl *UUD + = dyn_cast<UnresolvedUsingValueDecl>(D)) { + if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { + return isInstantiationOf(UUD, UD, Ctx); + } + } + + return false; + } + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Other)) + return isInstantiationOf(cast<CXXRecordDecl>(D), Record); + + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Other)) + return isInstantiationOf(cast<FunctionDecl>(D), Function); + + if (EnumDecl *Enum = dyn_cast<EnumDecl>(Other)) + return isInstantiationOf(cast<EnumDecl>(D), Enum); + + if (VarDecl *Var = dyn_cast<VarDecl>(Other)) + if (Var->isStaticDataMember()) + return isInstantiationOfStaticDataMember(cast<VarDecl>(D), Var); + + if (ClassTemplateDecl *Temp = dyn_cast<ClassTemplateDecl>(Other)) + return isInstantiationOf(cast<ClassTemplateDecl>(D), Temp); + + if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other)) + return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp); + + if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other)) + return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D), + PartialSpec); + + if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) { + if (!Field->getDeclName()) { + // This is an unnamed field. + return Ctx.getInstantiatedFromUnnamedFieldDecl(Field) == + cast<FieldDecl>(D); + } + } + + if (UsingDecl *Using = dyn_cast<UsingDecl>(Other)) + return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx); + + if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other)) + return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx); + + return D->getDeclName() && isa<NamedDecl>(Other) && + D->getDeclName() == cast<NamedDecl>(Other)->getDeclName(); +} + +template<typename ForwardIterator> +static NamedDecl *findInstantiationOf(ASTContext &Ctx, + NamedDecl *D, + ForwardIterator first, + ForwardIterator last) { + for (; first != last; ++first) + if (isInstantiationOf(Ctx, D, *first)) + return cast<NamedDecl>(*first); + + return 0; +} + +/// \brief Finds the instantiation of the given declaration context +/// within the current instantiation. +/// +/// \returns NULL if there was an error +DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, + const MultiLevelTemplateArgumentList &TemplateArgs) { + if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) { + Decl* ID = FindInstantiatedDecl(Loc, D, TemplateArgs); + return cast_or_null<DeclContext>(ID); + } else return DC; +} + +/// \brief Find the instantiation of the given declaration within the +/// current instantiation. +/// +/// This routine is intended to be used when \p D is a declaration +/// referenced from within a template, that needs to mapped into the +/// corresponding declaration within an instantiation. For example, +/// given: +/// +/// \code +/// template<typename T> +/// struct X { +/// enum Kind { +/// KnownValue = sizeof(T) +/// }; +/// +/// bool getKind() const { return KnownValue; } +/// }; +/// +/// template struct X<int>; +/// \endcode +/// +/// In the instantiation of X<int>::getKind(), we need to map the +/// EnumConstantDecl for KnownValue (which refers to +/// X<T>::<Kind>::KnownValue) to its instantiation +/// (X<int>::<Kind>::KnownValue). InstantiateCurrentDeclRef() performs +/// this mapping from within the instantiation of X<int>. +NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, + const MultiLevelTemplateArgumentList &TemplateArgs) { + DeclContext *ParentDC = D->getDeclContext(); + if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || + isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || + (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) { + // D is a local of some kind. Look into the map of local + // declarations to their instantiations. + typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found + = CurrentInstantiationScope->findInstantiationOf(D); + + if (Found) { + if (Decl *FD = Found->dyn_cast<Decl *>()) + return cast<NamedDecl>(FD); + + unsigned PackIdx = ArgumentPackSubstitutionIndex; + return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]); + } + + // If we didn't find the decl, then we must have a label decl that hasn't + // been found yet. Lazily instantiate it and return it now. + assert(isa<LabelDecl>(D)); + + Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + assert(Inst && "Failed to instantiate label??"); + + CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return cast<LabelDecl>(Inst); + } + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { + if (!Record->isDependentContext()) + return D; + + // If the RecordDecl is actually the injected-class-name or a + // "templated" declaration for a class template, class template + // partial specialization, or a member class of a class template, + // substitute into the injected-class-name of the class template + // or partial specialization to find the new DeclContext. + QualType T; + ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); + + if (ClassTemplate) { + T = ClassTemplate->getInjectedClassNameSpecialization(); + } else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { + ClassTemplate = PartialSpec->getSpecializedTemplate(); + + // If we call SubstType with an InjectedClassNameType here we + // can end up in an infinite loop. + T = Context.getTypeDeclType(Record); + assert(isa<InjectedClassNameType>(T) && + "type of partial specialization is not an InjectedClassNameType"); + T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType(); + } + + if (!T.isNull()) { + // Substitute into the injected-class-name to get the type + // corresponding to the instantiation we want, which may also be + // the current instantiation (if we're in a template + // definition). This substitution should never fail, since we + // know we can instantiate the injected-class-name or we + // wouldn't have gotten to the injected-class-name! + + // FIXME: Can we use the CurrentInstantiationScope to avoid this + // extra instantiation in the common case? + T = SubstType(T, TemplateArgs, Loc, DeclarationName()); + assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); + + if (!T->isDependentType()) { + assert(T->isRecordType() && "Instantiation must produce a record type"); + return T->getAs<RecordType>()->getDecl(); + } + + // We are performing "partial" template instantiation to create + // the member declarations for the members of a class template + // specialization. Therefore, D is actually referring to something + // in the current instantiation. Look through the current + // context, which contains actual instantiations, to find the + // instantiation of the "current instantiation" that D refers + // to. + bool SawNonDependentContext = false; + for (DeclContext *DC = CurContext; !DC->isFileContext(); + DC = DC->getParent()) { + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(DC)) + if (isInstantiationOf(ClassTemplate, + Spec->getSpecializedTemplate())) + return Spec; + + if (!DC->isDependentContext()) + SawNonDependentContext = true; + } + + // We're performing "instantiation" of a member of the current + // instantiation while we are type-checking the + // definition. Compute the declaration context and return that. + assert(!SawNonDependentContext && + "No dependent context while instantiating record"); + DeclContext *DC = computeDeclContext(T); + assert(DC && + "Unable to find declaration for the current instantiation"); + return cast<CXXRecordDecl>(DC); + } + + // Fall through to deal with other dependent record types (e.g., + // anonymous unions in class templates). + } + + if (!ParentDC->isDependentContext()) + return D; + + ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs); + if (!ParentDC) + return 0; + + if (ParentDC != D->getDeclContext()) { + // We performed some kind of instantiation in the parent context, + // so now we need to look into the instantiated parent context to + // find the instantiation of the declaration D. + + // If our context used to be dependent, we may need to instantiate + // it before performing lookup into that context. + bool IsBeingInstantiated = false; + if (CXXRecordDecl *Spec = dyn_cast<CXXRecordDecl>(ParentDC)) { + if (!Spec->isDependentContext()) { + QualType T = Context.getTypeDeclType(Spec); + const RecordType *Tag = T->getAs<RecordType>(); + assert(Tag && "type of non-dependent record is not a RecordType"); + if (Tag->isBeingDefined()) + IsBeingInstantiated = true; + if (!Tag->isBeingDefined() && + RequireCompleteType(Loc, T, diag::err_incomplete_type)) + return 0; + + ParentDC = Tag->getDecl(); + } + } + + NamedDecl *Result = 0; + if (D->getDeclName()) { + DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName()); + Result = findInstantiationOf(Context, D, Found.first, Found.second); + } else { + // Since we don't have a name for the entity we're looking for, + // our only option is to walk through all of the declarations to + // find that name. This will occur in a few cases: + // + // - anonymous struct/union within a template + // - unnamed class/struct/union/enum within a template + // + // FIXME: Find a better way to find these instantiations! + Result = findInstantiationOf(Context, D, + ParentDC->decls_begin(), + ParentDC->decls_end()); + } + + if (!Result) { + if (isa<UsingShadowDecl>(D)) { + // UsingShadowDecls can instantiate to nothing because of using hiding. + } else if (Diags.hasErrorOccurred()) { + // We've already complained about something, so most likely this + // declaration failed to instantiate. There's no point in complaining + // further, since this is normal in invalid code. + } else if (IsBeingInstantiated) { + // The class in which this member exists is currently being + // instantiated, and we haven't gotten around to instantiating this + // member yet. This can happen when the code uses forward declarations + // of member classes, and introduces ordering dependencies via + // template instantiation. + Diag(Loc, diag::err_member_not_yet_instantiated) + << D->getDeclName() + << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC)); + Diag(D->getLocation(), diag::note_non_instantiated_member_here); + } else { + // We should have found something, but didn't. + llvm_unreachable("Unable to find instantiation of declaration!"); + } + } + + D = Result; + } + + return D; +} + +/// \brief Performs template instantiation for all implicit template +/// instantiations we have seen until this point. +void Sema::PerformPendingInstantiations(bool LocalOnly) { + while (!PendingLocalImplicitInstantiations.empty() || + (!LocalOnly && !PendingInstantiations.empty())) { + PendingImplicitInstantiation Inst; + + if (PendingLocalImplicitInstantiations.empty()) { + Inst = PendingInstantiations.front(); + PendingInstantiations.pop_front(); + } else { + Inst = PendingLocalImplicitInstantiations.front(); + PendingLocalImplicitInstantiations.pop_front(); + } + + // Instantiate function definitions + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) { + PrettyDeclStackTraceEntry CrashInfo(*this, Function, SourceLocation(), + "instantiating function definition"); + bool DefinitionRequired = Function->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition; + InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, + DefinitionRequired); + continue; + } + + // Instantiate static data member definitions. + VarDecl *Var = cast<VarDecl>(Inst.first); + assert(Var->isStaticDataMember() && "Not a static data member?"); + + // Don't try to instantiate declarations if the most recent redeclaration + // is invalid. + if (Var->getMostRecentDeclaration()->isInvalidDecl()) + continue; + + // Check if the most recent declaration has changed the specialization kind + // and removed the need for implicit instantiation. + switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) { + case TSK_Undeclared: + assert(false && "Cannot instantitiate an undeclared specialization."); + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitSpecialization: + continue; // No longer need to instantiate this type. + case TSK_ExplicitInstantiationDefinition: + // We only need an instantiation if the pending instantiation *is* the + // explicit instantiation. + if (Var != Var->getMostRecentDeclaration()) continue; + case TSK_ImplicitInstantiation: + break; + } + + PrettyDeclStackTraceEntry CrashInfo(*this, Var, Var->getLocation(), + "instantiating static data member " + "definition"); + + bool DefinitionRequired = Var->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition; + InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true, + DefinitionRequired); + } +} + +void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, + const MultiLevelTemplateArgumentList &TemplateArgs) { + for (DeclContext::ddiag_iterator I = Pattern->ddiag_begin(), + E = Pattern->ddiag_end(); I != E; ++I) { + DependentDiagnostic *DD = *I; + + switch (DD->getKind()) { + case DependentDiagnostic::Access: + HandleDependentAccessCheck(*DD, TemplateArgs); + break; + } + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp new file mode 100644 index 0000000..86d3bc1 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -0,0 +1,750 @@ +//===------- SemaTemplateVariadic.cpp - C++ Variadic Templates ------------===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements semantic analysis for C++0x variadic templates. +//===----------------------------------------------------------------------===/ + +#include "clang/Sema/Sema.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Template.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/TypeLoc.h" + +using namespace clang; + +//---------------------------------------------------------------------------- +// Visitor that collects unexpanded parameter packs +//---------------------------------------------------------------------------- + +namespace { + /// \brief A class that collects unexpanded parameter packs. + class CollectUnexpandedParameterPacksVisitor : + public RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> + { + typedef RecursiveASTVisitor<CollectUnexpandedParameterPacksVisitor> + inherited; + + llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded; + + public: + explicit CollectUnexpandedParameterPacksVisitor( + llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) + : Unexpanded(Unexpanded) { } + + bool shouldWalkTypesOfTypeLocs() const { return false; } + + //------------------------------------------------------------------------ + // Recording occurrences of (unexpanded) parameter packs. + //------------------------------------------------------------------------ + + /// \brief Record occurrences of template type parameter packs. + bool VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { + if (TL.getTypePtr()->isParameterPack()) + Unexpanded.push_back(std::make_pair(TL.getTypePtr(), TL.getNameLoc())); + return true; + } + + /// \brief Record occurrences of template type parameter packs + /// when we don't have proper source-location information for + /// them. + /// + /// Ideally, this routine would never be used. + bool VisitTemplateTypeParmType(TemplateTypeParmType *T) { + if (T->isParameterPack()) + Unexpanded.push_back(std::make_pair(T, SourceLocation())); + + return true; + } + + /// \brief Record occurrences of function and non-type template + /// parameter packs in an expression. + bool VisitDeclRefExpr(DeclRefExpr *E) { + if (E->getDecl()->isParameterPack()) + Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation())); + + return true; + } + + // \brief Record occurrences of function and non-type template parameter + // packs in a block-captured expression. + bool VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { + if (E->getDecl()->isParameterPack()) + Unexpanded.push_back(std::make_pair(E->getDecl(), E->getLocation())); + + return true; + } + + /// \brief Record occurrences of template template parameter packs. + bool TraverseTemplateName(TemplateName Template) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast_or_null<TemplateTemplateParmDecl>( + Template.getAsTemplateDecl())) + if (TTP->isParameterPack()) + Unexpanded.push_back(std::make_pair(TTP, SourceLocation())); + + return inherited::TraverseTemplateName(Template); + } + + //------------------------------------------------------------------------ + // Pruning the search for unexpanded parameter packs. + //------------------------------------------------------------------------ + + /// \brief Suppress traversal into statements and expressions that + /// do not contain unexpanded parameter packs. + bool TraverseStmt(Stmt *S) { + if (Expr *E = dyn_cast_or_null<Expr>(S)) + if (E->containsUnexpandedParameterPack()) + return inherited::TraverseStmt(E); + + return true; + } + + /// \brief Suppress traversal into types that do not contain + /// unexpanded parameter packs. + bool TraverseType(QualType T) { + if (!T.isNull() && T->containsUnexpandedParameterPack()) + return inherited::TraverseType(T); + + return true; + } + + /// \brief Suppress traversel into types with location information + /// that do not contain unexpanded parameter packs. + bool TraverseTypeLoc(TypeLoc TL) { + if (!TL.getType().isNull() && + TL.getType()->containsUnexpandedParameterPack()) + return inherited::TraverseTypeLoc(TL); + + return true; + } + + /// \brief Suppress traversal of non-parameter declarations, since + /// they cannot contain unexpanded parameter packs. + bool TraverseDecl(Decl *D) { + if (D && isa<ParmVarDecl>(D)) + return inherited::TraverseDecl(D); + + return true; + } + + /// \brief Suppress traversal of template argument pack expansions. + bool TraverseTemplateArgument(const TemplateArgument &Arg) { + if (Arg.isPackExpansion()) + return true; + + return inherited::TraverseTemplateArgument(Arg); + } + + /// \brief Suppress traversal of template argument pack expansions. + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) { + if (ArgLoc.getArgument().isPackExpansion()) + return true; + + return inherited::TraverseTemplateArgumentLoc(ArgLoc); + } + }; +} + +/// \brief Diagnose all of the unexpanded parameter packs in the given +/// vector. +static void +DiagnoseUnexpandedParameterPacks(Sema &S, SourceLocation Loc, + Sema::UnexpandedParameterPackContext UPPC, + const llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + llvm::SmallVector<SourceLocation, 4> Locations; + llvm::SmallVector<IdentifierInfo *, 4> Names; + llvm::SmallPtrSet<IdentifierInfo *, 4> NamesKnown; + + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { + IdentifierInfo *Name = 0; + if (const TemplateTypeParmType *TTP + = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) + Name = TTP->getIdentifier(); + else + Name = Unexpanded[I].first.get<NamedDecl *>()->getIdentifier(); + + if (Name && NamesKnown.insert(Name)) + Names.push_back(Name); + + if (Unexpanded[I].second.isValid()) + Locations.push_back(Unexpanded[I].second); + } + + DiagnosticBuilder DB + = Names.size() == 0? S.Diag(Loc, diag::err_unexpanded_parameter_pack_0) + << (int)UPPC + : Names.size() == 1? S.Diag(Loc, diag::err_unexpanded_parameter_pack_1) + << (int)UPPC << Names[0] + : Names.size() == 2? S.Diag(Loc, diag::err_unexpanded_parameter_pack_2) + << (int)UPPC << Names[0] << Names[1] + : S.Diag(Loc, diag::err_unexpanded_parameter_pack_3_or_more) + << (int)UPPC << Names[0] << Names[1]; + + for (unsigned I = 0, N = Locations.size(); I != N; ++I) + DB << SourceRange(Locations[I]); +} + +bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, + TypeSourceInfo *T, + UnexpandedParameterPackContext UPPC) { + // C++0x [temp.variadic]p5: + // An appearance of a name of a parameter pack that is not expanded is + // ill-formed. + if (!T->getType()->containsUnexpandedParameterPack()) + return false; + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc( + T->getTypeLoc()); + assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); + DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded); + return true; +} + +bool Sema::DiagnoseUnexpandedParameterPack(Expr *E, + UnexpandedParameterPackContext UPPC) { + // C++0x [temp.variadic]p5: + // An appearance of a name of a parameter pack that is not expanded is + // ill-formed. + if (!E->containsUnexpandedParameterPack()) + return false; + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseStmt(E); + assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); + DiagnoseUnexpandedParameterPacks(*this, E->getLocStart(), UPPC, Unexpanded); + return true; +} + +bool Sema::DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, + UnexpandedParameterPackContext UPPC) { + // C++0x [temp.variadic]p5: + // An appearance of a name of a parameter pack that is not expanded is + // ill-formed. + if (!SS.getScopeRep() || + !SS.getScopeRep()->containsUnexpandedParameterPack()) + return false; + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseNestedNameSpecifier(SS.getScopeRep()); + assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); + DiagnoseUnexpandedParameterPacks(*this, SS.getRange().getBegin(), + UPPC, Unexpanded); + return true; +} + +bool Sema::DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, + UnexpandedParameterPackContext UPPC) { + // C++0x [temp.variadic]p5: + // An appearance of a name of a parameter pack that is not expanded is + // ill-formed. + switch (NameInfo.getName().getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + return false; + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: + // FIXME: We shouldn't need this null check! + if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo()) + return DiagnoseUnexpandedParameterPack(NameInfo.getLoc(), TSInfo, UPPC); + + if (!NameInfo.getName().getCXXNameType()->containsUnexpandedParameterPack()) + return false; + + break; + } + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseType(NameInfo.getName().getCXXNameType()); + assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); + DiagnoseUnexpandedParameterPacks(*this, NameInfo.getLoc(), UPPC, Unexpanded); + return true; +} + +bool Sema::DiagnoseUnexpandedParameterPack(SourceLocation Loc, + TemplateName Template, + UnexpandedParameterPackContext UPPC) { + + if (Template.isNull() || !Template.containsUnexpandedParameterPack()) + return false; + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseTemplateName(Template); + assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); + DiagnoseUnexpandedParameterPacks(*this, Loc, UPPC, Unexpanded); + return true; +} + +bool Sema::DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, + UnexpandedParameterPackContext UPPC) { + if (Arg.getArgument().isNull() || + !Arg.getArgument().containsUnexpandedParameterPack()) + return false; + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseTemplateArgumentLoc(Arg); + assert(!Unexpanded.empty() && "Unable to find unexpanded parameter packs"); + DiagnoseUnexpandedParameterPacks(*this, Arg.getLocation(), UPPC, Unexpanded); + return true; +} + +void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg, + llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseTemplateArgument(Arg); +} + +void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg, + llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + CollectUnexpandedParameterPacksVisitor(Unexpanded) + .TraverseTemplateArgumentLoc(Arg); +} + +void Sema::collectUnexpandedParameterPacks(QualType T, + llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T); +} + +void Sema::collectUnexpandedParameterPacks(TypeLoc TL, + llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL); +} + +ParsedTemplateArgument +Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, + SourceLocation EllipsisLoc) { + if (Arg.isInvalid()) + return Arg; + + switch (Arg.getKind()) { + case ParsedTemplateArgument::Type: { + TypeResult Result = ActOnPackExpansion(Arg.getAsType(), EllipsisLoc); + if (Result.isInvalid()) + return ParsedTemplateArgument(); + + return ParsedTemplateArgument(Arg.getKind(), Result.get().getAsOpaquePtr(), + Arg.getLocation()); + } + + case ParsedTemplateArgument::NonType: { + ExprResult Result = ActOnPackExpansion(Arg.getAsExpr(), EllipsisLoc); + if (Result.isInvalid()) + return ParsedTemplateArgument(); + + return ParsedTemplateArgument(Arg.getKind(), Result.get(), + Arg.getLocation()); + } + + case ParsedTemplateArgument::Template: + if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) { + SourceRange R(Arg.getLocation()); + if (Arg.getScopeSpec().isValid()) + R.setBegin(Arg.getScopeSpec().getBeginLoc()); + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << R; + return ParsedTemplateArgument(); + } + + return Arg.getTemplatePackExpansion(EllipsisLoc); + } + llvm_unreachable("Unhandled template argument kind?"); + return ParsedTemplateArgument(); +} + +TypeResult Sema::ActOnPackExpansion(ParsedType Type, + SourceLocation EllipsisLoc) { + TypeSourceInfo *TSInfo; + GetTypeFromParser(Type, &TSInfo); + if (!TSInfo) + return true; + + TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, + llvm::Optional<unsigned>()); + if (!TSResult) + return true; + + return CreateParsedType(TSResult->getType(), TSResult); +} + +TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern, + SourceLocation EllipsisLoc, + llvm::Optional<unsigned> NumExpansions) { + // Create the pack expansion type and source-location information. + QualType Result = CheckPackExpansion(Pattern->getType(), + Pattern->getTypeLoc().getSourceRange(), + EllipsisLoc, NumExpansions); + if (Result.isNull()) + return 0; + + TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result); + PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc()); + TL.setEllipsisLoc(EllipsisLoc); + + // Copy over the source-location information from the type. + memcpy(TL.getNextTypeLoc().getOpaqueData(), + Pattern->getTypeLoc().getOpaqueData(), + Pattern->getTypeLoc().getFullDataSize()); + return TSResult; +} + +QualType Sema::CheckPackExpansion(QualType Pattern, + SourceRange PatternRange, + SourceLocation EllipsisLoc, + llvm::Optional<unsigned> NumExpansions) { + // C++0x [temp.variadic]p5: + // The pattern of a pack expansion shall name one or more + // parameter packs that are not expanded by a nested pack + // expansion. + if (!Pattern->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << PatternRange; + return QualType(); + } + + return Context.getPackExpansionType(Pattern, NumExpansions); +} + +ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { + return CheckPackExpansion(Pattern, EllipsisLoc, llvm::Optional<unsigned>()); +} + +ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, + llvm::Optional<unsigned> NumExpansions) { + if (!Pattern) + return ExprError(); + + // C++0x [temp.variadic]p5: + // The pattern of a pack expansion shall name one or more + // parameter packs that are not expanded by a nested pack + // expansion. + if (!Pattern->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << Pattern->getSourceRange(); + return ExprError(); + } + + // Create the pack expansion expression and source-location information. + return Owned(new (Context) PackExpansionExpr(Context.DependentTy, Pattern, + EllipsisLoc, NumExpansions)); +} + +/// \brief Retrieve the depth and index of a parameter pack. +static std::pair<unsigned, unsigned> +getDepthAndIndex(NamedDecl *ND) { + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND)) + return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); + + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND); + return std::make_pair(TTP->getDepth(), TTP->getIndex()); +} + +bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, + SourceRange PatternRange, + const UnexpandedParameterPack *Unexpanded, + unsigned NumUnexpanded, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool &ShouldExpand, + bool &RetainExpansion, + llvm::Optional<unsigned> &NumExpansions) { + ShouldExpand = true; + RetainExpansion = false; + std::pair<IdentifierInfo *, SourceLocation> FirstPack; + bool HaveFirstPack = false; + + for (unsigned I = 0; I != NumUnexpanded; ++I) { + // Compute the depth and index for this parameter pack. + unsigned Depth = 0, Index = 0; + IdentifierInfo *Name; + bool IsFunctionParameterPack = false; + + if (const TemplateTypeParmType *TTP + = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) { + Depth = TTP->getDepth(); + Index = TTP->getIndex(); + Name = TTP->getIdentifier(); + } else { + NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>(); + if (isa<ParmVarDecl>(ND)) + IsFunctionParameterPack = true; + else + llvm::tie(Depth, Index) = getDepthAndIndex(ND); + + Name = ND->getIdentifier(); + } + + // Determine the size of this argument pack. + unsigned NewPackSize; + if (IsFunctionParameterPack) { + // Figure out whether we're instantiating to an argument pack or not. + typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation + = CurrentInstantiationScope->findInstantiationOf( + Unexpanded[I].first.get<NamedDecl *>()); + if (Instantiation->is<DeclArgumentPack *>()) { + // We could expand this function parameter pack. + NewPackSize = Instantiation->get<DeclArgumentPack *>()->size(); + } else { + // We can't expand this function parameter pack, so we can't expand + // the pack expansion. + ShouldExpand = false; + continue; + } + } else { + // If we don't have a template argument at this depth/index, then we + // cannot expand the pack expansion. Make a note of this, but we still + // want to check any parameter packs we *do* have arguments for. + if (Depth >= TemplateArgs.getNumLevels() || + !TemplateArgs.hasTemplateArgument(Depth, Index)) { + ShouldExpand = false; + continue; + } + + // Determine the size of the argument pack. + NewPackSize = TemplateArgs(Depth, Index).pack_size(); + } + + // C++0x [temp.arg.explicit]p9: + // Template argument deduction can extend the sequence of template + // arguments corresponding to a template parameter pack, even when the + // sequence contains explicitly specified template arguments. + if (!IsFunctionParameterPack) { + if (NamedDecl *PartialPack + = CurrentInstantiationScope->getPartiallySubstitutedPack()){ + unsigned PartialDepth, PartialIndex; + llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack); + if (PartialDepth == Depth && PartialIndex == Index) + RetainExpansion = true; + } + } + + if (!NumExpansions) { + // The is the first pack we've seen for which we have an argument. + // Record it. + NumExpansions = NewPackSize; + FirstPack.first = Name; + FirstPack.second = Unexpanded[I].second; + HaveFirstPack = true; + continue; + } + + if (NewPackSize != *NumExpansions) { + // C++0x [temp.variadic]p5: + // All of the parameter packs expanded by a pack expansion shall have + // the same number of arguments specified. + if (HaveFirstPack) + Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict) + << FirstPack.first << Name << *NumExpansions << NewPackSize + << SourceRange(FirstPack.second) << SourceRange(Unexpanded[I].second); + else + Diag(EllipsisLoc, diag::err_pack_expansion_length_conflict_multilevel) + << Name << *NumExpansions << NewPackSize + << SourceRange(Unexpanded[I].second); + return true; + } + } + + return false; +} + +unsigned Sema::getNumArgumentsInExpansion(QualType T, + const MultiLevelTemplateArgumentList &TemplateArgs) { + QualType Pattern = cast<PackExpansionType>(T)->getPattern(); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); + + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { + // Compute the depth and index for this parameter pack. + unsigned Depth; + unsigned Index; + + if (const TemplateTypeParmType *TTP + = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) { + Depth = TTP->getDepth(); + Index = TTP->getIndex(); + } else { + NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>(); + if (isa<ParmVarDecl>(ND)) { + // Function parameter pack. + typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation + = CurrentInstantiationScope->findInstantiationOf( + Unexpanded[I].first.get<NamedDecl *>()); + if (Instantiation->is<DeclArgumentPack *>()) + return Instantiation->get<DeclArgumentPack *>()->size(); + + continue; + } + + llvm::tie(Depth, Index) = getDepthAndIndex(ND); + } + if (Depth >= TemplateArgs.getNumLevels() || + !TemplateArgs.hasTemplateArgument(Depth, Index)) + continue; + + // Determine the size of the argument pack. + return TemplateArgs(Depth, Index).pack_size(); + } + + llvm_unreachable("No unexpanded parameter packs in type expansion."); + return 0; +} + +bool Sema::containsUnexpandedParameterPacks(Declarator &D) { + const DeclSpec &DS = D.getDeclSpec(); + switch (DS.getTypeSpecType()) { + case TST_typename: + case TST_typeofType: + case TST_underlyingType: { + QualType T = DS.getRepAsType().get(); + if (!T.isNull() && T->containsUnexpandedParameterPack()) + return true; + break; + } + + case TST_typeofExpr: + case TST_decltype: + if (DS.getRepAsExpr() && + DS.getRepAsExpr()->containsUnexpandedParameterPack()) + return true; + break; + + case TST_unspecified: + case TST_void: + case TST_char: + case TST_wchar: + case TST_char16: + case TST_char32: + case TST_int: + case TST_float: + case TST_double: + case TST_bool: + case TST_decimal32: + case TST_decimal64: + case TST_decimal128: + case TST_enum: + case TST_union: + case TST_struct: + case TST_class: + case TST_auto: + case TST_unknown_anytype: + case TST_error: + break; + } + + for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) { + const DeclaratorChunk &Chunk = D.getTypeObject(I); + switch (Chunk.Kind) { + case DeclaratorChunk::Pointer: + case DeclaratorChunk::Reference: + case DeclaratorChunk::Paren: + // These declarator chunks cannot contain any parameter packs. + break; + + case DeclaratorChunk::Array: + case DeclaratorChunk::Function: + case DeclaratorChunk::BlockPointer: + // Syntactically, these kinds of declarator chunks all come after the + // declarator-id (conceptually), so the parser should not invoke this + // routine at this time. + llvm_unreachable("Could not have seen this kind of declarator chunk"); + break; + + case DeclaratorChunk::MemberPointer: + if (Chunk.Mem.Scope().getScopeRep() && + Chunk.Mem.Scope().getScopeRep()->containsUnexpandedParameterPack()) + return true; + break; + } + } + + return false; +} + +/// \brief Called when an expression computing the size of a parameter pack +/// is parsed. +/// +/// \code +/// template<typename ...Types> struct count { +/// static const unsigned value = sizeof...(Types); +/// }; +/// \endcode +/// +// +/// \param OpLoc The location of the "sizeof" keyword. +/// \param Name The name of the parameter pack whose size will be determined. +/// \param NameLoc The source location of the name of the parameter pack. +/// \param RParenLoc The location of the closing parentheses. +ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, + SourceLocation OpLoc, + IdentifierInfo &Name, + SourceLocation NameLoc, + SourceLocation RParenLoc) { + // C++0x [expr.sizeof]p5: + // The identifier in a sizeof... expression shall name a parameter pack. + LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName); + LookupName(R, S); + + NamedDecl *ParameterPack = 0; + switch (R.getResultKind()) { + case LookupResult::Found: + ParameterPack = R.getFoundDecl(); + break; + + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + if (DeclarationName CorrectedName = CorrectTypo(R, S, 0, 0, false, + CTC_NoKeywords)) { + if (NamedDecl *CorrectedResult = R.getAsSingle<NamedDecl>()) + if (CorrectedResult->isParameterPack()) { + ParameterPack = CorrectedResult; + Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest) + << &Name << CorrectedName + << FixItHint::CreateReplacement(NameLoc, + CorrectedName.getAsString()); + Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here) + << CorrectedName; + } + } + + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + break; + + case LookupResult::Ambiguous: + DiagnoseAmbiguousLookup(R); + return ExprError(); + } + + if (!ParameterPack || !ParameterPack->isParameterPack()) { + Diag(NameLoc, diag::err_sizeof_pack_no_pack_name) + << &Name; + return ExprError(); + } + + return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, + ParameterPack, NameLoc, RParenLoc); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp new file mode 100644 index 0000000..5fd8afa --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -0,0 +1,3497 @@ +//===--- SemaType.cpp - Semantic Analysis for Types -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements type-related semantic analysis. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Template.h" +#include "clang/Basic/OpenCL.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeLocVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/DeclSpec.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; + +/// \brief Perform adjustment on the parameter type of a function. +/// +/// This routine adjusts the given parameter type @p T to the actual +/// parameter type used by semantic analysis (C99 6.7.5.3p[7,8], +/// C++ [dcl.fct]p3). The adjusted parameter type is returned. +QualType Sema::adjustParameterType(QualType T) { + // C99 6.7.5.3p7: + // A declaration of a parameter as "array of type" shall be + // adjusted to "qualified pointer to type", where the type + // qualifiers (if any) are those specified within the [ and ] of + // the array type derivation. + if (T->isArrayType()) + return Context.getArrayDecayedType(T); + + // C99 6.7.5.3p8: + // A declaration of a parameter as "function returning type" + // shall be adjusted to "pointer to function returning type", as + // in 6.3.2.1. + if (T->isFunctionType()) + return Context.getPointerType(T); + + return T; +} + + + +/// isOmittedBlockReturnType - Return true if this declarator is missing a +/// return type because this is a omitted return type on a block literal. +static bool isOmittedBlockReturnType(const Declarator &D) { + if (D.getContext() != Declarator::BlockLiteralContext || + D.getDeclSpec().hasTypeSpecifier()) + return false; + + if (D.getNumTypeObjects() == 0) + return true; // ^{ ... } + + if (D.getNumTypeObjects() == 1 && + D.getTypeObject(0).Kind == DeclaratorChunk::Function) + return true; // ^(int X, float Y) { ... } + + return false; +} + +/// diagnoseBadTypeAttribute - Diagnoses a type attribute which +/// doesn't apply to the given type. +static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, + QualType type) { + bool useInstantiationLoc = false; + + unsigned diagID = 0; + switch (attr.getKind()) { + case AttributeList::AT_objc_gc: + diagID = diag::warn_pointer_attribute_wrong_type; + useInstantiationLoc = true; + break; + + default: + // Assume everything else was a function attribute. + diagID = diag::warn_function_attribute_wrong_type; + break; + } + + SourceLocation loc = attr.getLoc(); + llvm::StringRef name = attr.getName()->getName(); + + // The GC attributes are usually written with macros; special-case them. + if (useInstantiationLoc && loc.isMacroID() && attr.getParameterName()) { + if (attr.getParameterName()->isStr("strong")) { + if (S.findMacroSpelling(loc, "__strong")) name = "__strong"; + } else if (attr.getParameterName()->isStr("weak")) { + if (S.findMacroSpelling(loc, "__weak")) name = "__weak"; + } + } + + S.Diag(loc, diagID) << name << type; +} + +// objc_gc applies to Objective-C pointers or, otherwise, to the +// smallest available pointer type (i.e. 'void*' in 'void**'). +#define OBJC_POINTER_TYPE_ATTRS_CASELIST \ + case AttributeList::AT_objc_gc + +// Function type attributes. +#define FUNCTION_TYPE_ATTRS_CASELIST \ + case AttributeList::AT_noreturn: \ + case AttributeList::AT_cdecl: \ + case AttributeList::AT_fastcall: \ + case AttributeList::AT_stdcall: \ + case AttributeList::AT_thiscall: \ + case AttributeList::AT_pascal: \ + case AttributeList::AT_regparm: \ + case AttributeList::AT_pcs \ + +namespace { + /// An object which stores processing state for the entire + /// GetTypeForDeclarator process. + class TypeProcessingState { + Sema &sema; + + /// The declarator being processed. + Declarator &declarator; + + /// The index of the declarator chunk we're currently processing. + /// May be the total number of valid chunks, indicating the + /// DeclSpec. + unsigned chunkIndex; + + /// Whether there are non-trivial modifications to the decl spec. + bool trivial; + + /// Whether we saved the attributes in the decl spec. + bool hasSavedAttrs; + + /// The original set of attributes on the DeclSpec. + llvm::SmallVector<AttributeList*, 2> savedAttrs; + + /// A list of attributes to diagnose the uselessness of when the + /// processing is complete. + llvm::SmallVector<AttributeList*, 2> ignoredTypeAttrs; + + public: + TypeProcessingState(Sema &sema, Declarator &declarator) + : sema(sema), declarator(declarator), + chunkIndex(declarator.getNumTypeObjects()), + trivial(true), hasSavedAttrs(false) {} + + Sema &getSema() const { + return sema; + } + + Declarator &getDeclarator() const { + return declarator; + } + + unsigned getCurrentChunkIndex() const { + return chunkIndex; + } + + void setCurrentChunkIndex(unsigned idx) { + assert(idx <= declarator.getNumTypeObjects()); + chunkIndex = idx; + } + + AttributeList *&getCurrentAttrListRef() const { + assert(chunkIndex <= declarator.getNumTypeObjects()); + if (chunkIndex == declarator.getNumTypeObjects()) + return getMutableDeclSpec().getAttributes().getListRef(); + return declarator.getTypeObject(chunkIndex).getAttrListRef(); + } + + /// Save the current set of attributes on the DeclSpec. + void saveDeclSpecAttrs() { + // Don't try to save them multiple times. + if (hasSavedAttrs) return; + + DeclSpec &spec = getMutableDeclSpec(); + for (AttributeList *attr = spec.getAttributes().getList(); attr; + attr = attr->getNext()) + savedAttrs.push_back(attr); + trivial &= savedAttrs.empty(); + hasSavedAttrs = true; + } + + /// Record that we had nowhere to put the given type attribute. + /// We will diagnose such attributes later. + void addIgnoredTypeAttr(AttributeList &attr) { + ignoredTypeAttrs.push_back(&attr); + } + + /// Diagnose all the ignored type attributes, given that the + /// declarator worked out to the given type. + void diagnoseIgnoredTypeAttrs(QualType type) const { + for (llvm::SmallVectorImpl<AttributeList*>::const_iterator + i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end(); + i != e; ++i) + diagnoseBadTypeAttribute(getSema(), **i, type); + } + + ~TypeProcessingState() { + if (trivial) return; + + restoreDeclSpecAttrs(); + } + + private: + DeclSpec &getMutableDeclSpec() const { + return const_cast<DeclSpec&>(declarator.getDeclSpec()); + } + + void restoreDeclSpecAttrs() { + assert(hasSavedAttrs); + + if (savedAttrs.empty()) { + getMutableDeclSpec().getAttributes().set(0); + return; + } + + getMutableDeclSpec().getAttributes().set(savedAttrs[0]); + for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i) + savedAttrs[i]->setNext(savedAttrs[i+1]); + savedAttrs.back()->setNext(0); + } + }; + + /// Basically std::pair except that we really want to avoid an + /// implicit operator= for safety concerns. It's also a minor + /// link-time optimization for this to be a private type. + struct AttrAndList { + /// The attribute. + AttributeList &first; + + /// The head of the list the attribute is currently in. + AttributeList *&second; + + AttrAndList(AttributeList &attr, AttributeList *&head) + : first(attr), second(head) {} + }; +} + +namespace llvm { + template <> struct isPodLike<AttrAndList> { + static const bool value = true; + }; +} + +static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) { + attr.setNext(head); + head = &attr; +} + +static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) { + if (head == &attr) { + head = attr.getNext(); + return; + } + + AttributeList *cur = head; + while (true) { + assert(cur && cur->getNext() && "ran out of attrs?"); + if (cur->getNext() == &attr) { + cur->setNext(attr.getNext()); + return; + } + cur = cur->getNext(); + } +} + +static void moveAttrFromListToList(AttributeList &attr, + AttributeList *&fromList, + AttributeList *&toList) { + spliceAttrOutOfList(attr, fromList); + spliceAttrIntoList(attr, toList); +} + +static void processTypeAttrs(TypeProcessingState &state, + QualType &type, bool isDeclSpec, + AttributeList *attrs); + +static bool handleFunctionTypeAttr(TypeProcessingState &state, + AttributeList &attr, + QualType &type); + +static bool handleObjCGCTypeAttr(TypeProcessingState &state, + AttributeList &attr, QualType &type); + +static bool handleObjCPointerTypeAttr(TypeProcessingState &state, + AttributeList &attr, QualType &type) { + // Right now, we have exactly one of these attributes: objc_gc. + assert(attr.getKind() == AttributeList::AT_objc_gc); + return handleObjCGCTypeAttr(state, attr, type); +} + +/// Given that an objc_gc attribute was written somewhere on a +/// declaration *other* than on the declarator itself (for which, use +/// distributeObjCPointerTypeAttrFromDeclarator), and given that it +/// didn't apply in whatever position it was written in, try to move +/// it to a more appropriate position. +static void distributeObjCPointerTypeAttr(TypeProcessingState &state, + AttributeList &attr, + QualType type) { + Declarator &declarator = state.getDeclarator(); + for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) { + DeclaratorChunk &chunk = declarator.getTypeObject(i-1); + switch (chunk.Kind) { + case DeclaratorChunk::Pointer: + case DeclaratorChunk::BlockPointer: + moveAttrFromListToList(attr, state.getCurrentAttrListRef(), + chunk.getAttrListRef()); + return; + + case DeclaratorChunk::Paren: + case DeclaratorChunk::Array: + continue; + + // Don't walk through these. + case DeclaratorChunk::Reference: + case DeclaratorChunk::Function: + case DeclaratorChunk::MemberPointer: + goto error; + } + } + error: + + diagnoseBadTypeAttribute(state.getSema(), attr, type); +} + +/// Distribute an objc_gc type attribute that was written on the +/// declarator. +static void +distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, + AttributeList &attr, + QualType &declSpecType) { + Declarator &declarator = state.getDeclarator(); + + // objc_gc goes on the innermost pointer to something that's not a + // pointer. + unsigned innermost = -1U; + bool considerDeclSpec = true; + for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) { + DeclaratorChunk &chunk = declarator.getTypeObject(i); + switch (chunk.Kind) { + case DeclaratorChunk::Pointer: + case DeclaratorChunk::BlockPointer: + innermost = i; + continue; + + case DeclaratorChunk::Reference: + case DeclaratorChunk::MemberPointer: + case DeclaratorChunk::Paren: + case DeclaratorChunk::Array: + continue; + + case DeclaratorChunk::Function: + considerDeclSpec = false; + goto done; + } + } + done: + + // That might actually be the decl spec if we weren't blocked by + // anything in the declarator. + if (considerDeclSpec) { + if (handleObjCPointerTypeAttr(state, attr, declSpecType)) { + // Splice the attribute into the decl spec. Prevents the + // attribute from being applied multiple times and gives + // the source-location-filler something to work with. + state.saveDeclSpecAttrs(); + moveAttrFromListToList(attr, declarator.getAttrListRef(), + declarator.getMutableDeclSpec().getAttributes().getListRef()); + return; + } + } + + // Otherwise, if we found an appropriate chunk, splice the attribute + // into it. + if (innermost != -1U) { + moveAttrFromListToList(attr, declarator.getAttrListRef(), + declarator.getTypeObject(innermost).getAttrListRef()); + return; + } + + // Otherwise, diagnose when we're done building the type. + spliceAttrOutOfList(attr, declarator.getAttrListRef()); + state.addIgnoredTypeAttr(attr); +} + +/// A function type attribute was written somewhere in a declaration +/// *other* than on the declarator itself or in the decl spec. Given +/// that it didn't apply in whatever position it was written in, try +/// to move it to a more appropriate position. +static void distributeFunctionTypeAttr(TypeProcessingState &state, + AttributeList &attr, + QualType type) { + Declarator &declarator = state.getDeclarator(); + + // Try to push the attribute from the return type of a function to + // the function itself. + for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) { + DeclaratorChunk &chunk = declarator.getTypeObject(i-1); + switch (chunk.Kind) { + case DeclaratorChunk::Function: + moveAttrFromListToList(attr, state.getCurrentAttrListRef(), + chunk.getAttrListRef()); + return; + + case DeclaratorChunk::Paren: + case DeclaratorChunk::Pointer: + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::Array: + case DeclaratorChunk::Reference: + case DeclaratorChunk::MemberPointer: + continue; + } + } + + diagnoseBadTypeAttribute(state.getSema(), attr, type); +} + +/// Try to distribute a function type attribute to the innermost +/// function chunk or type. Returns true if the attribute was +/// distributed, false if no location was found. +static bool +distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, + AttributeList &attr, + AttributeList *&attrList, + QualType &declSpecType) { + Declarator &declarator = state.getDeclarator(); + + // Put it on the innermost function chunk, if there is one. + for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) { + DeclaratorChunk &chunk = declarator.getTypeObject(i); + if (chunk.Kind != DeclaratorChunk::Function) continue; + + moveAttrFromListToList(attr, attrList, chunk.getAttrListRef()); + return true; + } + + return handleFunctionTypeAttr(state, attr, declSpecType); +} + +/// A function type attribute was written in the decl spec. Try to +/// apply it somewhere. +static void +distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, + AttributeList &attr, + QualType &declSpecType) { + state.saveDeclSpecAttrs(); + + // Try to distribute to the innermost. + if (distributeFunctionTypeAttrToInnermost(state, attr, + state.getCurrentAttrListRef(), + declSpecType)) + return; + + // If that failed, diagnose the bad attribute when the declarator is + // fully built. + state.addIgnoredTypeAttr(attr); +} + +/// A function type attribute was written on the declarator. Try to +/// apply it somewhere. +static void +distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, + AttributeList &attr, + QualType &declSpecType) { + Declarator &declarator = state.getDeclarator(); + + // Try to distribute to the innermost. + if (distributeFunctionTypeAttrToInnermost(state, attr, + declarator.getAttrListRef(), + declSpecType)) + return; + + // If that failed, diagnose the bad attribute when the declarator is + // fully built. + spliceAttrOutOfList(attr, declarator.getAttrListRef()); + state.addIgnoredTypeAttr(attr); +} + +/// \brief Given that there are attributes written on the declarator +/// itself, try to distribute any type attributes to the appropriate +/// declarator chunk. +/// +/// These are attributes like the following: +/// int f ATTR; +/// int (f ATTR)(); +/// but not necessarily this: +/// int f() ATTR; +static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, + QualType &declSpecType) { + // Collect all the type attributes from the declarator itself. + assert(state.getDeclarator().getAttributes() && "declarator has no attrs!"); + AttributeList *attr = state.getDeclarator().getAttributes(); + AttributeList *next; + do { + next = attr->getNext(); + + switch (attr->getKind()) { + OBJC_POINTER_TYPE_ATTRS_CASELIST: + distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType); + break; + + FUNCTION_TYPE_ATTRS_CASELIST: + distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); + break; + + default: + break; + } + } while ((attr = next)); +} + +/// Add a synthetic '()' to a block-literal declarator if it is +/// required, given the return type. +static void maybeSynthesizeBlockSignature(TypeProcessingState &state, + QualType declSpecType) { + Declarator &declarator = state.getDeclarator(); + + // First, check whether the declarator would produce a function, + // i.e. whether the innermost semantic chunk is a function. + if (declarator.isFunctionDeclarator()) { + // If so, make that declarator a prototyped declarator. + declarator.getFunctionTypeInfo().hasPrototype = true; + return; + } + + // If there are any type objects, the type as written won't name a + // function, regardless of the decl spec type. This is because a + // block signature declarator is always an abstract-declarator, and + // abstract-declarators can't just be parentheses chunks. Therefore + // we need to build a function chunk unless there are no type + // objects and the decl spec type is a function. + if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType()) + return; + + // Note that there *are* cases with invalid declarators where + // declarators consist solely of parentheses. In general, these + // occur only in failed efforts to make function declarators, so + // faking up the function chunk is still the right thing to do. + + // Otherwise, we need to fake up a function declarator. + SourceLocation loc = declarator.getSourceRange().getBegin(); + + // ...and *prepend* it to the declarator. + declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction( + /*proto*/ true, + /*variadic*/ false, SourceLocation(), + /*args*/ 0, 0, + /*type quals*/ 0, + /*ref-qualifier*/true, SourceLocation(), + /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, + /*parens*/ loc, loc, + declarator)); + + // For consistency, make sure the state still has us as processing + // the decl spec. + assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1); + state.setCurrentChunkIndex(declarator.getNumTypeObjects()); +} + +/// \brief Convert the specified declspec to the appropriate type +/// object. +/// \param D the declarator containing the declaration specifier. +/// \returns The type described by the declaration specifiers. This function +/// never returns null. +static QualType ConvertDeclSpecToType(Sema &S, TypeProcessingState &state) { + // FIXME: Should move the logic from DeclSpec::Finish to here for validity + // checking. + + Declarator &declarator = state.getDeclarator(); + const DeclSpec &DS = declarator.getDeclSpec(); + SourceLocation DeclLoc = declarator.getIdentifierLoc(); + if (DeclLoc.isInvalid()) + DeclLoc = DS.getSourceRange().getBegin(); + + ASTContext &Context = S.Context; + + QualType Result; + switch (DS.getTypeSpecType()) { + case DeclSpec::TST_void: + Result = Context.VoidTy; + break; + case DeclSpec::TST_char: + if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) + Result = Context.CharTy; + else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) + Result = Context.SignedCharTy; + else { + assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned && + "Unknown TSS value"); + Result = Context.UnsignedCharTy; + } + break; + case DeclSpec::TST_wchar: + if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) + Result = Context.WCharTy; + else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) { + S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) + << DS.getSpecifierName(DS.getTypeSpecType()); + Result = Context.getSignedWCharType(); + } else { + assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned && + "Unknown TSS value"); + S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) + << DS.getSpecifierName(DS.getTypeSpecType()); + Result = Context.getUnsignedWCharType(); + } + break; + case DeclSpec::TST_char16: + assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && + "Unknown TSS value"); + Result = Context.Char16Ty; + break; + case DeclSpec::TST_char32: + assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && + "Unknown TSS value"); + Result = Context.Char32Ty; + break; + case DeclSpec::TST_unspecified: + // "<proto1,proto2>" is an objc qualified ID with a missing id. + if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { + Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, + (ObjCProtocolDecl**)PQ, + DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(Result); + break; + } + + // If this is a missing declspec in a block literal return context, then it + // is inferred from the return statements inside the block. + if (isOmittedBlockReturnType(declarator)) { + Result = Context.DependentTy; + break; + } + + // Unspecified typespec defaults to int in C90. However, the C90 grammar + // [C90 6.5] only allows a decl-spec if there was *some* type-specifier, + // type-qualifier, or storage-class-specifier. If not, emit an extwarn. + // Note that the one exception to this is function definitions, which are + // allowed to be completely missing a declspec. This is handled in the + // parser already though by it pretending to have seen an 'int' in this + // case. + if (S.getLangOptions().ImplicitInt) { + // In C89 mode, we only warn if there is a completely missing declspec + // when one is not allowed. + if (DS.isEmpty()) { + S.Diag(DeclLoc, diag::ext_missing_declspec) + << DS.getSourceRange() + << FixItHint::CreateInsertion(DS.getSourceRange().getBegin(), "int"); + } + } else if (!DS.hasTypeSpecifier()) { + // C99 and C++ require a type specifier. For example, C99 6.7.2p2 says: + // "At least one type specifier shall be given in the declaration + // specifiers in each declaration, and in the specifier-qualifier list in + // each struct declaration and type name." + // FIXME: Does Microsoft really have the implicit int extension in C++? + if (S.getLangOptions().CPlusPlus && + !S.getLangOptions().Microsoft) { + S.Diag(DeclLoc, diag::err_missing_type_specifier) + << DS.getSourceRange(); + + // When this occurs in C++ code, often something is very broken with the + // value being declared, poison it as invalid so we don't get chains of + // errors. + declarator.setInvalidType(true); + } else { + S.Diag(DeclLoc, diag::ext_missing_type_specifier) + << DS.getSourceRange(); + } + } + + // FALL THROUGH. + case DeclSpec::TST_int: { + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_unspecified: Result = Context.IntTy; break; + case DeclSpec::TSW_short: Result = Context.ShortTy; break; + case DeclSpec::TSW_long: Result = Context.LongTy; break; + case DeclSpec::TSW_longlong: + Result = Context.LongLongTy; + + // long long is a C99 feature. + if (!S.getLangOptions().C99 && + !S.getLangOptions().CPlusPlus0x) + S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong); + break; + } + } else { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break; + case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break; + case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break; + case DeclSpec::TSW_longlong: + Result = Context.UnsignedLongLongTy; + + // long long is a C99 feature. + if (!S.getLangOptions().C99 && + !S.getLangOptions().CPlusPlus0x) + S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong); + break; + } + } + break; + } + case DeclSpec::TST_float: Result = Context.FloatTy; break; + case DeclSpec::TST_double: + if (DS.getTypeSpecWidth() == DeclSpec::TSW_long) + Result = Context.LongDoubleTy; + else + Result = Context.DoubleTy; + + if (S.getLangOptions().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64); + declarator.setInvalidType(true); + } + break; + case DeclSpec::TST_bool: Result = Context.BoolTy; break; // _Bool or bool + case DeclSpec::TST_decimal32: // _Decimal32 + case DeclSpec::TST_decimal64: // _Decimal64 + case DeclSpec::TST_decimal128: // _Decimal128 + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported); + Result = Context.IntTy; + declarator.setInvalidType(true); + break; + case DeclSpec::TST_class: + case DeclSpec::TST_enum: + case DeclSpec::TST_union: + case DeclSpec::TST_struct: { + TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl()); + if (!D) { + // This can happen in C++ with ambiguous lookups. + Result = Context.IntTy; + declarator.setInvalidType(true); + break; + } + + // If the type is deprecated or unavailable, diagnose it. + S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc()); + + assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && + DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!"); + + // TypeQuals handled by caller. + Result = Context.getTypeDeclType(D); + + // In both C and C++, make an ElaboratedType. + ElaboratedTypeKeyword Keyword + = ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType()); + Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result); + + if (D->isInvalidDecl()) + declarator.setInvalidType(true); + break; + } + case DeclSpec::TST_typename: { + assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && + DS.getTypeSpecSign() == 0 && + "Can't handle qualifiers on typedef names yet!"); + Result = S.GetTypeFromParser(DS.getRepAsType()); + if (Result.isNull()) + declarator.setInvalidType(true); + else if (DeclSpec::ProtocolQualifierListTy PQ + = DS.getProtocolQualifiers()) { + if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) { + // Silently drop any existing protocol qualifiers. + // TODO: determine whether that's the right thing to do. + if (ObjT->getNumProtocols()) + Result = ObjT->getBaseType(); + + if (DS.getNumProtocolQualifiers()) + Result = Context.getObjCObjectType(Result, + (ObjCProtocolDecl**) PQ, + DS.getNumProtocolQualifiers()); + } else if (Result->isObjCIdType()) { + // id<protocol-list> + Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, + (ObjCProtocolDecl**) PQ, + DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(Result); + } else if (Result->isObjCClassType()) { + // Class<protocol-list> + Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, + (ObjCProtocolDecl**) PQ, + DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(Result); + } else { + S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers) + << DS.getSourceRange(); + declarator.setInvalidType(true); + } + } + + // TypeQuals handled by caller. + break; + } + case DeclSpec::TST_typeofType: + // FIXME: Preserve type source info. + Result = S.GetTypeFromParser(DS.getRepAsType()); + assert(!Result.isNull() && "Didn't get a type for typeof?"); + if (!Result->isDependentType()) + if (const TagType *TT = Result->getAs<TagType>()) + S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc()); + // TypeQuals handled by caller. + Result = Context.getTypeOfType(Result); + break; + case DeclSpec::TST_typeofExpr: { + Expr *E = DS.getRepAsExpr(); + assert(E && "Didn't get an expression for typeof?"); + // TypeQuals handled by caller. + Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + declarator.setInvalidType(true); + } + break; + } + case DeclSpec::TST_decltype: { + Expr *E = DS.getRepAsExpr(); + assert(E && "Didn't get an expression for decltype?"); + // TypeQuals handled by caller. + Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + declarator.setInvalidType(true); + } + break; + } + case DeclSpec::TST_underlyingType: + Result = S.GetTypeFromParser(DS.getRepAsType()); + assert(!Result.isNull() && "Didn't get a type for __underlying_type?"); + Result = S.BuildUnaryTransformType(Result, + UnaryTransformType::EnumUnderlyingType, + DS.getTypeSpecTypeLoc()); + if (Result.isNull()) { + Result = Context.IntTy; + declarator.setInvalidType(true); + } + break; + + case DeclSpec::TST_auto: { + // TypeQuals handled by caller. + Result = Context.getAutoType(QualType()); + break; + } + + case DeclSpec::TST_unknown_anytype: + Result = Context.UnknownAnyTy; + break; + + case DeclSpec::TST_error: + Result = Context.IntTy; + declarator.setInvalidType(true); + break; + } + + // Handle complex types. + if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) { + if (S.getLangOptions().Freestanding) + S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex); + Result = Context.getComplexType(Result); + } else if (DS.isTypeAltiVecVector()) { + unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result)); + assert(typeSize > 0 && "type size for vector must be greater than 0 bits"); + VectorType::VectorKind VecKind = VectorType::AltiVecVector; + if (DS.isTypeAltiVecPixel()) + VecKind = VectorType::AltiVecPixel; + else if (DS.isTypeAltiVecBool()) + VecKind = VectorType::AltiVecBool; + Result = Context.getVectorType(Result, 128/typeSize, VecKind); + } + + // FIXME: Imaginary. + if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary) + S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported); + + // Before we process any type attributes, synthesize a block literal + // function declarator if necessary. + if (declarator.getContext() == Declarator::BlockLiteralContext) + maybeSynthesizeBlockSignature(state, Result); + + // Apply any type attributes from the decl spec. This may cause the + // list of type attributes to be temporarily saved while the type + // attributes are pushed around. + if (AttributeList *attrs = DS.getAttributes().getList()) + processTypeAttrs(state, Result, true, attrs); + + // Apply const/volatile/restrict qualifiers to T. + if (unsigned TypeQuals = DS.getTypeQualifiers()) { + + // Enforce C99 6.7.3p2: "Types other than pointer types derived from object + // or incomplete types shall not be restrict-qualified." C++ also allows + // restrict-qualified references. + if (TypeQuals & DeclSpec::TQ_restrict) { + if (Result->isAnyPointerType() || Result->isReferenceType()) { + QualType EltTy; + if (Result->isObjCObjectPointerType()) + EltTy = Result; + else + EltTy = Result->isPointerType() ? + Result->getAs<PointerType>()->getPointeeType() : + Result->getAs<ReferenceType>()->getPointeeType(); + + // If we have a pointer or reference, the pointee must have an object + // incomplete type. + if (!EltTy->isIncompleteOrObjectType()) { + S.Diag(DS.getRestrictSpecLoc(), + diag::err_typecheck_invalid_restrict_invalid_pointee) + << EltTy << DS.getSourceRange(); + TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier. + } + } else { + S.Diag(DS.getRestrictSpecLoc(), + diag::err_typecheck_invalid_restrict_not_pointer) + << Result << DS.getSourceRange(); + TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier. + } + } + + // Warn about CV qualifiers on functions: C99 6.7.3p8: "If the specification + // of a function type includes any type qualifiers, the behavior is + // undefined." + if (Result->isFunctionType() && TypeQuals) { + // Get some location to point at, either the C or V location. + SourceLocation Loc; + if (TypeQuals & DeclSpec::TQ_const) + Loc = DS.getConstSpecLoc(); + else if (TypeQuals & DeclSpec::TQ_volatile) + Loc = DS.getVolatileSpecLoc(); + else { + assert((TypeQuals & DeclSpec::TQ_restrict) && + "Has CVR quals but not C, V, or R?"); + Loc = DS.getRestrictSpecLoc(); + } + S.Diag(Loc, diag::warn_typecheck_function_qualifiers) + << Result << DS.getSourceRange(); + } + + // C++ [dcl.ref]p1: + // Cv-qualified references are ill-formed except when the + // cv-qualifiers are introduced through the use of a typedef + // (7.1.3) or of a template type argument (14.3), in which + // case the cv-qualifiers are ignored. + // FIXME: Shouldn't we be checking SCS_typedef here? + if (DS.getTypeSpecType() == DeclSpec::TST_typename && + TypeQuals && Result->isReferenceType()) { + TypeQuals &= ~DeclSpec::TQ_const; + TypeQuals &= ~DeclSpec::TQ_volatile; + } + + Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals); + Result = Context.getQualifiedType(Result, Quals); + } + + return Result; +} + +static std::string getPrintableNameForEntity(DeclarationName Entity) { + if (Entity) + return Entity.getAsString(); + + return "type name"; +} + +QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, + Qualifiers Qs) { + // Enforce C99 6.7.3p2: "Types other than pointer types derived from + // object or incomplete types shall not be restrict-qualified." + if (Qs.hasRestrict()) { + unsigned DiagID = 0; + QualType ProblemTy; + + const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); + if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) { + if (!RTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs<ReferenceType>()->getPointeeType(); + } + } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) { + if (!PTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs<PointerType>()->getPointeeType(); + } + } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) { + if (!PTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs<PointerType>()->getPointeeType(); + } + } else if (!Ty->isDependentType()) { + // FIXME: this deserves a proper diagnostic + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T; + } + + if (DiagID) { + Diag(Loc, DiagID) << ProblemTy; + Qs.removeRestrict(); + } + } + + return Context.getQualifiedType(T, Qs); +} + +/// \brief Build a paren type including \p T. +QualType Sema::BuildParenType(QualType T) { + return Context.getParenType(T); +} + +/// \brief Build a pointer type. +/// +/// \param T The type to which we'll be building a pointer. +/// +/// \param Loc The location of the entity whose type involves this +/// pointer type or, if there is no such entity, the location of the +/// type that will have pointer type. +/// +/// \param Entity The name of the entity that involves the pointer +/// type, if known. +/// +/// \returns A suitable pointer type, if there are no +/// errors. Otherwise, returns a NULL type. +QualType Sema::BuildPointerType(QualType T, + SourceLocation Loc, DeclarationName Entity) { + if (T->isReferenceType()) { + // C++ 8.3.2p4: There shall be no ... pointers to references ... + Diag(Loc, diag::err_illegal_decl_pointer_to_reference) + << getPrintableNameForEntity(Entity) << T; + return QualType(); + } + + assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType"); + + // Build the pointer type. + return Context.getPointerType(T); +} + +/// \brief Build a reference type. +/// +/// \param T The type to which we'll be building a reference. +/// +/// \param Loc The location of the entity whose type involves this +/// reference type or, if there is no such entity, the location of the +/// type that will have reference type. +/// +/// \param Entity The name of the entity that involves the reference +/// type, if known. +/// +/// \returns A suitable reference type, if there are no +/// errors. Otherwise, returns a NULL type. +QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, + SourceLocation Loc, + DeclarationName Entity) { + assert(Context.getCanonicalType(T) != Context.OverloadTy && + "Unresolved overloaded function type"); + + // C++0x [dcl.ref]p6: + // If a typedef (7.1.3), a type template-parameter (14.3.1), or a + // decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a + // type T, an attempt to create the type "lvalue reference to cv TR" creates + // the type "lvalue reference to T", while an attempt to create the type + // "rvalue reference to cv TR" creates the type TR. + bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>(); + + // C++ [dcl.ref]p4: There shall be no references to references. + // + // According to C++ DR 106, references to references are only + // diagnosed when they are written directly (e.g., "int & &"), + // but not when they happen via a typedef: + // + // typedef int& intref; + // typedef intref& intref2; + // + // Parser::ParseDeclaratorInternal diagnoses the case where + // references are written directly; here, we handle the + // collapsing of references-to-references as described in C++0x. + // DR 106 and 540 introduce reference-collapsing into C++98/03. + + // C++ [dcl.ref]p1: + // A declarator that specifies the type "reference to cv void" + // is ill-formed. + if (T->isVoidType()) { + Diag(Loc, diag::err_reference_to_void); + return QualType(); + } + + // Handle restrict on references. + if (LValueRef) + return Context.getLValueReferenceType(T, SpelledAsLValue); + return Context.getRValueReferenceType(T); +} + +/// \brief Build an array type. +/// +/// \param T The type of each element in the array. +/// +/// \param ASM C99 array size modifier (e.g., '*', 'static'). +/// +/// \param ArraySize Expression describing the size of the array. +/// +/// \param Loc The location of the entity whose type involves this +/// array type or, if there is no such entity, the location of the +/// type that will have array type. +/// +/// \param Entity The name of the entity that involves the array +/// type, if known. +/// +/// \returns A suitable array type, if there are no errors. Otherwise, +/// returns a NULL type. +QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, + Expr *ArraySize, unsigned Quals, + SourceRange Brackets, DeclarationName Entity) { + + SourceLocation Loc = Brackets.getBegin(); + if (getLangOptions().CPlusPlus) { + // C++ [dcl.array]p1: + // T is called the array element type; this type shall not be a reference + // type, the (possibly cv-qualified) type void, a function type or an + // abstract class type. + // + // Note: function types are handled in the common path with C. + if (T->isReferenceType()) { + Diag(Loc, diag::err_illegal_decl_array_of_references) + << getPrintableNameForEntity(Entity) << T; + return QualType(); + } + + if (T->isVoidType()) { + Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T; + return QualType(); + } + + if (RequireNonAbstractType(Brackets.getBegin(), T, + diag::err_array_of_abstract_type)) + return QualType(); + + } else { + // C99 6.7.5.2p1: If the element type is an incomplete or function type, + // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) + if (RequireCompleteType(Loc, T, + diag::err_illegal_decl_array_incomplete_type)) + return QualType(); + } + + if (T->isFunctionType()) { + Diag(Loc, diag::err_illegal_decl_array_of_functions) + << getPrintableNameForEntity(Entity) << T; + return QualType(); + } + + if (T->getContainedAutoType()) { + Diag(Loc, diag::err_illegal_decl_array_of_auto) + << getPrintableNameForEntity(Entity) << T; + return QualType(); + } + + if (const RecordType *EltTy = T->getAs<RecordType>()) { + // If the element type is a struct or union that contains a variadic + // array, accept it as a GNU extension: C99 6.7.2.1p2. + if (EltTy->getDecl()->hasFlexibleArrayMember()) + Diag(Loc, diag::ext_flexible_array_in_array) << T; + } else if (T->isObjCObjectType()) { + Diag(Loc, diag::err_objc_array_of_interfaces) << T; + return QualType(); + } + + // Do lvalue-to-rvalue conversions on the array size expression. + if (ArraySize && !ArraySize->isRValue()) { + ExprResult Result = DefaultLvalueConversion(ArraySize); + if (Result.isInvalid()) + return QualType(); + + ArraySize = Result.take(); + } + + // C99 6.7.5.2p1: The size expression shall have integer type. + // TODO: in theory, if we were insane, we could allow contextual + // conversions to integer type here. + if (ArraySize && !ArraySize->isTypeDependent() && + !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { + Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) + << ArraySize->getType() << ArraySize->getSourceRange(); + return QualType(); + } + llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType())); + if (!ArraySize) { + if (ASM == ArrayType::Star) + T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets); + else + T = Context.getIncompleteArrayType(T, ASM, Quals); + } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) { + T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets); + } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) || + (!T->isDependentType() && !T->isIncompleteType() && + !T->isConstantSizeType())) { + // Per C99, a variable array is an array with either a non-constant + // size or an element type that has a non-constant-size + T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets); + } else { + // C99 6.7.5.2p1: If the expression is a constant expression, it shall + // have a value greater than zero. + if (ConstVal.isSigned() && ConstVal.isNegative()) { + if (Entity) + Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size) + << getPrintableNameForEntity(Entity) << ArraySize->getSourceRange(); + else + Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size) + << ArraySize->getSourceRange(); + return QualType(); + } + if (ConstVal == 0) { + // GCC accepts zero sized static arrays. We allow them when + // we're not in a SFINAE context. + Diag(ArraySize->getLocStart(), + isSFINAEContext()? diag::err_typecheck_zero_array_size + : diag::ext_typecheck_zero_array_size) + << ArraySize->getSourceRange(); + } else if (!T->isDependentType() && !T->isVariablyModifiedType() && + !T->isIncompleteType()) { + // Is the array too large? + unsigned ActiveSizeBits + = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal); + if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) + Diag(ArraySize->getLocStart(), diag::err_array_too_large) + << ConstVal.toString(10) + << ArraySize->getSourceRange(); + } + + T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); + } + // If this is not C99, extwarn about VLA's and C99 array size modifiers. + if (!getLangOptions().C99) { + if (T->isVariableArrayType()) { + // Prohibit the use of non-POD types in VLAs. + if (!T->isDependentType() && + !Context.getBaseElementType(T)->isPODType()) { + Diag(Loc, diag::err_vla_non_pod) + << Context.getBaseElementType(T); + return QualType(); + } + // Prohibit the use of VLAs during template argument deduction. + else if (isSFINAEContext()) { + Diag(Loc, diag::err_vla_in_sfinae); + return QualType(); + } + // Just extwarn about VLAs. + else + Diag(Loc, diag::ext_vla); + } else if (ASM != ArrayType::Normal || Quals != 0) + Diag(Loc, + getLangOptions().CPlusPlus? diag::err_c99_array_usage_cxx + : diag::ext_c99_array_usage); + } + + return T; +} + +/// \brief Build an ext-vector type. +/// +/// Run the required checks for the extended vector type. +QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, + SourceLocation AttrLoc) { + // unlike gcc's vector_size attribute, we do not allow vectors to be defined + // in conjunction with complex types (pointers, arrays, functions, etc.). + if (!T->isDependentType() && + !T->isIntegerType() && !T->isRealFloatingType()) { + Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T; + return QualType(); + } + + if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) { + llvm::APSInt vecSize(32); + if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_not_int) + << "ext_vector_type" << ArraySize->getSourceRange(); + return QualType(); + } + + // unlike gcc's vector_size attribute, the size is specified as the + // number of elements, not the number of bytes. + unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); + + if (vectorSize == 0) { + Diag(AttrLoc, diag::err_attribute_zero_size) + << ArraySize->getSourceRange(); + return QualType(); + } + + if (!T->isDependentType()) + return Context.getExtVectorType(T, vectorSize); + } + + return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc); +} + +/// \brief Build a function type. +/// +/// This routine checks the function type according to C++ rules and +/// under the assumption that the result type and parameter types have +/// just been instantiated from a template. It therefore duplicates +/// some of the behavior of GetTypeForDeclarator, but in a much +/// simpler form that is only suitable for this narrow use case. +/// +/// \param T The return type of the function. +/// +/// \param ParamTypes The parameter types of the function. This array +/// will be modified to account for adjustments to the types of the +/// function parameters. +/// +/// \param NumParamTypes The number of parameter types in ParamTypes. +/// +/// \param Variadic Whether this is a variadic function type. +/// +/// \param Quals The cvr-qualifiers to be applied to the function type. +/// +/// \param Loc The location of the entity whose type involves this +/// function type or, if there is no such entity, the location of the +/// type that will have function type. +/// +/// \param Entity The name of the entity that involves the function +/// type, if known. +/// +/// \returns A suitable function type, if there are no +/// errors. Otherwise, returns a NULL type. +QualType Sema::BuildFunctionType(QualType T, + QualType *ParamTypes, + unsigned NumParamTypes, + bool Variadic, unsigned Quals, + RefQualifierKind RefQualifier, + SourceLocation Loc, DeclarationName Entity, + FunctionType::ExtInfo Info) { + if (T->isArrayType() || T->isFunctionType()) { + Diag(Loc, diag::err_func_returning_array_function) + << T->isFunctionType() << T; + return QualType(); + } + + bool Invalid = false; + for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) { + QualType ParamType = adjustParameterType(ParamTypes[Idx]); + if (ParamType->isVoidType()) { + Diag(Loc, diag::err_param_with_void_type); + Invalid = true; + } + + ParamTypes[Idx] = ParamType; + } + + if (Invalid) + return QualType(); + + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = Variadic; + EPI.TypeQuals = Quals; + EPI.RefQualifier = RefQualifier; + EPI.ExtInfo = Info; + + return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI); +} + +/// \brief Build a member pointer type \c T Class::*. +/// +/// \param T the type to which the member pointer refers. +/// \param Class the class type into which the member pointer points. +/// \param CVR Qualifiers applied to the member pointer type +/// \param Loc the location where this type begins +/// \param Entity the name of the entity that will have this member pointer type +/// +/// \returns a member pointer type, if successful, or a NULL type if there was +/// an error. +QualType Sema::BuildMemberPointerType(QualType T, QualType Class, + SourceLocation Loc, + DeclarationName Entity) { + // Verify that we're not building a pointer to pointer to function with + // exception specification. + if (CheckDistantExceptionSpec(T)) { + Diag(Loc, diag::err_distant_exception_spec); + + // FIXME: If we're doing this as part of template instantiation, + // we should return immediately. + + // Build the type anyway, but use the canonical type so that the + // exception specifiers are stripped off. + T = Context.getCanonicalType(T); + } + + // C++ 8.3.3p3: A pointer to member shall not point to ... a member + // with reference type, or "cv void." + if (T->isReferenceType()) { + Diag(Loc, diag::err_illegal_decl_mempointer_to_reference) + << (Entity? Entity.getAsString() : "type name") << T; + return QualType(); + } + + if (T->isVoidType()) { + Diag(Loc, diag::err_illegal_decl_mempointer_to_void) + << (Entity? Entity.getAsString() : "type name"); + return QualType(); + } + + if (!Class->isDependentType() && !Class->isRecordType()) { + Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class; + return QualType(); + } + + // In the Microsoft ABI, the class is allowed to be an incomplete + // type. In such cases, the compiler makes a worst-case assumption. + // We make no such assumption right now, so emit an error if the + // class isn't a complete type. + if (Context.Target.getCXXABI() == CXXABI_Microsoft && + RequireCompleteType(Loc, Class, diag::err_incomplete_type)) + return QualType(); + + return Context.getMemberPointerType(T, Class.getTypePtr()); +} + +/// \brief Build a block pointer type. +/// +/// \param T The type to which we'll be building a block pointer. +/// +/// \param CVR The cvr-qualifiers to be applied to the block pointer type. +/// +/// \param Loc The location of the entity whose type involves this +/// block pointer type or, if there is no such entity, the location of the +/// type that will have block pointer type. +/// +/// \param Entity The name of the entity that involves the block pointer +/// type, if known. +/// +/// \returns A suitable block pointer type, if there are no +/// errors. Otherwise, returns a NULL type. +QualType Sema::BuildBlockPointerType(QualType T, + SourceLocation Loc, + DeclarationName Entity) { + if (!T->isFunctionType()) { + Diag(Loc, diag::err_nonfunction_block_type); + return QualType(); + } + + return Context.getBlockPointerType(T); +} + +QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) { + QualType QT = Ty.get(); + if (QT.isNull()) { + if (TInfo) *TInfo = 0; + return QualType(); + } + + TypeSourceInfo *DI = 0; + if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) { + QT = LIT->getType(); + DI = LIT->getTypeSourceInfo(); + } + + if (TInfo) *TInfo = DI; + return QT; +} + +static void DiagnoseIgnoredQualifiers(unsigned Quals, + SourceLocation ConstQualLoc, + SourceLocation VolatileQualLoc, + SourceLocation RestrictQualLoc, + Sema& S) { + std::string QualStr; + unsigned NumQuals = 0; + SourceLocation Loc; + + FixItHint ConstFixIt; + FixItHint VolatileFixIt; + FixItHint RestrictFixIt; + + const SourceManager &SM = S.getSourceManager(); + + // FIXME: The locations here are set kind of arbitrarily. It'd be nicer to + // find a range and grow it to encompass all the qualifiers, regardless of + // the order in which they textually appear. + if (Quals & Qualifiers::Const) { + ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc); + QualStr = "const"; + ++NumQuals; + if (!Loc.isValid() || SM.isBeforeInTranslationUnit(ConstQualLoc, Loc)) + Loc = ConstQualLoc; + } + if (Quals & Qualifiers::Volatile) { + VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc); + QualStr += (NumQuals == 0 ? "volatile" : " volatile"); + ++NumQuals; + if (!Loc.isValid() || SM.isBeforeInTranslationUnit(VolatileQualLoc, Loc)) + Loc = VolatileQualLoc; + } + if (Quals & Qualifiers::Restrict) { + RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc); + QualStr += (NumQuals == 0 ? "restrict" : " restrict"); + ++NumQuals; + if (!Loc.isValid() || SM.isBeforeInTranslationUnit(RestrictQualLoc, Loc)) + Loc = RestrictQualLoc; + } + + assert(NumQuals > 0 && "No known qualifiers?"); + + S.Diag(Loc, diag::warn_qual_return_type) + << QualStr << NumQuals << ConstFixIt << VolatileFixIt << RestrictFixIt; +} + +/// GetTypeForDeclarator - Convert the type for the specified +/// declarator to Type instances. +/// +/// If OwnedDecl is non-NULL, and this declarator's decl-specifier-seq +/// owns the declaration of a type (e.g., the definition of a struct +/// type), then *OwnedDecl will receive the owned declaration. +/// +/// The result of this call will never be null, but the associated +/// type may be a null type if there's an unrecoverable error. +TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, + TagDecl **OwnedDecl, + bool AutoAllowedInTypeName) { + // Determine the type of the declarator. Not all forms of declarator + // have a type. + QualType T; + TypeSourceInfo *ReturnTypeInfo = 0; + + TypeProcessingState state(*this, D); + + // In C++0x, deallocation functions (normal and array operator delete) + // are implicitly noexcept. + bool ImplicitlyNoexcept = false; + + switch (D.getName().getKind()) { + case UnqualifiedId::IK_OperatorFunctionId: + if (getLangOptions().CPlusPlus0x) { + OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator; + if (OO == OO_Delete || OO == OO_Array_Delete) + ImplicitlyNoexcept = true; + } + // Intentional fall-through. + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedId::IK_TemplateId: + T = ConvertDeclSpecToType(*this, state); + + if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) { + TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); + // Owned declaration is embedded in declarator. + Owned->setEmbeddedInDeclarator(true); + if (OwnedDecl) *OwnedDecl = Owned; + } + break; + + case UnqualifiedId::IK_ConstructorName: + case UnqualifiedId::IK_ConstructorTemplateId: + case UnqualifiedId::IK_DestructorName: + // Constructors and destructors don't have return types. Use + // "void" instead. + T = Context.VoidTy; + break; + + case UnqualifiedId::IK_ConversionFunctionId: + // The result type of a conversion function is the type that it + // converts to. + T = GetTypeFromParser(D.getName().ConversionFunctionId, + &ReturnTypeInfo); + break; + } + + if (D.getAttributes()) + distributeTypeAttrsFromDeclarator(state, T); + + // C++0x [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. + // In C++0x, a function declarator using 'auto' must have a trailing return + // type (this is checked later) and we can skip this. In other languages + // using auto, we need to check regardless. + if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && + (!getLangOptions().CPlusPlus0x || !D.isFunctionDeclarator())) { + int Error = -1; + + switch (D.getContext()) { + case Declarator::KNRTypeListContext: + assert(0 && "K&R type lists aren't allowed in C++"); + break; + case Declarator::ObjCPrototypeContext: + case Declarator::PrototypeContext: + Error = 0; // Function prototype + break; + case Declarator::MemberContext: + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static) + break; + switch (cast<TagDecl>(CurContext)->getTagKind()) { + case TTK_Enum: assert(0 && "unhandled tag kind"); break; + case TTK_Struct: Error = 1; /* Struct member */ break; + case TTK_Union: Error = 2; /* Union member */ break; + case TTK_Class: Error = 3; /* Class member */ break; + } + break; + case Declarator::CXXCatchContext: + Error = 4; // Exception declaration + break; + case Declarator::TemplateParamContext: + Error = 5; // Template parameter + break; + case Declarator::BlockLiteralContext: + Error = 6; // Block literal + break; + case Declarator::TemplateTypeArgContext: + Error = 7; // Template type argument + break; + case Declarator::AliasDeclContext: + case Declarator::AliasTemplateContext: + Error = 9; // Type alias + break; + case Declarator::TypeNameContext: + if (!AutoAllowedInTypeName) + Error = 11; // Generic + break; + case Declarator::FileContext: + case Declarator::BlockContext: + case Declarator::ForContext: + case Declarator::ConditionContext: + break; + } + + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + Error = 8; + + // In Objective-C it is an error to use 'auto' on a function declarator. + if (D.isFunctionDeclarator()) + Error = 10; + + // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator + // contains a trailing return type. That is only legal at the outermost + // level. Check all declarator chunks (outermost first) anyway, to give + // better diagnostics. + if (getLangOptions().CPlusPlus0x && Error != -1) { + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + unsigned chunkIndex = e - i - 1; + state.setCurrentChunkIndex(chunkIndex); + DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); + if (DeclType.Kind == DeclaratorChunk::Function) { + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + if (FTI.TrailingReturnType) { + Error = -1; + break; + } + } + } + } + + if (Error != -1) { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed) + << Error; + T = Context.IntTy; + D.setInvalidType(true); + } + } + + if (T.isNull()) + return Context.getNullTypeSourceInfo(); + + // The name we're declaring, if any. + DeclarationName Name; + if (D.getIdentifier()) + Name = D.getIdentifier(); + + // Does this declaration declare a typedef-name? + bool IsTypedefName = + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef || + D.getContext() == Declarator::AliasDeclContext || + D.getContext() == Declarator::AliasTemplateContext; + + // Walk the DeclTypeInfo, building the recursive type as we go. + // DeclTypeInfos are ordered from the identifier out, which is + // opposite of what we want :). + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + unsigned chunkIndex = e - i - 1; + state.setCurrentChunkIndex(chunkIndex); + DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); + switch (DeclType.Kind) { + default: assert(0 && "Unknown decltype!"); + case DeclaratorChunk::Paren: + T = BuildParenType(T); + break; + case DeclaratorChunk::BlockPointer: + // If blocks are disabled, emit an error. + if (!LangOpts.Blocks) + Diag(DeclType.Loc, diag::err_blocks_disable); + + T = BuildBlockPointerType(T, D.getIdentifierLoc(), Name); + if (DeclType.Cls.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals); + break; + case DeclaratorChunk::Pointer: + // Verify that we're not building a pointer to pointer to function with + // exception specification. + if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { + Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec); + D.setInvalidType(true); + // Build the type anyway. + } + if (getLangOptions().ObjC1 && T->getAs<ObjCObjectType>()) { + T = Context.getObjCObjectPointerType(T); + if (DeclType.Ptr.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); + break; + } + T = BuildPointerType(T, DeclType.Loc, Name); + if (DeclType.Ptr.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); + + break; + case DeclaratorChunk::Reference: { + // Verify that we're not building a reference to pointer to function with + // exception specification. + if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { + Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec); + D.setInvalidType(true); + // Build the type anyway. + } + T = BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name); + + Qualifiers Quals; + if (DeclType.Ref.HasRestrict) + T = BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict); + break; + } + case DeclaratorChunk::Array: { + // Verify that we're not building an array of pointers to function with + // exception specification. + if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { + Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec); + D.setInvalidType(true); + // Build the type anyway. + } + DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr; + Expr *ArraySize = static_cast<Expr*>(ATI.NumElts); + ArrayType::ArraySizeModifier ASM; + if (ATI.isStar) + ASM = ArrayType::Star; + else if (ATI.hasStatic) + ASM = ArrayType::Static; + else + ASM = ArrayType::Normal; + if (ASM == ArrayType::Star && !D.isPrototypeContext()) { + // FIXME: This check isn't quite right: it allows star in prototypes + // for function definitions, and disallows some edge cases detailed + // in http://gcc.gnu.org/ml/gcc-patches/2009-02/msg00133.html + Diag(DeclType.Loc, diag::err_array_star_outside_prototype); + ASM = ArrayType::Normal; + D.setInvalidType(true); + } + T = BuildArrayType(T, ASM, ArraySize, + Qualifiers::fromCVRMask(ATI.TypeQuals), + SourceRange(DeclType.Loc, DeclType.EndLoc), Name); + break; + } + case DeclaratorChunk::Function: { + // If the function declarator has a prototype (i.e. it is not () and + // does not have a K&R-style identifier list), then the arguments are part + // of the type, otherwise the argument list is (). + const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; + + // Check for auto functions and trailing return type and adjust the + // return type accordingly. + if (!D.isInvalidType()) { + // trailing-return-type is only required if we're declaring a function, + // and not, for instance, a pointer to a function. + if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto && + !FTI.TrailingReturnType && chunkIndex == 0) { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_auto_missing_trailing_return); + T = Context.IntTy; + D.setInvalidType(true); + } else if (FTI.TrailingReturnType) { + // T must be exactly 'auto' at this point. See CWG issue 681. + if (isa<ParenType>(T)) { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_trailing_return_in_parens) + << T << D.getDeclSpec().getSourceRange(); + D.setInvalidType(true); + } else if (T.hasQualifiers() || !isa<AutoType>(T)) { + Diag(D.getDeclSpec().getTypeSpecTypeLoc(), + diag::err_trailing_return_without_auto) + << T << D.getDeclSpec().getSourceRange(); + D.setInvalidType(true); + } + + T = GetTypeFromParser( + ParsedType::getFromOpaquePtr(FTI.TrailingReturnType), + &ReturnTypeInfo); + } + } + + // C99 6.7.5.3p1: The return type may not be a function or array type. + // For conversion functions, we'll diagnose this particular error later. + if ((T->isArrayType() || T->isFunctionType()) && + (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) { + unsigned diagID = diag::err_func_returning_array_function; + // Last processing chunk in block context means this function chunk + // represents the block. + if (chunkIndex == 0 && + D.getContext() == Declarator::BlockLiteralContext) + diagID = diag::err_block_returning_array_function; + Diag(DeclType.Loc, diagID) << T->isFunctionType() << T; + T = Context.IntTy; + D.setInvalidType(true); + } + + // cv-qualifiers on return types are pointless except when the type is a + // class type in C++. + if (isa<PointerType>(T) && T.getLocalCVRQualifiers() && + (D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) && + (!getLangOptions().CPlusPlus || !T->isDependentType())) { + assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?"); + DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); + assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer); + + DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr; + + DiagnoseIgnoredQualifiers(PTI.TypeQuals, + SourceLocation::getFromRawEncoding(PTI.ConstQualLoc), + SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc), + SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc), + *this); + + } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() && + (!getLangOptions().CPlusPlus || + (!T->isDependentType() && !T->isRecordType()))) { + + DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(), + D.getDeclSpec().getConstSpecLoc(), + D.getDeclSpec().getVolatileSpecLoc(), + D.getDeclSpec().getRestrictSpecLoc(), + *this); + } + + if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) { + // C++ [dcl.fct]p6: + // Types shall not be defined in return or parameter types. + TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); + if (Tag->isDefinition()) + Diag(Tag->getLocation(), diag::err_type_defined_in_result_type) + << Context.getTypeDeclType(Tag); + } + + // Exception specs are not allowed in typedefs. Complain, but add it + // anyway. + if (IsTypedefName && FTI.getExceptionSpecType()) + Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef) + << (D.getContext() == Declarator::AliasDeclContext || + D.getContext() == Declarator::AliasTemplateContext); + + if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) { + // Simple void foo(), where the incoming T is the result type. + T = Context.getFunctionNoProtoType(T); + } else { + // We allow a zero-parameter variadic function in C if the + // function is marked with the "overloadable" attribute. Scan + // for this attribute now. + if (!FTI.NumArgs && FTI.isVariadic && !getLangOptions().CPlusPlus) { + bool Overloadable = false; + for (const AttributeList *Attrs = D.getAttributes(); + Attrs; Attrs = Attrs->getNext()) { + if (Attrs->getKind() == AttributeList::AT_overloadable) { + Overloadable = true; + break; + } + } + + if (!Overloadable) + Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg); + } + + if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) { + // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function + // definition. + Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); + D.setInvalidType(true); + break; + } + + FunctionProtoType::ExtProtoInfo EPI; + EPI.Variadic = FTI.isVariadic; + EPI.TypeQuals = FTI.TypeQuals; + EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None + : FTI.RefQualifierIsLValueRef? RQ_LValue + : RQ_RValue; + + // Otherwise, we have a function with an argument list that is + // potentially variadic. + llvm::SmallVector<QualType, 16> ArgTys; + ArgTys.reserve(FTI.NumArgs); + + for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { + ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param); + QualType ArgTy = Param->getType(); + assert(!ArgTy.isNull() && "Couldn't parse type?"); + + // Adjust the parameter type. + assert((ArgTy == adjustParameterType(ArgTy)) && "Unadjusted type?"); + + // Look for 'void'. void is allowed only as a single argument to a + // function with no other parameters (C99 6.7.5.3p10). We record + // int(void) as a FunctionProtoType with an empty argument list. + if (ArgTy->isVoidType()) { + // If this is something like 'float(int, void)', reject it. 'void' + // is an incomplete type (C99 6.2.5p19) and function decls cannot + // have arguments of incomplete type. + if (FTI.NumArgs != 1 || FTI.isVariadic) { + Diag(DeclType.Loc, diag::err_void_only_param); + ArgTy = Context.IntTy; + Param->setType(ArgTy); + } else if (FTI.ArgInfo[i].Ident) { + // Reject, but continue to parse 'int(void abc)'. + Diag(FTI.ArgInfo[i].IdentLoc, + diag::err_param_with_void_type); + ArgTy = Context.IntTy; + Param->setType(ArgTy); + } else { + // Reject, but continue to parse 'float(const void)'. + if (ArgTy.hasQualifiers()) + Diag(DeclType.Loc, diag::err_void_param_qualified); + + // Do not add 'void' to the ArgTys list. + break; + } + } else if (!FTI.hasPrototype) { + if (ArgTy->isPromotableIntegerType()) { + ArgTy = Context.getPromotedIntegerType(ArgTy); + Param->setKNRPromoted(true); + } else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) { + if (BTy->getKind() == BuiltinType::Float) { + ArgTy = Context.DoubleTy; + Param->setKNRPromoted(true); + } + } + } + + ArgTys.push_back(ArgTy); + } + + llvm::SmallVector<QualType, 4> Exceptions; + EPI.ExceptionSpecType = FTI.getExceptionSpecType(); + if (FTI.getExceptionSpecType() == EST_Dynamic) { + Exceptions.reserve(FTI.NumExceptions); + for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { + // FIXME: Preserve type source info. + QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty); + // Check that the type is valid for an exception spec, and + // drop it if not. + if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range)) + Exceptions.push_back(ET); + } + EPI.NumExceptions = Exceptions.size(); + EPI.Exceptions = Exceptions.data(); + } else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) { + // If an error occurred, there's no expression here. + if (Expr *NoexceptExpr = FTI.NoexceptExpr) { + assert((NoexceptExpr->isTypeDependent() || + NoexceptExpr->getType()->getCanonicalTypeUnqualified() == + Context.BoolTy) && + "Parser should have made sure that the expression is boolean"); + SourceLocation ErrLoc; + llvm::APSInt Dummy; + if (!NoexceptExpr->isValueDependent() && + !NoexceptExpr->isIntegerConstantExpr(Dummy, Context, &ErrLoc, + /*evaluated*/false)) + Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) + << NoexceptExpr->getSourceRange(); + else + EPI.NoexceptExpr = NoexceptExpr; + } + } else if (FTI.getExceptionSpecType() == EST_None && + ImplicitlyNoexcept && chunkIndex == 0) { + // Only the outermost chunk is marked noexcept, of course. + EPI.ExceptionSpecType = EST_BasicNoexcept; + } + + T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI); + } + + break; + } + case DeclaratorChunk::MemberPointer: + // The scope spec must refer to a class, or be dependent. + CXXScopeSpec &SS = DeclType.Mem.Scope(); + QualType ClsType; + if (SS.isInvalid()) { + // Avoid emitting extra errors if we already errored on the scope. + D.setInvalidType(true); + } else if (isDependentScopeSpecifier(SS) || + dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS))) { + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + NestedNameSpecifier *NNSPrefix = NNS->getPrefix(); + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + ClsType = Context.getDependentNameType(ETK_None, NNSPrefix, + NNS->getAsIdentifier()); + break; + + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + llvm_unreachable("Nested-name-specifier must name a type"); + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + ClsType = QualType(NNS->getAsType(), 0); + // Note: if the NNS has a prefix and ClsType is a nondependent + // TemplateSpecializationType, then the NNS prefix is NOT included + // in ClsType; hence we wrap ClsType into an ElaboratedType. + // NOTE: in particular, no wrap occurs if ClsType already is an + // Elaborated, DependentName, or DependentTemplateSpecialization. + if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType())) + ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType); + break; + } + } else { + Diag(DeclType.Mem.Scope().getBeginLoc(), + diag::err_illegal_decl_mempointer_in_nonclass) + << (D.getIdentifier() ? D.getIdentifier()->getName() : "type name") + << DeclType.Mem.Scope().getRange(); + D.setInvalidType(true); + } + + if (!ClsType.isNull()) + T = BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier()); + if (T.isNull()) { + T = Context.IntTy; + D.setInvalidType(true); + } else if (DeclType.Mem.TypeQuals) { + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals); + } + break; + } + + if (T.isNull()) { + D.setInvalidType(true); + T = Context.IntTy; + } + + // See if there are any attributes on this declarator chunk. + if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs())) + processTypeAttrs(state, T, false, attrs); + } + + if (getLangOptions().CPlusPlus && T->isFunctionType()) { + const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>(); + assert(FnTy && "Why oh why is there not a FunctionProtoType here?"); + + // C++ 8.3.5p4: + // A cv-qualifier-seq shall only be part of the function type + // for a nonstatic member function, the function type to which a pointer + // to member refers, or the top-level function type of a function typedef + // declaration. + // + // Core issue 547 also allows cv-qualifiers on function types that are + // top-level template type arguments. + bool FreeFunction; + if (!D.getCXXScopeSpec().isSet()) { + FreeFunction = (D.getContext() != Declarator::MemberContext || + D.getDeclSpec().isFriendSpecified()); + } else { + DeclContext *DC = computeDeclContext(D.getCXXScopeSpec()); + FreeFunction = (DC && !DC->isRecord()); + } + + // C++0x [dcl.fct]p6: + // A ref-qualifier shall only be part of the function type for a + // non-static member function, the function type to which a pointer to + // member refers, or the top-level function type of a function typedef + // declaration. + if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) && + !(D.getContext() == Declarator::TemplateTypeArgContext && + !D.isFunctionDeclarator()) && !IsTypedefName && + (FreeFunction || + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) { + if (D.getContext() == Declarator::TemplateTypeArgContext) { + // Accept qualified function types as template type arguments as a GNU + // extension. This is also the subject of C++ core issue 547. + std::string Quals; + if (FnTy->getTypeQuals() != 0) + Quals = Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString(); + + switch (FnTy->getRefQualifier()) { + case RQ_None: + break; + + case RQ_LValue: + if (!Quals.empty()) + Quals += ' '; + Quals += '&'; + break; + + case RQ_RValue: + if (!Quals.empty()) + Quals += ' '; + Quals += "&&"; + break; + } + + Diag(D.getIdentifierLoc(), + diag::ext_qualified_function_type_template_arg) + << Quals; + } else { + if (FnTy->getTypeQuals() != 0) { + if (D.isFunctionDeclarator()) + Diag(D.getIdentifierLoc(), + diag::err_invalid_qualified_function_type); + else + Diag(D.getIdentifierLoc(), + diag::err_invalid_qualified_typedef_function_type_use) + << FreeFunction; + } + + if (FnTy->getRefQualifier()) { + if (D.isFunctionDeclarator()) { + SourceLocation Loc = D.getIdentifierLoc(); + for (unsigned I = 0, N = D.getNumTypeObjects(); I != N; ++I) { + const DeclaratorChunk &Chunk = D.getTypeObject(N-I-1); + if (Chunk.Kind == DeclaratorChunk::Function && + Chunk.Fun.hasRefQualifier()) { + Loc = Chunk.Fun.getRefQualifierLoc(); + break; + } + } + + Diag(Loc, diag::err_invalid_ref_qualifier_function_type) + << (FnTy->getRefQualifier() == RQ_LValue) + << FixItHint::CreateRemoval(Loc); + } else { + Diag(D.getIdentifierLoc(), + diag::err_invalid_ref_qualifier_typedef_function_type_use) + << FreeFunction + << (FnTy->getRefQualifier() == RQ_LValue); + } + } + + // Strip the cv-qualifiers and ref-qualifiers from the type. + FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); + EPI.TypeQuals = 0; + EPI.RefQualifier = RQ_None; + + T = Context.getFunctionType(FnTy->getResultType(), + FnTy->arg_type_begin(), + FnTy->getNumArgs(), EPI); + } + } + } + + // Apply any undistributed attributes from the declarator. + if (!T.isNull()) + if (AttributeList *attrs = D.getAttributes()) + processTypeAttrs(state, T, false, attrs); + + // Diagnose any ignored type attributes. + if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T); + + // C++0x [dcl.constexpr]p9: + // A constexpr specifier used in an object declaration declares the object + // as const. + if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) { + T.addConst(); + } + + // If there was an ellipsis in the declarator, the declaration declares a + // parameter pack whose type may be a pack expansion type. + if (D.hasEllipsis() && !T.isNull()) { + // C++0x [dcl.fct]p13: + // A declarator-id or abstract-declarator containing an ellipsis shall + // only be used in a parameter-declaration. Such a parameter-declaration + // is a parameter pack (14.5.3). [...] + switch (D.getContext()) { + case Declarator::PrototypeContext: + // C++0x [dcl.fct]p13: + // [...] When it is part of a parameter-declaration-clause, the + // parameter pack is a function parameter pack (14.5.3). The type T + // of the declarator-id of the function parameter pack shall contain + // a template parameter pack; each template parameter pack in T is + // expanded by the function parameter pack. + // + // We represent function parameter packs as function parameters whose + // type is a pack expansion. + if (!T->containsUnexpandedParameterPack()) { + Diag(D.getEllipsisLoc(), + diag::err_function_parameter_pack_without_parameter_packs) + << T << D.getSourceRange(); + D.setEllipsisLoc(SourceLocation()); + } else { + T = Context.getPackExpansionType(T, llvm::Optional<unsigned>()); + } + break; + + case Declarator::TemplateParamContext: + // C++0x [temp.param]p15: + // If a template-parameter is a [...] is a parameter-declaration that + // declares a parameter pack (8.3.5), then the template-parameter is a + // template parameter pack (14.5.3). + // + // Note: core issue 778 clarifies that, if there are any unexpanded + // parameter packs in the type of the non-type template parameter, then + // it expands those parameter packs. + if (T->containsUnexpandedParameterPack()) + T = Context.getPackExpansionType(T, llvm::Optional<unsigned>()); + else if (!getLangOptions().CPlusPlus0x) + Diag(D.getEllipsisLoc(), diag::ext_variadic_templates); + break; + + case Declarator::FileContext: + case Declarator::KNRTypeListContext: + case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here? + case Declarator::TypeNameContext: + case Declarator::AliasDeclContext: + case Declarator::AliasTemplateContext: + case Declarator::MemberContext: + case Declarator::BlockContext: + case Declarator::ForContext: + case Declarator::ConditionContext: + case Declarator::CXXCatchContext: + case Declarator::BlockLiteralContext: + case Declarator::TemplateTypeArgContext: + // FIXME: We may want to allow parameter packs in block-literal contexts + // in the future. + Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter); + D.setEllipsisLoc(SourceLocation()); + break; + } + } + + if (T.isNull()) + return Context.getNullTypeSourceInfo(); + else if (D.isInvalidType()) + return Context.getTrivialTypeSourceInfo(T); + return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo); +} + +/// Map an AttributedType::Kind to an AttributeList::Kind. +static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { + switch (kind) { + case AttributedType::attr_address_space: + return AttributeList::AT_address_space; + case AttributedType::attr_regparm: + return AttributeList::AT_regparm; + case AttributedType::attr_vector_size: + return AttributeList::AT_vector_size; + case AttributedType::attr_neon_vector_type: + return AttributeList::AT_neon_vector_type; + case AttributedType::attr_neon_polyvector_type: + return AttributeList::AT_neon_polyvector_type; + case AttributedType::attr_objc_gc: + return AttributeList::AT_objc_gc; + case AttributedType::attr_noreturn: + return AttributeList::AT_noreturn; + case AttributedType::attr_cdecl: + return AttributeList::AT_cdecl; + case AttributedType::attr_fastcall: + return AttributeList::AT_fastcall; + case AttributedType::attr_stdcall: + return AttributeList::AT_stdcall; + case AttributedType::attr_thiscall: + return AttributeList::AT_thiscall; + case AttributedType::attr_pascal: + return AttributeList::AT_pascal; + case AttributedType::attr_pcs: + return AttributeList::AT_pcs; + } + llvm_unreachable("unexpected attribute kind!"); + return AttributeList::Kind(); +} + +static void fillAttributedTypeLoc(AttributedTypeLoc TL, + const AttributeList *attrs) { + AttributedType::Kind kind = TL.getAttrKind(); + + assert(attrs && "no type attributes in the expected location!"); + AttributeList::Kind parsedKind = getAttrListKind(kind); + while (attrs->getKind() != parsedKind) { + attrs = attrs->getNext(); + assert(attrs && "no matching attribute in expected location!"); + } + + TL.setAttrNameLoc(attrs->getLoc()); + if (TL.hasAttrExprOperand()) + TL.setAttrExprOperand(attrs->getArg(0)); + else if (TL.hasAttrEnumOperand()) + TL.setAttrEnumOperandLoc(attrs->getParameterLoc()); + + // FIXME: preserve this information to here. + if (TL.hasAttrOperand()) + TL.setAttrOperandParensRange(SourceRange()); +} + +namespace { + class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> { + ASTContext &Context; + const DeclSpec &DS; + + public: + TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS) + : Context(Context), DS(DS) {} + + void VisitAttributedTypeLoc(AttributedTypeLoc TL) { + fillAttributedTypeLoc(TL, DS.getAttributes().getList()); + Visit(TL.getModifiedLoc()); + } + void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { + Visit(TL.getUnqualifiedLoc()); + } + void VisitTypedefTypeLoc(TypedefTypeLoc TL) { + TL.setNameLoc(DS.getTypeSpecTypeLoc()); + } + void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { + TL.setNameLoc(DS.getTypeSpecTypeLoc()); + } + void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { + // Handle the base type, which might not have been written explicitly. + if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { + TL.setHasBaseTypeAsWritten(false); + TL.getBaseLoc().initialize(Context, SourceLocation()); + } else { + TL.setHasBaseTypeAsWritten(true); + Visit(TL.getBaseLoc()); + } + + // Protocol qualifiers. + if (DS.getProtocolQualifiers()) { + assert(TL.getNumProtocols() > 0); + assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); + TL.setLAngleLoc(DS.getProtocolLAngleLoc()); + TL.setRAngleLoc(DS.getSourceRange().getEnd()); + for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i) + TL.setProtocolLoc(i, DS.getProtocolLocs()[i]); + } else { + assert(TL.getNumProtocols() == 0); + TL.setLAngleLoc(SourceLocation()); + TL.setRAngleLoc(SourceLocation()); + } + } + void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { + TL.setStarLoc(SourceLocation()); + Visit(TL.getPointeeLoc()); + } + void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + + // If we got no declarator info from previous Sema routines, + // just fill with the typespec loc. + if (!TInfo) { + TL.initialize(Context, DS.getTypeSpecTypeNameLoc()); + return; + } + + TypeLoc OldTL = TInfo->getTypeLoc(); + if (TInfo->getType()->getAs<ElaboratedType>()) { + ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL); + TemplateSpecializationTypeLoc NamedTL = + cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc()); + TL.copy(NamedTL); + } + else + TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL)); + } + void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { + assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr); + TL.setTypeofLoc(DS.getTypeSpecTypeLoc()); + TL.setParensRange(DS.getTypeofParensRange()); + } + void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { + assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType); + TL.setTypeofLoc(DS.getTypeSpecTypeLoc()); + TL.setParensRange(DS.getTypeofParensRange()); + assert(DS.getRepAsType()); + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + TL.setUnderlyingTInfo(TInfo); + } + void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) { + // FIXME: This holds only because we only have one unary transform. + assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType); + TL.setKWLoc(DS.getTypeSpecTypeLoc()); + TL.setParensRange(DS.getTypeofParensRange()); + assert(DS.getRepAsType()); + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + TL.setUnderlyingTInfo(TInfo); + } + void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { + // By default, use the source location of the type specifier. + TL.setBuiltinLoc(DS.getTypeSpecTypeLoc()); + if (TL.needsExtraLocalData()) { + // Set info for the written builtin specifiers. + TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs(); + // Try to have a meaningful source location. + if (TL.getWrittenSignSpec() != TSS_unspecified) + // Sign spec loc overrides the others (e.g., 'unsigned long'). + TL.setBuiltinLoc(DS.getTypeSpecSignLoc()); + else if (TL.getWrittenWidthSpec() != TSW_unspecified) + // Width spec loc overrides type spec loc (e.g., 'short int'). + TL.setBuiltinLoc(DS.getTypeSpecWidthLoc()); + } + } + void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); + if (DS.getTypeSpecType() == TST_typename) { + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc())); + return; + } + } + TL.setKeywordLoc(Keyword != ETK_None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); + const CXXScopeSpec& SS = DS.getTypeSpecScope(); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + Visit(TL.getNextTypeLoc().getUnqualifiedLoc()); + } + void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); + if (DS.getTypeSpecType() == TST_typename) { + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc())); + return; + } + } + TL.setKeywordLoc(Keyword != ETK_None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); + const CXXScopeSpec& SS = DS.getTypeSpecScope(); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); + } + void VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); + if (Keyword == ETK_Typename) { + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + if (TInfo) { + TL.copy(cast<DependentTemplateSpecializationTypeLoc>( + TInfo->getTypeLoc())); + return; + } + } + TL.initializeLocal(Context, SourceLocation()); + TL.setKeywordLoc(Keyword != ETK_None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); + const CXXScopeSpec& SS = DS.getTypeSpecScope(); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); + } + void VisitTagTypeLoc(TagTypeLoc TL) { + TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); + } + + void VisitTypeLoc(TypeLoc TL) { + // FIXME: add other typespec types and change this to an assert. + TL.initialize(Context, DS.getTypeSpecTypeLoc()); + } + }; + + class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> { + ASTContext &Context; + const DeclaratorChunk &Chunk; + + public: + DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk) + : Context(Context), Chunk(Chunk) {} + + void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { + llvm_unreachable("qualified type locs not expected here!"); + } + + void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::BlockPointer); + TL.setCaretLoc(Chunk.Loc); + } + void VisitPointerTypeLoc(PointerTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Pointer); + TL.setStarLoc(Chunk.Loc); + } + void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Pointer); + TL.setStarLoc(Chunk.Loc); + } + void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::MemberPointer); + const CXXScopeSpec& SS = Chunk.Mem.Scope(); + NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context); + + const Type* ClsTy = TL.getClass(); + QualType ClsQT = QualType(ClsTy, 0); + TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0); + // Now copy source location info into the type loc component. + TypeLoc ClsTL = ClsTInfo->getTypeLoc(); + switch (NNSLoc.getNestedNameSpecifier()->getKind()) { + case NestedNameSpecifier::Identifier: + assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc"); + { + DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL); + DNTLoc.setKeywordLoc(SourceLocation()); + DNTLoc.setQualifierLoc(NNSLoc.getPrefix()); + DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc()); + } + break; + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + if (isa<ElaboratedType>(ClsTy)) { + ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL); + ETLoc.setKeywordLoc(SourceLocation()); + ETLoc.setQualifierLoc(NNSLoc.getPrefix()); + TypeLoc NamedTL = ETLoc.getNamedTypeLoc(); + NamedTL.initializeFullCopy(NNSLoc.getTypeLoc()); + } else { + ClsTL.initializeFullCopy(NNSLoc.getTypeLoc()); + } + break; + + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + case NestedNameSpecifier::Global: + llvm_unreachable("Nested-name-specifier must name a type"); + break; + } + + // Finally fill in MemberPointerLocInfo fields. + TL.setStarLoc(Chunk.Loc); + TL.setClassTInfo(ClsTInfo); + } + void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Reference); + // 'Amp' is misleading: this might have been originally + /// spelled with AmpAmp. + TL.setAmpLoc(Chunk.Loc); + } + void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Reference); + assert(!Chunk.Ref.LValueRef); + TL.setAmpAmpLoc(Chunk.Loc); + } + void VisitArrayTypeLoc(ArrayTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Array); + TL.setLBracketLoc(Chunk.Loc); + TL.setRBracketLoc(Chunk.EndLoc); + TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts)); + } + void VisitFunctionTypeLoc(FunctionTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Function); + TL.setLocalRangeBegin(Chunk.Loc); + TL.setLocalRangeEnd(Chunk.EndLoc); + TL.setTrailingReturn(!!Chunk.Fun.TrailingReturnType); + + const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; + for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) { + ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param); + TL.setArg(tpi++, Param); + } + // FIXME: exception specs + } + void VisitParenTypeLoc(ParenTypeLoc TL) { + assert(Chunk.Kind == DeclaratorChunk::Paren); + TL.setLParenLoc(Chunk.Loc); + TL.setRParenLoc(Chunk.EndLoc); + } + + void VisitTypeLoc(TypeLoc TL) { + llvm_unreachable("unsupported TypeLoc kind in declarator!"); + } + }; +} + +/// \brief Create and instantiate a TypeSourceInfo with type source information. +/// +/// \param T QualType referring to the type as written in source code. +/// +/// \param ReturnTypeInfo For declarators whose return type does not show +/// up in the normal place in the declaration specifiers (such as a C++ +/// conversion function), this pointer will refer to a type source information +/// for that return type. +TypeSourceInfo * +Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, + TypeSourceInfo *ReturnTypeInfo) { + TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T); + UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); + + // Handle parameter packs whose type is a pack expansion. + if (isa<PackExpansionType>(T)) { + cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc()); + CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); + } + + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + while (isa<AttributedTypeLoc>(CurrTL)) { + AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs()); + CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); + } + + DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL); + CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); + } + + // If we have different source information for the return type, use + // that. This really only applies to C++ conversion functions. + if (ReturnTypeInfo) { + TypeLoc TL = ReturnTypeInfo->getTypeLoc(); + assert(TL.getFullDataSize() == CurrTL.getFullDataSize()); + memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize()); + } else { + TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL); + } + + return TInfo; +} + +/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo. +ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) { + // FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser + // and Sema during declaration parsing. Try deallocating/caching them when + // it's appropriate, instead of allocating them and keeping them around. + LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType), + TypeAlignment); + new (LocT) LocInfoType(T, TInfo); + assert(LocT->getTypeClass() != T->getTypeClass() && + "LocInfoType's TypeClass conflicts with an existing Type class"); + return ParsedType::make(QualType(LocT, 0)); +} + +void LocInfoType::getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const { + assert(false && "LocInfoType leaked into the type system; an opaque TypeTy*" + " was used directly instead of getting the QualType through" + " GetTypeFromParser"); +} + +TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { + // C99 6.7.6: Type names have no identifier. This is already validated by + // the parser. + assert(D.getIdentifier() == 0 && "Type name should have no identifier!"); + + TagDecl *OwnedTag = 0; + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag); + QualType T = TInfo->getType(); + if (D.isInvalidType()) + return true; + + if (getLangOptions().CPlusPlus) { + // Check that there are no default arguments (C++ only). + CheckExtraCXXDefaultArguments(D); + + // C++0x [dcl.type]p3: + // A type-specifier-seq shall not define a class or enumeration unless + // it appears in the type-id of an alias-declaration (7.1.3) that is not + // the declaration of a template-declaration. + if (OwnedTag && OwnedTag->isDefinition()) { + if (D.getContext() == Declarator::AliasTemplateContext) + Diag(OwnedTag->getLocation(), diag::err_type_defined_in_alias_template) + << Context.getTypeDeclType(OwnedTag); + else if (D.getContext() != Declarator::AliasDeclContext) + Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier) + << Context.getTypeDeclType(OwnedTag); + } + } + + return CreateParsedType(T, TInfo); +} + + + +//===----------------------------------------------------------------------===// +// Type Attribute Processing +//===----------------------------------------------------------------------===// + +/// HandleAddressSpaceTypeAttribute - Process an address_space attribute on the +/// specified type. The attribute contains 1 argument, the id of the address +/// space for the type. +static void HandleAddressSpaceTypeAttribute(QualType &Type, + const AttributeList &Attr, Sema &S){ + + // If this type is already address space qualified, reject it. + // Clause 6.7.3 - Type qualifiers: "No type shall be qualified by qualifiers + // for two or more different address spaces." + if (Type.getAddressSpace()) { + S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers); + Attr.setInvalid(); + return; + } + + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0)); + llvm::APSInt addrSpace(32); + if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() || + !ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int) + << ASArgExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + + // Bounds checking. + if (addrSpace.isSigned()) { + if (addrSpace.isNegative()) { + S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative) + << ASArgExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + addrSpace.setIsSigned(false); + } + llvm::APSInt max(addrSpace.getBitWidth()); + max = Qualifiers::MaxAddressSpace; + if (addrSpace > max) { + S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high) + << Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + + unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue()); + Type = S.Context.getAddrSpaceQualType(Type, ASIdx); +} + +/// handleObjCGCTypeAttr - Process the __attribute__((objc_gc)) type +/// attribute on the specified type. Returns true to indicate that +/// the attribute was handled, false to indicate that the type does +/// not permit the attribute. +static bool handleObjCGCTypeAttr(TypeProcessingState &state, + AttributeList &attr, + QualType &type) { + Sema &S = state.getSema(); + + // Delay if this isn't some kind of pointer. + if (!type->isPointerType() && + !type->isObjCObjectPointerType() && + !type->isBlockPointerType()) + return false; + + if (type.getObjCGCAttr() != Qualifiers::GCNone) { + S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc); + attr.setInvalid(); + return true; + } + + // Check the attribute arguments. + if (!attr.getParameterName()) { + S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string) + << "objc_gc" << 1; + attr.setInvalid(); + return true; + } + Qualifiers::GC GCAttr; + if (attr.getNumArgs() != 0) { + S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + attr.setInvalid(); + return true; + } + if (attr.getParameterName()->isStr("weak")) + GCAttr = Qualifiers::Weak; + else if (attr.getParameterName()->isStr("strong")) + GCAttr = Qualifiers::Strong; + else { + S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported) + << "objc_gc" << attr.getParameterName(); + attr.setInvalid(); + return true; + } + + QualType origType = type; + type = S.Context.getObjCGCQualType(origType, GCAttr); + + // Make an attributed type to preserve the source information. + if (attr.getLoc().isValid()) + type = S.Context.getAttributedType(AttributedType::attr_objc_gc, + origType, type); + + return true; +} + +namespace { + /// A helper class to unwrap a type down to a function for the + /// purposes of applying attributes there. + /// + /// Use: + /// FunctionTypeUnwrapper unwrapped(SemaRef, T); + /// if (unwrapped.isFunctionType()) { + /// const FunctionType *fn = unwrapped.get(); + /// // change fn somehow + /// T = unwrapped.wrap(fn); + /// } + struct FunctionTypeUnwrapper { + enum WrapKind { + Desugar, + Parens, + Pointer, + BlockPointer, + Reference, + MemberPointer + }; + + QualType Original; + const FunctionType *Fn; + llvm::SmallVector<unsigned char /*WrapKind*/, 8> Stack; + + FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) { + while (true) { + const Type *Ty = T.getTypePtr(); + if (isa<FunctionType>(Ty)) { + Fn = cast<FunctionType>(Ty); + return; + } else if (isa<ParenType>(Ty)) { + T = cast<ParenType>(Ty)->getInnerType(); + Stack.push_back(Parens); + } else if (isa<PointerType>(Ty)) { + T = cast<PointerType>(Ty)->getPointeeType(); + Stack.push_back(Pointer); + } else if (isa<BlockPointerType>(Ty)) { + T = cast<BlockPointerType>(Ty)->getPointeeType(); + Stack.push_back(BlockPointer); + } else if (isa<MemberPointerType>(Ty)) { + T = cast<MemberPointerType>(Ty)->getPointeeType(); + Stack.push_back(MemberPointer); + } else if (isa<ReferenceType>(Ty)) { + T = cast<ReferenceType>(Ty)->getPointeeType(); + Stack.push_back(Reference); + } else { + const Type *DTy = Ty->getUnqualifiedDesugaredType(); + if (Ty == DTy) { + Fn = 0; + return; + } + + T = QualType(DTy, 0); + Stack.push_back(Desugar); + } + } + } + + bool isFunctionType() const { return (Fn != 0); } + const FunctionType *get() const { return Fn; } + + QualType wrap(Sema &S, const FunctionType *New) { + // If T wasn't modified from the unwrapped type, do nothing. + if (New == get()) return Original; + + Fn = New; + return wrap(S.Context, Original, 0); + } + + private: + QualType wrap(ASTContext &C, QualType Old, unsigned I) { + if (I == Stack.size()) + return C.getQualifiedType(Fn, Old.getQualifiers()); + + // Build up the inner type, applying the qualifiers from the old + // type to the new type. + SplitQualType SplitOld = Old.split(); + + // As a special case, tail-recurse if there are no qualifiers. + if (SplitOld.second.empty()) + return wrap(C, SplitOld.first, I); + return C.getQualifiedType(wrap(C, SplitOld.first, I), SplitOld.second); + } + + QualType wrap(ASTContext &C, const Type *Old, unsigned I) { + if (I == Stack.size()) return QualType(Fn, 0); + + switch (static_cast<WrapKind>(Stack[I++])) { + case Desugar: + // This is the point at which we potentially lose source + // information. + return wrap(C, Old->getUnqualifiedDesugaredType(), I); + + case Parens: { + QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I); + return C.getParenType(New); + } + + case Pointer: { + QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I); + return C.getPointerType(New); + } + + case BlockPointer: { + QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I); + return C.getBlockPointerType(New); + } + + case MemberPointer: { + const MemberPointerType *OldMPT = cast<MemberPointerType>(Old); + QualType New = wrap(C, OldMPT->getPointeeType(), I); + return C.getMemberPointerType(New, OldMPT->getClass()); + } + + case Reference: { + const ReferenceType *OldRef = cast<ReferenceType>(Old); + QualType New = wrap(C, OldRef->getPointeeType(), I); + if (isa<LValueReferenceType>(OldRef)) + return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue()); + else + return C.getRValueReferenceType(New); + } + } + + llvm_unreachable("unknown wrapping kind"); + return QualType(); + } + }; +} + +/// Process an individual function attribute. Returns true to +/// indicate that the attribute was handled, false if it wasn't. +static bool handleFunctionTypeAttr(TypeProcessingState &state, + AttributeList &attr, + QualType &type) { + Sema &S = state.getSema(); + + FunctionTypeUnwrapper unwrapped(S, type); + + if (attr.getKind() == AttributeList::AT_noreturn) { + if (S.CheckNoReturnAttr(attr)) + return true; + + // Delay if this is not a function type. + if (!unwrapped.isFunctionType()) + return false; + + // Otherwise we can process right away. + FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true); + type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + return true; + } + + if (attr.getKind() == AttributeList::AT_regparm) { + unsigned value; + if (S.CheckRegparmAttr(attr, value)) + return true; + + // Delay if this is not a function type. + if (!unwrapped.isFunctionType()) + return false; + + // Diagnose regparm with fastcall. + const FunctionType *fn = unwrapped.get(); + CallingConv CC = fn->getCallConv(); + if (CC == CC_X86FastCall) { + S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) + << FunctionType::getNameForCallConv(CC) + << "regparm"; + attr.setInvalid(); + return true; + } + + FunctionType::ExtInfo EI = + unwrapped.get()->getExtInfo().withRegParm(value); + type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + return true; + } + + // Otherwise, a calling convention. + CallingConv CC; + if (S.CheckCallingConvAttr(attr, CC)) + return true; + + // Delay if the type didn't work out to a function. + if (!unwrapped.isFunctionType()) return false; + + const FunctionType *fn = unwrapped.get(); + CallingConv CCOld = fn->getCallConv(); + if (S.Context.getCanonicalCallConv(CC) == + S.Context.getCanonicalCallConv(CCOld)) { + FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC); + type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + return true; + } + + if (CCOld != CC_Default) { + // Should we diagnose reapplications of the same convention? + S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) + << FunctionType::getNameForCallConv(CC) + << FunctionType::getNameForCallConv(CCOld); + attr.setInvalid(); + return true; + } + + // Diagnose the use of X86 fastcall on varargs or unprototyped functions. + if (CC == CC_X86FastCall) { + if (isa<FunctionNoProtoType>(fn)) { + S.Diag(attr.getLoc(), diag::err_cconv_knr) + << FunctionType::getNameForCallConv(CC); + attr.setInvalid(); + return true; + } + + const FunctionProtoType *FnP = cast<FunctionProtoType>(fn); + if (FnP->isVariadic()) { + S.Diag(attr.getLoc(), diag::err_cconv_varargs) + << FunctionType::getNameForCallConv(CC); + attr.setInvalid(); + return true; + } + + // Also diagnose fastcall with regparm. + if (fn->getHasRegParm()) { + S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible) + << "regparm" + << FunctionType::getNameForCallConv(CC); + attr.setInvalid(); + return true; + } + } + + FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC); + type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI)); + return true; +} + +/// Handle OpenCL image access qualifiers: read_only, write_only, read_write +static void HandleOpenCLImageAccessAttribute(QualType& CurType, + const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); + llvm::APSInt arg(32); + if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || + !sizeExpr->isIntegerConstantExpr(arg, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "opencl_image_access" << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + unsigned iarg = static_cast<unsigned>(arg.getZExtValue()); + switch (iarg) { + case CLIA_read_only: + case CLIA_write_only: + case CLIA_read_write: + // Implemented in a separate patch + break; + default: + // Implemented in a separate patch + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + break; + } +} + +/// HandleVectorSizeAttribute - this attribute is only applicable to integral +/// and float scalars, although arrays, pointers, and function return values are +/// allowed in conjunction with this construct. Aggregates with this attribute +/// are invalid, even if they are of the same size as a corresponding scalar. +/// The raw attribute should contain precisely 1 argument, the vector size for +/// the variable, measured in bytes. If curType and rawAttr are well formed, +/// this routine will return a new vector type. +static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); + llvm::APSInt vecSize(32); + if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() || + !sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "vector_size" << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + // the base type must be integer or float, and can't already be a vector. + if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType; + Attr.setInvalid(); + return; + } + unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType)); + // vecSize is specified in bytes - convert to bits. + unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8); + + // the vector size needs to be an integral multiple of the type size. + if (vectorSize % typeSize) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + if (vectorSize == 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) + << sizeExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + + // Success! Instantiate the vector type, the number of elements is > 0, and + // not required to be a power of 2, unlike GCC. + CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, + VectorType::GenericVector); +} + +/// HandleNeonVectorTypeAttr - The "neon_vector_type" and +/// "neon_polyvector_type" attributes are used to create vector types that +/// are mangled according to ARM's ABI. Otherwise, these types are identical +/// to those created with the "vector_size" attribute. Unlike "vector_size" +/// the argument to these Neon attributes is the number of vector elements, +/// not the vector size in bytes. The vector width and element type must +/// match one of the standard Neon vector types. +static void HandleNeonVectorTypeAttr(QualType& CurType, + const AttributeList &Attr, Sema &S, + VectorType::VectorKind VecKind, + const char *AttrName) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + // The number of elements must be an ICE. + Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0)); + llvm::APSInt numEltsInt(32); + if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() || + !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << AttrName << numEltsExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + // Only certain element types are supported for Neon vectors. + const BuiltinType* BTy = CurType->getAs<BuiltinType>(); + if (!BTy || + (VecKind == VectorType::NeonPolyVector && + BTy->getKind() != BuiltinType::SChar && + BTy->getKind() != BuiltinType::Short) || + (BTy->getKind() != BuiltinType::SChar && + BTy->getKind() != BuiltinType::UChar && + BTy->getKind() != BuiltinType::Short && + BTy->getKind() != BuiltinType::UShort && + BTy->getKind() != BuiltinType::Int && + BTy->getKind() != BuiltinType::UInt && + BTy->getKind() != BuiltinType::LongLong && + BTy->getKind() != BuiltinType::ULongLong && + BTy->getKind() != BuiltinType::Float)) { + S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType; + Attr.setInvalid(); + return; + } + // The total size of the vector must be 64 or 128 bits. + unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType)); + unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue()); + unsigned vecSize = typeSize * numElts; + if (vecSize != 64 && vecSize != 128) { + S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType; + Attr.setInvalid(); + return; + } + + CurType = S.Context.getVectorType(CurType, numElts, VecKind); +} + +static void processTypeAttrs(TypeProcessingState &state, QualType &type, + bool isDeclSpec, AttributeList *attrs) { + // Scan through and apply attributes to this type where it makes sense. Some + // attributes (such as __address_space__, __vector_size__, etc) apply to the + // type, but others can be present in the type specifiers even though they + // apply to the decl. Here we apply type attributes and ignore the rest. + + AttributeList *next; + do { + AttributeList &attr = *attrs; + next = attr.getNext(); + + // Skip attributes that were marked to be invalid. + if (attr.isInvalid()) + continue; + + // If this is an attribute we can handle, do so now, + // otherwise, add it to the FnAttrs list for rechaining. + switch (attr.getKind()) { + default: break; + + case AttributeList::AT_address_space: + HandleAddressSpaceTypeAttribute(type, attr, state.getSema()); + break; + OBJC_POINTER_TYPE_ATTRS_CASELIST: + if (!handleObjCPointerTypeAttr(state, attr, type)) + distributeObjCPointerTypeAttr(state, attr, type); + break; + case AttributeList::AT_vector_size: + HandleVectorSizeAttr(type, attr, state.getSema()); + break; + case AttributeList::AT_neon_vector_type: + HandleNeonVectorTypeAttr(type, attr, state.getSema(), + VectorType::NeonVector, "neon_vector_type"); + break; + case AttributeList::AT_neon_polyvector_type: + HandleNeonVectorTypeAttr(type, attr, state.getSema(), + VectorType::NeonPolyVector, + "neon_polyvector_type"); + break; + + case AttributeList::AT_opencl_image_access: + HandleOpenCLImageAccessAttribute(type, attr, state.getSema()); + break; + + FUNCTION_TYPE_ATTRS_CASELIST: + // Never process function type attributes as part of the + // declaration-specifiers. + if (isDeclSpec) + distributeFunctionTypeAttrFromDeclSpec(state, attr, type); + + // Otherwise, handle the possible delays. + else if (!handleFunctionTypeAttr(state, attr, type)) + distributeFunctionTypeAttr(state, attr, type); + break; + } + } while ((attrs = next)); +} + +/// \brief Ensure that the type of the given expression is complete. +/// +/// This routine checks whether the expression \p E has a complete type. If the +/// expression refers to an instantiable construct, that instantiation is +/// performed as needed to complete its type. Furthermore +/// Sema::RequireCompleteType is called for the expression's type (or in the +/// case of a reference type, the referred-to type). +/// +/// \param E The expression whose type is required to be complete. +/// \param PD The partial diagnostic that will be printed out if the type cannot +/// be completed. +/// +/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false +/// otherwise. +bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, + std::pair<SourceLocation, + PartialDiagnostic> Note) { + QualType T = E->getType(); + + // Fast path the case where the type is already complete. + if (!T->isIncompleteType()) + return false; + + // Incomplete array types may be completed by the initializer attached to + // their definitions. For static data members of class templates we need to + // instantiate the definition to get this initializer and complete the type. + if (T->isIncompleteArrayType()) { + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { + if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { + if (Var->isStaticDataMember() && + Var->getInstantiatedFromStaticDataMember()) { + + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + if (MSInfo->getTemplateSpecializationKind() + != TSK_ExplicitSpecialization) { + // If we don't already have a point of instantiation, this is it. + if (MSInfo->getPointOfInstantiation().isInvalid()) { + MSInfo->setPointOfInstantiation(E->getLocStart()); + + // This is a modification of an existing AST node. Notify + // listeners. + if (ASTMutationListener *L = getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); + } + + InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var); + + // Update the type to the newly instantiated definition's type both + // here and within the expression. + if (VarDecl *Def = Var->getDefinition()) { + DRE->setDecl(Def); + T = Def->getType(); + DRE->setType(T); + E->setType(T); + } + } + + // We still go on to try to complete the type independently, as it + // may also require instantiations or diagnostics if it remains + // incomplete. + } + } + } + } + + // FIXME: Are there other cases which require instantiating something other + // than the type to complete the type of an expression? + + // Look through reference types and complete the referred type. + if (const ReferenceType *Ref = T->getAs<ReferenceType>()) + T = Ref->getPointeeType(); + + return RequireCompleteType(E->getExprLoc(), T, PD, Note); +} + +/// @brief Ensure that the type T is a complete type. +/// +/// This routine checks whether the type @p T is complete in any +/// context where a complete type is required. If @p T is a complete +/// type, returns false. If @p T is a class template specialization, +/// this routine then attempts to perform class template +/// instantiation. If instantiation fails, or if @p T is incomplete +/// and cannot be completed, issues the diagnostic @p diag (giving it +/// the type @p T) and returns true. +/// +/// @param Loc The location in the source that the incomplete type +/// diagnostic should refer to. +/// +/// @param T The type that this routine is examining for completeness. +/// +/// @param PD The partial diagnostic that will be printed out if T is not a +/// complete type. +/// +/// @returns @c true if @p T is incomplete and a diagnostic was emitted, +/// @c false otherwise. +bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD, + std::pair<SourceLocation, + PartialDiagnostic> Note) { + unsigned diag = PD.getDiagID(); + + // FIXME: Add this assertion to make sure we always get instantiation points. + // assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType"); + // FIXME: Add this assertion to help us flush out problems with + // checking for dependent types and type-dependent expressions. + // + // assert(!T->isDependentType() && + // "Can't ask whether a dependent type is complete"); + + // If we have a complete type, we're done. + if (!T->isIncompleteType()) + return false; + + // If we have a class template specialization or a class member of a + // class template specialization, or an array with known size of such, + // try to instantiate it. + QualType MaybeTemplate = T; + if (const ConstantArrayType *Array = Context.getAsConstantArrayType(T)) + MaybeTemplate = Array->getElementType(); + if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) { + if (ClassTemplateSpecializationDecl *ClassTemplateSpec + = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) { + if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) + return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec, + TSK_ImplicitInstantiation, + /*Complain=*/diag != 0); + } else if (CXXRecordDecl *Rec + = dyn_cast<CXXRecordDecl>(Record->getDecl())) { + if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) { + MemberSpecializationInfo *MSInfo = Rec->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + // This record was instantiated from a class within a template. + if (MSInfo->getTemplateSpecializationKind() + != TSK_ExplicitSpecialization) + return InstantiateClass(Loc, Rec, Pattern, + getTemplateInstantiationArgs(Rec), + TSK_ImplicitInstantiation, + /*Complain=*/diag != 0); + } + } + } + + if (diag == 0) + return true; + + const TagType *Tag = T->getAs<TagType>(); + + // Avoid diagnosing invalid decls as incomplete. + if (Tag && Tag->getDecl()->isInvalidDecl()) + return true; + + // Give the external AST source a chance to complete the type. + if (Tag && Tag->getDecl()->hasExternalLexicalStorage()) { + Context.getExternalSource()->CompleteType(Tag->getDecl()); + if (!Tag->isIncompleteType()) + return false; + } + + // We have an incomplete type. Produce a diagnostic. + Diag(Loc, PD) << T; + + // If we have a note, produce it. + if (!Note.first.isInvalid()) + Diag(Note.first, Note.second); + + // If the type was a forward declaration of a class/struct/union + // type, produce a note. + if (Tag && !Tag->getDecl()->isInvalidDecl()) + Diag(Tag->getDecl()->getLocation(), + Tag->isBeingDefined() ? diag::note_type_being_defined + : diag::note_forward_declaration) + << QualType(Tag, 0); + + return true; +} + +bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, + const PartialDiagnostic &PD) { + return RequireCompleteType(Loc, T, PD, + std::make_pair(SourceLocation(), PDiag(0))); +} + +bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, + unsigned DiagID) { + return RequireCompleteType(Loc, T, PDiag(DiagID), + std::make_pair(SourceLocation(), PDiag(0))); +} + +/// \brief Retrieve a version of the type 'T' that is elaborated by Keyword +/// and qualified by the nested-name-specifier contained in SS. +QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, + const CXXScopeSpec &SS, QualType T) { + if (T.isNull()) + return T; + NestedNameSpecifier *NNS; + if (SS.isValid()) + NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + else { + if (Keyword == ETK_None) + return T; + NNS = 0; + } + return Context.getElaboratedType(Keyword, NNS, T); +} + +QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) { + ExprResult ER = CheckPlaceholderExpr(E); + if (ER.isInvalid()) return QualType(); + E = ER.take(); + + if (!E->isTypeDependent()) { + QualType T = E->getType(); + if (const TagType *TT = T->getAs<TagType>()) + DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc()); + } + return Context.getTypeOfExprType(E); +} + +QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) { + ExprResult ER = CheckPlaceholderExpr(E); + if (ER.isInvalid()) return QualType(); + E = ER.take(); + + return Context.getDecltypeType(E); +} + +QualType Sema::BuildUnaryTransformType(QualType BaseType, + UnaryTransformType::UTTKind UKind, + SourceLocation Loc) { + switch (UKind) { + case UnaryTransformType::EnumUnderlyingType: + if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) { + Diag(Loc, diag::err_only_enums_have_underlying_types); + return QualType(); + } else { + QualType Underlying = BaseType; + if (!BaseType->isDependentType()) { + EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl(); + assert(ED && "EnumType has no EnumDecl"); + DiagnoseUseOfDecl(ED, Loc); + Underlying = ED->getIntegerType(); + } + assert(!Underlying.isNull()); + return Context.getUnaryTransformType(BaseType, Underlying, + UnaryTransformType::EnumUnderlyingType); + } + } + llvm_unreachable("unknown unary transform type"); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp new file mode 100644 index 0000000..ab697ee --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.cpp @@ -0,0 +1,276 @@ +//===-- TargetAttributesSema.cpp - Encapsulate target attributes-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains semantic analysis implementation for target-specific +// attributes. +// +//===----------------------------------------------------------------------===// + +#include "TargetAttributesSema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/AST/DeclCXX.h" +#include "llvm/ADT/Triple.h" + +using namespace clang; + +TargetAttributesSema::~TargetAttributesSema() {} +bool TargetAttributesSema::ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const { + return false; +} + +static void HandleMSP430InterruptAttr(Decl *d, + const AttributeList &Attr, Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + Expr *NumParamsExpr = static_cast<Expr *>(Attr.getArg(0)); + llvm::APSInt NumParams(32); + if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "interrupt" << NumParamsExpr->getSourceRange(); + return; + } + + unsigned Num = NumParams.getLimitedValue(255); + if ((Num & 1) || Num > 30) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_out_of_bounds) + << "interrupt" << (int)NumParams.getSExtValue() + << NumParamsExpr->getSourceRange(); + return; + } + + d->addAttr(::new (S.Context) MSP430InterruptAttr(Attr.getLoc(), S.Context, Num)); + d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); + } + +namespace { + class MSP430AttributesSema : public TargetAttributesSema { + public: + MSP430AttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const { + if (Attr.getName()->getName() == "interrupt") { + HandleMSP430InterruptAttr(D, Attr, S); + return true; + } + return false; + } + }; +} + +static void HandleMBlazeInterruptHandlerAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + d->addAttr(::new (S.Context) MBlazeInterruptHandlerAttr(Attr.getLoc(), + S.Context)); + d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); +} + +static void HandleMBlazeSaveVolatilesAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + + // FIXME: Check for decl - it should be void ()(void). + + d->addAttr(::new (S.Context) MBlazeSaveVolatilesAttr(Attr.getLoc(), + S.Context)); + d->addAttr(::new (S.Context) UsedAttr(Attr.getLoc(), S.Context)); +} + + +namespace { + class MBlazeAttributesSema : public TargetAttributesSema { + public: + MBlazeAttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, + Sema &S) const { + if (Attr.getName()->getName() == "interrupt_handler") { + HandleMBlazeInterruptHandlerAttr(D, Attr, S); + return true; + } else if (Attr.getName()->getName() == "save_volatiles") { + HandleMBlazeSaveVolatilesAttr(D, Attr, S); + return true; + } + return false; + } + }; +} + +static void HandleX86ForceAlignArgPointerAttr(Decl *D, + const AttributeList& Attr, + Sema &S) { + // Check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // If we try to apply it to a function pointer, don't warn, but don't + // do anything, either. It doesn't matter anyway, because there's nothing + // special about calling a force_align_arg_pointer function. + ValueDecl *VD = dyn_cast<ValueDecl>(D); + if (VD && VD->getType()->isFunctionPointerType()) + return; + // Also don't warn on function pointer typedefs. + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); + if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || + TD->getUnderlyingType()->isFunctionType())) + return; + // Attribute can only be applied to function types. + if (!isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << /* function */0; + return; + } + + D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr(Attr.getLoc(), S.Context)); +} + +static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // Attribute can be applied only to functions or variables. + if (isa<VarDecl>(D)) { + D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context)); + return; + } + + FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) { + // Apparently Visual C++ thinks it is okay to not emit a warning + // in this case, so only emit a warning when -fms-extensions is not + // specified. + if (!S.getLangOptions().Microsoft) + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 2 /*variable and function*/; + return; + } + + // Currently, the dllimport attribute is ignored for inlined functions. + // Warning is emitted. + if (FD->isInlineSpecified()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; + return; + } + + // The attribute is also overridden by a subsequent declaration as dllexport. + // Warning is emitted. + for (AttributeList *nextAttr = Attr.getNext(); nextAttr; + nextAttr = nextAttr->getNext()) { + if (nextAttr->getKind() == AttributeList::AT_dllexport) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; + return; + } + } + + if (D->getAttr<DLLExportAttr>()) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; + return; + } + + D->addAttr(::new (S.Context) DLLImportAttr(Attr.getLoc(), S.Context)); +} + +static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + // Attribute can be applied only to functions or variables. + if (isa<VarDecl>(D)) { + D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context)); + return; + } + + FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 2 /*variable and function*/; + return; + } + + // Currently, the dllexport attribute is ignored for inlined functions, unless + // the -fkeep-inline-functions flag has been used. Warning is emitted; + if (FD->isInlineSpecified()) { + // FIXME: ... unless the -fkeep-inline-functions flag has been used. + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport"; + return; + } + + D->addAttr(::new (S.Context) DLLExportAttr(Attr.getLoc(), S.Context)); +} + +namespace { + class X86AttributesSema : public TargetAttributesSema { + public: + X86AttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const { + const llvm::Triple &Triple(S.Context.Target.getTriple()); + if (Triple.getOS() == llvm::Triple::Win32 || + Triple.getOS() == llvm::Triple::MinGW32) { + switch (Attr.getKind()) { + case AttributeList::AT_dllimport: HandleDLLImportAttr(D, Attr, S); + return true; + case AttributeList::AT_dllexport: HandleDLLExportAttr(D, Attr, S); + return true; + default: break; + } + } + if (Attr.getName()->getName() == "force_align_arg_pointer" || + Attr.getName()->getName() == "__force_align_arg_pointer__") { + HandleX86ForceAlignArgPointerAttr(D, Attr, S); + return true; + } + return false; + } + }; +} + +const TargetAttributesSema &Sema::getTargetAttributesSema() const { + if (TheTargetAttributesSema) + return *TheTargetAttributesSema; + + const llvm::Triple &Triple(Context.Target.getTriple()); + switch (Triple.getArch()) { + default: + return *(TheTargetAttributesSema = new TargetAttributesSema); + + case llvm::Triple::msp430: + return *(TheTargetAttributesSema = new MSP430AttributesSema); + case llvm::Triple::mblaze: + return *(TheTargetAttributesSema = new MBlazeAttributesSema); + case llvm::Triple::x86: + return *(TheTargetAttributesSema = new X86AttributesSema); + } +} diff --git a/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h new file mode 100644 index 0000000..410c900 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/TargetAttributesSema.h @@ -0,0 +1,27 @@ +//===--- TargetAttributesSema.h - Semantic Analysis For Target Attributes -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_SEMA_TARGETSEMA_H +#define CLANG_SEMA_TARGETSEMA_H + +namespace clang { + class Scope; + class Decl; + class AttributeList; + class Sema; + + class TargetAttributesSema { + public: + virtual ~TargetAttributesSema(); + virtual bool ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const; + }; +} + +#endif diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h new file mode 100644 index 0000000..ff2e46a --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -0,0 +1,8287 @@ +//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// This file implements a semantic tree transformation that takes a given +// AST and rebuilds it, possibly transforming some nodes in the process. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_TREETRANSFORM_H +#define LLVM_CLANG_SEMA_TREETRANSFORM_H + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/Designator.h" +#include "clang/Lex/Preprocessor.h" +#include "llvm/Support/ErrorHandling.h" +#include "TypeLocBuilder.h" +#include <algorithm> + +namespace clang { +using namespace sema; + +/// \brief A semantic tree transformation that allows one to transform one +/// abstract syntax tree into another. +/// +/// A new tree transformation is defined by creating a new subclass \c X of +/// \c TreeTransform<X> and then overriding certain operations to provide +/// behavior specific to that transformation. For example, template +/// instantiation is implemented as a tree transformation where the +/// transformation of TemplateTypeParmType nodes involves substituting the +/// template arguments for their corresponding template parameters; a similar +/// transformation is performed for non-type template parameters and +/// template template parameters. +/// +/// This tree-transformation template uses static polymorphism to allow +/// subclasses to customize any of its operations. Thus, a subclass can +/// override any of the transformation or rebuild operators by providing an +/// operation with the same signature as the default implementation. The +/// overridding function should not be virtual. +/// +/// Semantic tree transformations are split into two stages, either of which +/// can be replaced by a subclass. The "transform" step transforms an AST node +/// or the parts of an AST node using the various transformation functions, +/// then passes the pieces on to the "rebuild" step, which constructs a new AST +/// node of the appropriate kind from the pieces. The default transformation +/// routines recursively transform the operands to composite AST nodes (e.g., +/// the pointee type of a PointerType node) and, if any of those operand nodes +/// were changed by the transformation, invokes the rebuild operation to create +/// a new AST node. +/// +/// Subclasses can customize the transformation at various levels. The +/// most coarse-grained transformations involve replacing TransformType(), +/// TransformExpr(), TransformDecl(), TransformNestedNameSpecifierLoc(), +/// TransformTemplateName(), or TransformTemplateArgument() with entirely +/// new implementations. +/// +/// For more fine-grained transformations, subclasses can replace any of the +/// \c TransformXXX functions (where XXX is the name of an AST node, e.g., +/// PointerType, StmtExpr) to alter the transformation. As mentioned previously, +/// replacing TransformTemplateTypeParmType() allows template instantiation +/// to substitute template arguments for their corresponding template +/// parameters. Additionally, subclasses can override the \c RebuildXXX +/// functions to control how AST nodes are rebuilt when their operands change. +/// By default, \c TreeTransform will invoke semantic analysis to rebuild +/// AST nodes. However, certain other tree transformations (e.g, cloning) may +/// be able to use more efficient rebuild steps. +/// +/// There are a handful of other functions that can be overridden, allowing one +/// to avoid traversing nodes that don't need any transformation +/// (\c AlreadyTransformed()), force rebuilding AST nodes even when their +/// operands have not changed (\c AlwaysRebuild()), and customize the +/// default locations and entity names used for type-checking +/// (\c getBaseLocation(), \c getBaseEntity()). +template<typename Derived> +class TreeTransform { + /// \brief Private RAII object that helps us forget and then re-remember + /// the template argument corresponding to a partially-substituted parameter + /// pack. + class ForgetPartiallySubstitutedPackRAII { + Derived &Self; + TemplateArgument Old; + + public: + ForgetPartiallySubstitutedPackRAII(Derived &Self) : Self(Self) { + Old = Self.ForgetPartiallySubstitutedPack(); + } + + ~ForgetPartiallySubstitutedPackRAII() { + Self.RememberPartiallySubstitutedPack(Old); + } + }; + +protected: + Sema &SemaRef; + +public: + /// \brief Initializes a new tree transformer. + TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { } + + /// \brief Retrieves a reference to the derived class. + Derived &getDerived() { return static_cast<Derived&>(*this); } + + /// \brief Retrieves a reference to the derived class. + const Derived &getDerived() const { + return static_cast<const Derived&>(*this); + } + + static inline ExprResult Owned(Expr *E) { return E; } + static inline StmtResult Owned(Stmt *S) { return S; } + + /// \brief Retrieves a reference to the semantic analysis object used for + /// this tree transform. + Sema &getSema() const { return SemaRef; } + + /// \brief Whether the transformation should always rebuild AST nodes, even + /// if none of the children have changed. + /// + /// Subclasses may override this function to specify when the transformation + /// should rebuild all AST nodes. + bool AlwaysRebuild() { return false; } + + /// \brief Returns the location of the entity being transformed, if that + /// information was not available elsewhere in the AST. + /// + /// By default, returns no source-location information. Subclasses can + /// provide an alternative implementation that provides better location + /// information. + SourceLocation getBaseLocation() { return SourceLocation(); } + + /// \brief Returns the name of the entity being transformed, if that + /// information was not available elsewhere in the AST. + /// + /// By default, returns an empty name. Subclasses can provide an alternative + /// implementation with a more precise name. + DeclarationName getBaseEntity() { return DeclarationName(); } + + /// \brief Sets the "base" location and entity when that + /// information is known based on another transformation. + /// + /// By default, the source location and entity are ignored. Subclasses can + /// override this function to provide a customized implementation. + void setBase(SourceLocation Loc, DeclarationName Entity) { } + + /// \brief RAII object that temporarily sets the base location and entity + /// used for reporting diagnostics in types. + class TemporaryBase { + TreeTransform &Self; + SourceLocation OldLocation; + DeclarationName OldEntity; + + public: + TemporaryBase(TreeTransform &Self, SourceLocation Location, + DeclarationName Entity) : Self(Self) { + OldLocation = Self.getDerived().getBaseLocation(); + OldEntity = Self.getDerived().getBaseEntity(); + + if (Location.isValid()) + Self.getDerived().setBase(Location, Entity); + } + + ~TemporaryBase() { + Self.getDerived().setBase(OldLocation, OldEntity); + } + }; + + /// \brief Determine whether the given type \p T has already been + /// transformed. + /// + /// Subclasses can provide an alternative implementation of this routine + /// to short-circuit evaluation when it is known that a given type will + /// not change. For example, template instantiation need not traverse + /// non-dependent types. + bool AlreadyTransformed(QualType T) { + return T.isNull(); + } + + /// \brief Determine whether the given call argument should be dropped, e.g., + /// because it is a default argument. + /// + /// Subclasses can provide an alternative implementation of this routine to + /// determine which kinds of call arguments get dropped. By default, + /// CXXDefaultArgument nodes are dropped (prior to transformation). + bool DropCallArgument(Expr *E) { + return E->isDefaultArgument(); + } + + /// \brief Determine whether we should expand a pack expansion with the + /// given set of parameter packs into separate arguments by repeatedly + /// transforming the pattern. + /// + /// By default, the transformer never tries to expand pack expansions. + /// Subclasses can override this routine to provide different behavior. + /// + /// \param EllipsisLoc The location of the ellipsis that identifies the + /// pack expansion. + /// + /// \param PatternRange The source range that covers the entire pattern of + /// the pack expansion. + /// + /// \param Unexpanded The set of unexpanded parameter packs within the + /// pattern. + /// + /// \param NumUnexpanded The number of unexpanded parameter packs in + /// \p Unexpanded. + /// + /// \param ShouldExpand Will be set to \c true if the transformer should + /// expand the corresponding pack expansions into separate arguments. When + /// set, \c NumExpansions must also be set. + /// + /// \param RetainExpansion Whether the caller should add an unexpanded + /// pack expansion after all of the expanded arguments. This is used + /// when extending explicitly-specified template argument packs per + /// C++0x [temp.arg.explicit]p9. + /// + /// \param NumExpansions The number of separate arguments that will be in + /// the expanded form of the corresponding pack expansion. This is both an + /// input and an output parameter, which can be set by the caller if the + /// number of expansions is known a priori (e.g., due to a prior substitution) + /// and will be set by the callee when the number of expansions is known. + /// The callee must set this value when \c ShouldExpand is \c true; it may + /// set this value in other cases. + /// + /// \returns true if an error occurred (e.g., because the parameter packs + /// are to be instantiated with arguments of different lengths), false + /// otherwise. If false, \c ShouldExpand (and possibly \c NumExpansions) + /// must be set. + bool TryExpandParameterPacks(SourceLocation EllipsisLoc, + SourceRange PatternRange, + const UnexpandedParameterPack *Unexpanded, + unsigned NumUnexpanded, + bool &ShouldExpand, + bool &RetainExpansion, + llvm::Optional<unsigned> &NumExpansions) { + ShouldExpand = false; + return false; + } + + /// \brief "Forget" about the partially-substituted pack template argument, + /// when performing an instantiation that must preserve the parameter pack + /// use. + /// + /// This routine is meant to be overridden by the template instantiator. + TemplateArgument ForgetPartiallySubstitutedPack() { + return TemplateArgument(); + } + + /// \brief "Remember" the partially-substituted pack template argument + /// after performing an instantiation that must preserve the parameter pack + /// use. + /// + /// This routine is meant to be overridden by the template instantiator. + void RememberPartiallySubstitutedPack(TemplateArgument Arg) { } + + /// \brief Note to the derived class when a function parameter pack is + /// being expanded. + void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { } + + /// \brief Transforms the given type into another type. + /// + /// By default, this routine transforms a type by creating a + /// TypeSourceInfo for it and delegating to the appropriate + /// function. This is expensive, but we don't mind, because + /// this method is deprecated anyway; all users should be + /// switched to storing TypeSourceInfos. + /// + /// \returns the transformed type. + QualType TransformType(QualType T); + + /// \brief Transforms the given type-with-location into a new + /// type-with-location. + /// + /// By default, this routine transforms a type by delegating to the + /// appropriate TransformXXXType to build a new type. Subclasses + /// may override this function (to take over all type + /// transformations) or some set of the TransformXXXType functions + /// to alter the transformation. + TypeSourceInfo *TransformType(TypeSourceInfo *DI); + + /// \brief Transform the given type-with-location into a new + /// type, collecting location information in the given builder + /// as necessary. + /// + QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL); + + /// \brief Transform the given statement. + /// + /// By default, this routine transforms a statement by delegating to the + /// appropriate TransformXXXStmt function to transform a specific kind of + /// statement or the TransformExpr() function to transform an expression. + /// Subclasses may override this function to transform statements using some + /// other mechanism. + /// + /// \returns the transformed statement. + StmtResult TransformStmt(Stmt *S); + + /// \brief Transform the given expression. + /// + /// By default, this routine transforms an expression by delegating to the + /// appropriate TransformXXXExpr function to build a new expression. + /// Subclasses may override this function to transform expressions using some + /// other mechanism. + /// + /// \returns the transformed expression. + ExprResult TransformExpr(Expr *E); + + /// \brief Transform the given list of expressions. + /// + /// This routine transforms a list of expressions by invoking + /// \c TransformExpr() for each subexpression. However, it also provides + /// support for variadic templates by expanding any pack expansions (if the + /// derived class permits such expansion) along the way. When pack expansions + /// are present, the number of outputs may not equal the number of inputs. + /// + /// \param Inputs The set of expressions to be transformed. + /// + /// \param NumInputs The number of expressions in \c Inputs. + /// + /// \param IsCall If \c true, then this transform is being performed on + /// function-call arguments, and any arguments that should be dropped, will + /// be. + /// + /// \param Outputs The transformed input expressions will be added to this + /// vector. + /// + /// \param ArgChanged If non-NULL, will be set \c true if any argument changed + /// due to transformation. + /// + /// \returns true if an error occurred, false otherwise. + bool TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall, + llvm::SmallVectorImpl<Expr *> &Outputs, + bool *ArgChanged = 0); + + /// \brief Transform the given declaration, which is referenced from a type + /// or expression. + /// + /// By default, acts as the identity function on declarations. Subclasses + /// may override this function to provide alternate behavior. + Decl *TransformDecl(SourceLocation Loc, Decl *D) { return D; } + + /// \brief Transform the definition of the given declaration. + /// + /// By default, invokes TransformDecl() to transform the declaration. + /// Subclasses may override this function to provide alternate behavior. + Decl *TransformDefinition(SourceLocation Loc, Decl *D) { + return getDerived().TransformDecl(Loc, D); + } + + /// \brief Transform the given declaration, which was the first part of a + /// nested-name-specifier in a member access expression. + /// + /// This specific declaration transformation only applies to the first + /// identifier in a nested-name-specifier of a member access expression, e.g., + /// the \c T in \c x->T::member + /// + /// By default, invokes TransformDecl() to transform the declaration. + /// Subclasses may override this function to provide alternate behavior. + NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) { + return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D)); + } + + /// \brief Transform the given nested-name-specifier with source-location + /// information. + /// + /// By default, transforms all of the types and declarations within the + /// nested-name-specifier. Subclasses may override this function to provide + /// alternate behavior. + NestedNameSpecifierLoc TransformNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + QualType ObjectType = QualType(), + NamedDecl *FirstQualifierInScope = 0); + + /// \brief Transform the given declaration name. + /// + /// By default, transforms the types of conversion function, constructor, + /// and destructor names and then (if needed) rebuilds the declaration name. + /// Identifiers and selectors are returned unmodified. Sublcasses may + /// override this function to provide alternate behavior. + DeclarationNameInfo + TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo); + + /// \brief Transform the given template name. + /// + /// \param SS The nested-name-specifier that qualifies the template + /// name. This nested-name-specifier must already have been transformed. + /// + /// \param Name The template name to transform. + /// + /// \param NameLoc The source location of the template name. + /// + /// \param ObjectType If we're translating a template name within a member + /// access expression, this is the type of the object whose member template + /// is being referenced. + /// + /// \param FirstQualifierInScope If the first part of a nested-name-specifier + /// also refers to a name within the current (lexical) scope, this is the + /// declaration it refers to. + /// + /// By default, transforms the template name by transforming the declarations + /// and nested-name-specifiers that occur within the template name. + /// Subclasses may override this function to provide alternate behavior. + TemplateName TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, + QualType ObjectType = QualType(), + NamedDecl *FirstQualifierInScope = 0); + + /// \brief Transform the given template argument. + /// + /// By default, this operation transforms the type, expression, or + /// declaration stored within the template argument and constructs a + /// new template argument from the transformed result. Subclasses may + /// override this function to provide alternate behavior. + /// + /// Returns true if there was an error. + bool TransformTemplateArgument(const TemplateArgumentLoc &Input, + TemplateArgumentLoc &Output); + + /// \brief Transform the given set of template arguments. + /// + /// By default, this operation transforms all of the template arguments + /// in the input set using \c TransformTemplateArgument(), and appends + /// the transformed arguments to the output list. + /// + /// Note that this overload of \c TransformTemplateArguments() is merely + /// a convenience function. Subclasses that wish to override this behavior + /// should override the iterator-based member template version. + /// + /// \param Inputs The set of template arguments to be transformed. + /// + /// \param NumInputs The number of template arguments in \p Inputs. + /// + /// \param Outputs The set of transformed template arguments output by this + /// routine. + /// + /// Returns true if an error occurred. + bool TransformTemplateArguments(const TemplateArgumentLoc *Inputs, + unsigned NumInputs, + TemplateArgumentListInfo &Outputs) { + return TransformTemplateArguments(Inputs, Inputs + NumInputs, Outputs); + } + + /// \brief Transform the given set of template arguments. + /// + /// By default, this operation transforms all of the template arguments + /// in the input set using \c TransformTemplateArgument(), and appends + /// the transformed arguments to the output list. + /// + /// \param First An iterator to the first template argument. + /// + /// \param Last An iterator one step past the last template argument. + /// + /// \param Outputs The set of transformed template arguments output by this + /// routine. + /// + /// Returns true if an error occurred. + template<typename InputIterator> + bool TransformTemplateArguments(InputIterator First, + InputIterator Last, + TemplateArgumentListInfo &Outputs); + + /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument. + void InventTemplateArgumentLoc(const TemplateArgument &Arg, + TemplateArgumentLoc &ArgLoc); + + /// \brief Fakes up a TypeSourceInfo for a type. + TypeSourceInfo *InventTypeSourceInfo(QualType T) { + return SemaRef.Context.getTrivialTypeSourceInfo(T, + getDerived().getBaseLocation()); + } + +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T); +#include "clang/AST/TypeLocNodes.def" + + StmtResult + TransformSEHHandler(Stmt *Handler); + + QualType + TransformTemplateSpecializationType(TypeLocBuilder &TLB, + TemplateSpecializationTypeLoc TL, + TemplateName Template); + + QualType + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + TemplateName Template, + CXXScopeSpec &SS); + + QualType + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc); + + /// \brief Transforms the parameters of a function type into the + /// given vectors. + /// + /// The result vectors should be kept in sync; null entries in the + /// variables vector are acceptable. + /// + /// Return true on error. + bool TransformFunctionTypeParams(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, + const QualType *ParamTypes, + llvm::SmallVectorImpl<QualType> &PTypes, + llvm::SmallVectorImpl<ParmVarDecl*> *PVars); + + /// \brief Transforms a single function-type parameter. Return null + /// on error. + /// + /// \param indexAdjustment - A number to add to the parameter's + /// scope index; can be negative + ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, + llvm::Optional<unsigned> NumExpansions); + + QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); + + StmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); + ExprResult TransformCXXNamedCastExpr(CXXNamedCastExpr *E); + +#define STMT(Node, Parent) \ + StmtResult Transform##Node(Node *S); +#define EXPR(Node, Parent) \ + ExprResult Transform##Node(Node *E); +#define ABSTRACT_STMT(Stmt) +#include "clang/AST/StmtNodes.inc" + + /// \brief Build a new pointer type given its pointee type. + /// + /// By default, performs semantic analysis when building the pointer type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil); + + /// \brief Build a new block pointer type given its pointee type. + /// + /// By default, performs semantic analysis when building the block pointer + /// type. Subclasses may override this routine to provide different behavior. + QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil); + + /// \brief Build a new reference type given the type it references. + /// + /// By default, performs semantic analysis when building the + /// reference type. Subclasses may override this routine to provide + /// different behavior. + /// + /// \param LValue whether the type was written with an lvalue sigil + /// or an rvalue sigil. + QualType RebuildReferenceType(QualType ReferentType, + bool LValue, + SourceLocation Sigil); + + /// \brief Build a new member pointer type given the pointee type and the + /// class type it refers into. + /// + /// By default, performs semantic analysis when building the member pointer + /// type. Subclasses may override this routine to provide different behavior. + QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType, + SourceLocation Sigil); + + /// \brief Build a new array type given the element type, size + /// modifier, size of the array (if known), size expression, and index type + /// qualifiers. + /// + /// By default, performs semantic analysis when building the array type. + /// Subclasses may override this routine to provide different behavior. + /// Also by default, all of the other Rebuild*Array + QualType RebuildArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + const llvm::APInt *Size, + Expr *SizeExpr, + unsigned IndexTypeQuals, + SourceRange BracketsRange); + + /// \brief Build a new constant array type given the element type, size + /// modifier, (known) size of the array, and index type qualifiers. + /// + /// By default, performs semantic analysis when building the array type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildConstantArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + const llvm::APInt &Size, + unsigned IndexTypeQuals, + SourceRange BracketsRange); + + /// \brief Build a new incomplete array type given the element type, size + /// modifier, and index type qualifiers. + /// + /// By default, performs semantic analysis when building the array type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildIncompleteArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + unsigned IndexTypeQuals, + SourceRange BracketsRange); + + /// \brief Build a new variable-length array type given the element type, + /// size modifier, size expression, and index type qualifiers. + /// + /// By default, performs semantic analysis when building the array type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildVariableArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + Expr *SizeExpr, + unsigned IndexTypeQuals, + SourceRange BracketsRange); + + /// \brief Build a new dependent-sized array type given the element type, + /// size modifier, size expression, and index type qualifiers. + /// + /// By default, performs semantic analysis when building the array type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildDependentSizedArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + Expr *SizeExpr, + unsigned IndexTypeQuals, + SourceRange BracketsRange); + + /// \brief Build a new vector type given the element type and + /// number of elements. + /// + /// By default, performs semantic analysis when building the vector type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildVectorType(QualType ElementType, unsigned NumElements, + VectorType::VectorKind VecKind); + + /// \brief Build a new extended vector type given the element type and + /// number of elements. + /// + /// By default, performs semantic analysis when building the vector type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildExtVectorType(QualType ElementType, unsigned NumElements, + SourceLocation AttributeLoc); + + /// \brief Build a new potentially dependently-sized extended vector type + /// given the element type and number of elements. + /// + /// By default, performs semantic analysis when building the vector type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildDependentSizedExtVectorType(QualType ElementType, + Expr *SizeExpr, + SourceLocation AttributeLoc); + + /// \brief Build a new function type. + /// + /// By default, performs semantic analysis when building the function type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildFunctionProtoType(QualType T, + QualType *ParamTypes, + unsigned NumParamTypes, + bool Variadic, unsigned Quals, + RefQualifierKind RefQualifier, + const FunctionType::ExtInfo &Info); + + /// \brief Build a new unprototyped function type. + QualType RebuildFunctionNoProtoType(QualType ResultType); + + /// \brief Rebuild an unresolved typename type, given the decl that + /// the UnresolvedUsingTypenameDecl was transformed to. + QualType RebuildUnresolvedUsingType(Decl *D); + + /// \brief Build a new typedef type. + QualType RebuildTypedefType(TypedefNameDecl *Typedef) { + return SemaRef.Context.getTypeDeclType(Typedef); + } + + /// \brief Build a new class/struct/union type. + QualType RebuildRecordType(RecordDecl *Record) { + return SemaRef.Context.getTypeDeclType(Record); + } + + /// \brief Build a new Enum type. + QualType RebuildEnumType(EnumDecl *Enum) { + return SemaRef.Context.getTypeDeclType(Enum); + } + + /// \brief Build a new typeof(expr) type. + /// + /// By default, performs semantic analysis when building the typeof type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildTypeOfExprType(Expr *Underlying, SourceLocation Loc); + + /// \brief Build a new typeof(type) type. + /// + /// By default, builds a new TypeOfType with the given underlying type. + QualType RebuildTypeOfType(QualType Underlying); + + /// \brief Build a new unary transform type. + QualType RebuildUnaryTransformType(QualType BaseType, + UnaryTransformType::UTTKind UKind, + SourceLocation Loc); + + /// \brief Build a new C++0x decltype type. + /// + /// By default, performs semantic analysis when building the decltype type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildDecltypeType(Expr *Underlying, SourceLocation Loc); + + /// \brief Build a new C++0x auto type. + /// + /// By default, builds a new AutoType with the given deduced type. + QualType RebuildAutoType(QualType Deduced) { + return SemaRef.Context.getAutoType(Deduced); + } + + /// \brief Build a new template specialization type. + /// + /// By default, performs semantic analysis when building the template + /// specialization type. Subclasses may override this routine to provide + /// different behavior. + QualType RebuildTemplateSpecializationType(TemplateName Template, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &Args); + + /// \brief Build a new parenthesized type. + /// + /// By default, builds a new ParenType type from the inner type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildParenType(QualType InnerType) { + return SemaRef.Context.getParenType(InnerType); + } + + /// \brief Build a new qualified name type. + /// + /// By default, builds a new ElaboratedType type from the keyword, + /// the nested-name-specifier and the named type. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildElaboratedType(SourceLocation KeywordLoc, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifierLoc QualifierLoc, + QualType Named) { + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Named); + } + + /// \brief Build a new typename type that refers to a template-id. + /// + /// By default, builds a new DependentNameType type from the + /// nested-name-specifier and the given type. Subclasses may override + /// this routine to provide different behavior. + QualType RebuildDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo *Name, + SourceLocation NameLoc, + TemplateArgumentListInfo &Args) { + // Rebuild the template name. + // TODO: avoid TemplateName abstraction + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + TemplateName InstName + = getDerived().RebuildTemplateName(SS, *Name, NameLoc, QualType(), 0); + + if (InstName.isNull()) + return QualType(); + + // If it's still dependent, make a dependent specialization. + if (InstName.getAsDependentTemplateName()) + return SemaRef.Context.getDependentTemplateSpecializationType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Name, + Args); + + // Otherwise, make an elaborated type wrapping a non-dependent + // specialization. + QualType T = + getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + if (T.isNull()) return QualType(); + + if (Keyword == ETK_None && QualifierLoc.getNestedNameSpecifier() == 0) + return T; + + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + T); + } + + /// \brief Build a new typename type that refers to an identifier. + /// + /// By default, performs semantic analysis when building the typename type + /// (or elaborated type). Subclasses may override this routine to provide + /// different behavior. + QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, + SourceLocation KeywordLoc, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo *Id, + SourceLocation IdLoc) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + if (QualifierLoc.getNestedNameSpecifier()->isDependent()) { + // If the name is still dependent, just build a new dependent name type. + if (!SemaRef.computeDeclContext(SS)) + return SemaRef.Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + Id); + } + + if (Keyword == ETK_None || Keyword == ETK_Typename) + return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, + *Id, IdLoc); + + TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); + + // We had a dependent elaborated-type-specifier that has been transformed + // into a non-dependent elaborated-type-specifier. Find the tag we're + // referring to. + LookupResult Result(SemaRef, Id, IdLoc, Sema::LookupTagName); + DeclContext *DC = SemaRef.computeDeclContext(SS, false); + if (!DC) + return QualType(); + + if (SemaRef.RequireCompleteDeclContext(SS, DC)) + return QualType(); + + TagDecl *Tag = 0; + SemaRef.LookupQualifiedName(Result, DC); + switch (Result.getResultKind()) { + case LookupResult::NotFound: + case LookupResult::NotFoundInCurrentInstantiation: + break; + + case LookupResult::Found: + Tag = Result.getAsSingle<TagDecl>(); + break; + + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: + llvm_unreachable("Tag lookup cannot find non-tags"); + return QualType(); + + case LookupResult::Ambiguous: + // Let the LookupResult structure handle ambiguities. + return QualType(); + } + + if (!Tag) { + // Check where the name exists but isn't a tag type and use that to emit + // better diagnostics. + LookupResult Result(SemaRef, Id, IdLoc, Sema::LookupTagName); + SemaRef.LookupQualifiedName(Result, DC); + switch (Result.getResultKind()) { + case LookupResult::Found: + case LookupResult::FoundOverloaded: + case LookupResult::FoundUnresolvedValue: { + NamedDecl *SomeDecl = Result.getRepresentativeDecl(); + unsigned Kind = 0; + if (isa<TypedefDecl>(SomeDecl)) Kind = 1; + else if (isa<TypeAliasDecl>(SomeDecl)) Kind = 2; + else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 3; + SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind; + SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at); + break; + } + default: + // FIXME: Would be nice to highlight just the source range. + SemaRef.Diag(IdLoc, diag::err_not_tag_in_scope) + << Kind << Id << DC; + break; + } + return QualType(); + } + + if (!SemaRef.isAcceptableTagRedeclaration(Tag, Kind, /*isDefinition*/false, + IdLoc, *Id)) { + SemaRef.Diag(KeywordLoc, diag::err_use_with_wrong_tag) << Id; + SemaRef.Diag(Tag->getLocation(), diag::note_previous_use); + return QualType(); + } + + // Build the elaborated-type-specifier type. + QualType T = SemaRef.Context.getTypeDeclType(Tag); + return SemaRef.Context.getElaboratedType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + T); + } + + /// \brief Build a new pack expansion type. + /// + /// By default, builds a new PackExpansionType type from the given pattern. + /// Subclasses may override this routine to provide different behavior. + QualType RebuildPackExpansionType(QualType Pattern, + SourceRange PatternRange, + SourceLocation EllipsisLoc, + llvm::Optional<unsigned> NumExpansions) { + return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc, + NumExpansions); + } + + /// \brief Build a new template name given a nested name specifier, a flag + /// indicating whether the "template" keyword was provided, and the template + /// that the template name refers to. + /// + /// By default, builds the new template name directly. Subclasses may override + /// this routine to provide different behavior. + TemplateName RebuildTemplateName(CXXScopeSpec &SS, + bool TemplateKW, + TemplateDecl *Template); + + /// \brief Build a new template name given a nested name specifier and the + /// name that is referred to as a template. + /// + /// By default, performs semantic analysis to determine whether the name can + /// be resolved to a specific template, then builds the appropriate kind of + /// template name. Subclasses may override this routine to provide different + /// behavior. + TemplateName RebuildTemplateName(CXXScopeSpec &SS, + const IdentifierInfo &Name, + SourceLocation NameLoc, + QualType ObjectType, + NamedDecl *FirstQualifierInScope); + + /// \brief Build a new template name given a nested name specifier and the + /// overloaded operator name that is referred to as a template. + /// + /// By default, performs semantic analysis to determine whether the name can + /// be resolved to a specific template, then builds the appropriate kind of + /// template name. Subclasses may override this routine to provide different + /// behavior. + TemplateName RebuildTemplateName(CXXScopeSpec &SS, + OverloadedOperatorKind Operator, + SourceLocation NameLoc, + QualType ObjectType); + + /// \brief Build a new template name given a template template parameter pack + /// and the + /// + /// By default, performs semantic analysis to determine whether the name can + /// be resolved to a specific template, then builds the appropriate kind of + /// template name. Subclasses may override this routine to provide different + /// behavior. + TemplateName RebuildTemplateName(TemplateTemplateParmDecl *Param, + const TemplateArgument &ArgPack) { + return getSema().Context.getSubstTemplateTemplateParmPack(Param, ArgPack); + } + + /// \brief Build a new compound statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCompoundStmt(SourceLocation LBraceLoc, + MultiStmtArg Statements, + SourceLocation RBraceLoc, + bool IsStmtExpr) { + return getSema().ActOnCompoundStmt(LBraceLoc, RBraceLoc, Statements, + IsStmtExpr); + } + + /// \brief Build a new case statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCaseStmt(SourceLocation CaseLoc, + Expr *LHS, + SourceLocation EllipsisLoc, + Expr *RHS, + SourceLocation ColonLoc) { + return getSema().ActOnCaseStmt(CaseLoc, LHS, EllipsisLoc, RHS, + ColonLoc); + } + + /// \brief Attach the body to a new case statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCaseStmtBody(Stmt *S, Stmt *Body) { + getSema().ActOnCaseStmtBody(S, Body); + return S; + } + + /// \brief Build a new default statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildDefaultStmt(SourceLocation DefaultLoc, + SourceLocation ColonLoc, + Stmt *SubStmt) { + return getSema().ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt, + /*CurScope=*/0); + } + + /// \brief Build a new label statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildLabelStmt(SourceLocation IdentLoc, LabelDecl *L, + SourceLocation ColonLoc, Stmt *SubStmt) { + return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt); + } + + /// \brief Build a new "if" statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond, + VarDecl *CondVar, Stmt *Then, + SourceLocation ElseLoc, Stmt *Else) { + return getSema().ActOnIfStmt(IfLoc, Cond, CondVar, Then, ElseLoc, Else); + } + + /// \brief Start building a new switch statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildSwitchStmtStart(SourceLocation SwitchLoc, + Expr *Cond, VarDecl *CondVar) { + return getSema().ActOnStartOfSwitchStmt(SwitchLoc, Cond, + CondVar); + } + + /// \brief Attach the body to the switch statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildSwitchStmtBody(SourceLocation SwitchLoc, + Stmt *Switch, Stmt *Body) { + return getSema().ActOnFinishSwitchStmt(SwitchLoc, Switch, Body); + } + + /// \brief Build a new while statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildWhileStmt(SourceLocation WhileLoc, Sema::FullExprArg Cond, + VarDecl *CondVar, Stmt *Body) { + return getSema().ActOnWhileStmt(WhileLoc, Cond, CondVar, Body); + } + + /// \brief Build a new do-while statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildDoStmt(SourceLocation DoLoc, Stmt *Body, + SourceLocation WhileLoc, SourceLocation LParenLoc, + Expr *Cond, SourceLocation RParenLoc) { + return getSema().ActOnDoStmt(DoLoc, Body, WhileLoc, LParenLoc, + Cond, RParenLoc); + } + + /// \brief Build a new for statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, + Stmt *Init, Sema::FullExprArg Cond, + VarDecl *CondVar, Sema::FullExprArg Inc, + SourceLocation RParenLoc, Stmt *Body) { + return getSema().ActOnForStmt(ForLoc, LParenLoc, Init, Cond, + CondVar, Inc, RParenLoc, Body); + } + + /// \brief Build a new goto statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, + LabelDecl *Label) { + return getSema().ActOnGotoStmt(GotoLoc, LabelLoc, Label); + } + + /// \brief Build a new indirect goto statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildIndirectGotoStmt(SourceLocation GotoLoc, + SourceLocation StarLoc, + Expr *Target) { + return getSema().ActOnIndirectGotoStmt(GotoLoc, StarLoc, Target); + } + + /// \brief Build a new return statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildReturnStmt(SourceLocation ReturnLoc, Expr *Result) { + return getSema().ActOnReturnStmt(ReturnLoc, Result); + } + + /// \brief Build a new declaration statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildDeclStmt(Decl **Decls, unsigned NumDecls, + SourceLocation StartLoc, + SourceLocation EndLoc) { + Sema::DeclGroupPtrTy DG = getSema().BuildDeclaratorGroup(Decls, NumDecls); + return getSema().ActOnDeclStmt(DG, StartLoc, EndLoc); + } + + /// \brief Build a new inline asm statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildAsmStmt(SourceLocation AsmLoc, + bool IsSimple, + bool IsVolatile, + unsigned NumOutputs, + unsigned NumInputs, + IdentifierInfo **Names, + MultiExprArg Constraints, + MultiExprArg Exprs, + Expr *AsmString, + MultiExprArg Clobbers, + SourceLocation RParenLoc, + bool MSAsm) { + return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, + NumInputs, Names, move(Constraints), + Exprs, AsmString, Clobbers, + RParenLoc, MSAsm); + } + + /// \brief Build a new Objective-C @try statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildObjCAtTryStmt(SourceLocation AtLoc, + Stmt *TryBody, + MultiStmtArg CatchStmts, + Stmt *Finally) { + return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, move(CatchStmts), + Finally); + } + + /// \brief Rebuild an Objective-C exception declaration. + /// + /// By default, performs semantic analysis to build the new declaration. + /// Subclasses may override this routine to provide different behavior. + VarDecl *RebuildObjCExceptionDecl(VarDecl *ExceptionDecl, + TypeSourceInfo *TInfo, QualType T) { + return getSema().BuildObjCExceptionDecl(TInfo, T, + ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), + ExceptionDecl->getIdentifier()); + } + + /// \brief Build a new Objective-C @catch statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildObjCAtCatchStmt(SourceLocation AtLoc, + SourceLocation RParenLoc, + VarDecl *Var, + Stmt *Body) { + return getSema().ActOnObjCAtCatchStmt(AtLoc, RParenLoc, + Var, Body); + } + + /// \brief Build a new Objective-C @finally statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildObjCAtFinallyStmt(SourceLocation AtLoc, + Stmt *Body) { + return getSema().ActOnObjCAtFinallyStmt(AtLoc, Body); + } + + /// \brief Build a new Objective-C @throw statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildObjCAtThrowStmt(SourceLocation AtLoc, + Expr *Operand) { + return getSema().BuildObjCAtThrowStmt(AtLoc, Operand); + } + + /// \brief Build a new Objective-C @synchronized statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc, + Expr *Object, + Stmt *Body) { + return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, Object, + Body); + } + + /// \brief Build a new Objective-C fast enumeration statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildObjCForCollectionStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, + Stmt *Element, + Expr *Collection, + SourceLocation RParenLoc, + Stmt *Body) { + return getSema().ActOnObjCForCollectionStmt(ForLoc, LParenLoc, + Element, + Collection, + RParenLoc, + Body); + } + + /// \brief Build a new C++ exception declaration. + /// + /// By default, performs semantic analysis to build the new decaration. + /// Subclasses may override this routine to provide different behavior. + VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, + TypeSourceInfo *Declarator, + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id) { + VarDecl *Var = getSema().BuildExceptionDeclaration(0, Declarator, + StartLoc, IdLoc, Id); + if (Var) + getSema().CurContext->addDecl(Var); + return Var; + } + + /// \brief Build a new C++ catch statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCXXCatchStmt(SourceLocation CatchLoc, + VarDecl *ExceptionDecl, + Stmt *Handler) { + return Owned(new (getSema().Context) CXXCatchStmt(CatchLoc, ExceptionDecl, + Handler)); + } + + /// \brief Build a new C++ try statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCXXTryStmt(SourceLocation TryLoc, + Stmt *TryBlock, + MultiStmtArg Handlers) { + return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers)); + } + + /// \brief Build a new C++0x range-based for statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult RebuildCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation ColonLoc, + Stmt *Range, Stmt *BeginEnd, + Expr *Cond, Expr *Inc, + Stmt *LoopVar, + SourceLocation RParenLoc) { + return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd, + Cond, Inc, LoopVar, RParenLoc); + } + + /// \brief Attach body to a C++0x range-based for statement. + /// + /// By default, performs semantic analysis to finish the new statement. + /// Subclasses may override this routine to provide different behavior. + StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body) { + return getSema().FinishCXXForRangeStmt(ForRange, Body); + } + + StmtResult RebuildSEHTryStmt(bool IsCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler) { + return getSema().ActOnSEHTryBlock(IsCXXTry,TryLoc,TryBlock,Handler); + } + + StmtResult RebuildSEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block) { + return getSema().ActOnSEHExceptBlock(Loc,FilterExpr,Block); + } + + StmtResult RebuildSEHFinallyStmt(SourceLocation Loc, + Stmt *Block) { + return getSema().ActOnSEHFinallyBlock(Loc,Block); + } + + /// \brief Build a new expression that references a declaration. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildDeclarationNameExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL) { + return getSema().BuildDeclarationNameExpr(SS, R, RequiresADL); + } + + + /// \brief Build a new expression that references a declaration. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildDeclRefExpr(NestedNameSpecifierLoc QualifierLoc, + ValueDecl *VD, + const DeclarationNameInfo &NameInfo, + TemplateArgumentListInfo *TemplateArgs) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + // FIXME: loses template args. + + return getSema().BuildDeclarationNameExpr(SS, NameInfo, VD); + } + + /// \brief Build a new expression in parentheses. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildParenExpr(Expr *SubExpr, SourceLocation LParen, + SourceLocation RParen) { + return getSema().ActOnParenExpr(LParen, RParen, SubExpr); + } + + /// \brief Build a new pseudo-destructor expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXPseudoDestructorExpr(Expr *Base, + SourceLocation OperatorLoc, + bool isArrow, + CXXScopeSpec &SS, + TypeSourceInfo *ScopeType, + SourceLocation CCLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage Destroyed); + + /// \brief Build a new unary operator expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildUnaryOperator(SourceLocation OpLoc, + UnaryOperatorKind Opc, + Expr *SubExpr) { + return getSema().BuildUnaryOp(/*Scope=*/0, OpLoc, Opc, SubExpr); + } + + /// \brief Build a new builtin offsetof expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildOffsetOfExpr(SourceLocation OperatorLoc, + TypeSourceInfo *Type, + Sema::OffsetOfComponent *Components, + unsigned NumComponents, + SourceLocation RParenLoc) { + return getSema().BuildBuiltinOffsetOf(OperatorLoc, Type, Components, + NumComponents, RParenLoc); + } + + /// \brief Build a new sizeof, alignof or vec_step expression with a + /// type argument. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildUnaryExprOrTypeTrait(TypeSourceInfo *TInfo, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { + return getSema().CreateUnaryExprOrTypeTraitExpr(TInfo, OpLoc, ExprKind, R); + } + + /// \brief Build a new sizeof, alignof or vec step expression with an + /// expression argument. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildUnaryExprOrTypeTrait(Expr *SubExpr, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R) { + ExprResult Result + = getSema().CreateUnaryExprOrTypeTraitExpr(SubExpr, OpLoc, ExprKind); + if (Result.isInvalid()) + return ExprError(); + + return move(Result); + } + + /// \brief Build a new array subscript expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildArraySubscriptExpr(Expr *LHS, + SourceLocation LBracketLoc, + Expr *RHS, + SourceLocation RBracketLoc) { + return getSema().ActOnArraySubscriptExpr(/*Scope=*/0, LHS, + LBracketLoc, RHS, + RBracketLoc); + } + + /// \brief Build a new call expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCallExpr(Expr *Callee, SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation RParenLoc, + Expr *ExecConfig = 0) { + return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc, + move(Args), RParenLoc, ExecConfig); + } + + /// \brief Build a new member access expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildMemberExpr(Expr *Base, SourceLocation OpLoc, + bool isArrow, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &MemberNameInfo, + ValueDecl *Member, + NamedDecl *FoundDecl, + const TemplateArgumentListInfo *ExplicitTemplateArgs, + NamedDecl *FirstQualifierInScope) { + if (!Member->getDeclName()) { + // We have a reference to an unnamed field. This is always the + // base of an anonymous struct/union member access, i.e. the + // field is always of record type. + assert(!QualifierLoc && "Can't have an unnamed field with a qualifier!"); + assert(Member->getType()->isRecordType() && + "unnamed member not of record type?"); + + ExprResult BaseResult = + getSema().PerformObjectMemberConversion(Base, + QualifierLoc.getNestedNameSpecifier(), + FoundDecl, Member); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + ExprValueKind VK = isArrow ? VK_LValue : Base->getValueKind(); + MemberExpr *ME = + new (getSema().Context) MemberExpr(Base, isArrow, + Member, MemberNameInfo, + cast<FieldDecl>(Member)->getType(), + VK, OK_Ordinary); + return getSema().Owned(ME); + } + + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + ExprResult BaseResult = getSema().DefaultFunctionArrayConversion(Base); + if (BaseResult.isInvalid()) + return ExprError(); + Base = BaseResult.take(); + QualType BaseType = Base->getType(); + + // FIXME: this involves duplicating earlier analysis in a lot of + // cases; we should avoid this when possible. + LookupResult R(getSema(), MemberNameInfo, Sema::LookupMemberName); + R.addDecl(FoundDecl); + R.resolveKind(); + + return getSema().BuildMemberReferenceExpr(Base, BaseType, OpLoc, isArrow, + SS, FirstQualifierInScope, + R, ExplicitTemplateArgs); + } + + /// \brief Build a new binary operator expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildBinaryOperator(SourceLocation OpLoc, + BinaryOperatorKind Opc, + Expr *LHS, Expr *RHS) { + return getSema().BuildBinOp(/*Scope=*/0, OpLoc, Opc, LHS, RHS); + } + + /// \brief Build a new conditional operator expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildConditionalOperator(Expr *Cond, + SourceLocation QuestionLoc, + Expr *LHS, + SourceLocation ColonLoc, + Expr *RHS) { + return getSema().ActOnConditionalOp(QuestionLoc, ColonLoc, Cond, + LHS, RHS); + } + + /// \brief Build a new C-style cast expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCStyleCastExpr(SourceLocation LParenLoc, + TypeSourceInfo *TInfo, + SourceLocation RParenLoc, + Expr *SubExpr) { + return getSema().BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, + SubExpr); + } + + /// \brief Build a new compound literal expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCompoundLiteralExpr(SourceLocation LParenLoc, + TypeSourceInfo *TInfo, + SourceLocation RParenLoc, + Expr *Init) { + return getSema().BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, + Init); + } + + /// \brief Build a new extended vector element access expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildExtVectorElementExpr(Expr *Base, + SourceLocation OpLoc, + SourceLocation AccessorLoc, + IdentifierInfo &Accessor) { + + CXXScopeSpec SS; + DeclarationNameInfo NameInfo(&Accessor, AccessorLoc); + return getSema().BuildMemberReferenceExpr(Base, Base->getType(), + OpLoc, /*IsArrow*/ false, + SS, /*FirstQualifierInScope*/ 0, + NameInfo, + /* TemplateArgs */ 0); + } + + /// \brief Build a new initializer list expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildInitList(SourceLocation LBraceLoc, + MultiExprArg Inits, + SourceLocation RBraceLoc, + QualType ResultTy) { + ExprResult Result + = SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc); + if (Result.isInvalid() || ResultTy->isDependentType()) + return move(Result); + + // Patch in the result type we were given, which may have been computed + // when the initial InitListExpr was built. + InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get()); + ILE->setType(ResultTy); + return move(Result); + } + + /// \brief Build a new designated initializer expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildDesignatedInitExpr(Designation &Desig, + MultiExprArg ArrayExprs, + SourceLocation EqualOrColonLoc, + bool GNUSyntax, + Expr *Init) { + ExprResult Result + = SemaRef.ActOnDesignatedInitializer(Desig, EqualOrColonLoc, GNUSyntax, + Init); + if (Result.isInvalid()) + return ExprError(); + + ArrayExprs.release(); + return move(Result); + } + + /// \brief Build a new value-initialized expression. + /// + /// By default, builds the implicit value initialization without performing + /// any semantic analysis. Subclasses may override this routine to provide + /// different behavior. + ExprResult RebuildImplicitValueInitExpr(QualType T) { + return SemaRef.Owned(new (SemaRef.Context) ImplicitValueInitExpr(T)); + } + + /// \brief Build a new \c va_arg expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildVAArgExpr(SourceLocation BuiltinLoc, + Expr *SubExpr, TypeSourceInfo *TInfo, + SourceLocation RParenLoc) { + return getSema().BuildVAArgExpr(BuiltinLoc, + SubExpr, TInfo, + RParenLoc); + } + + /// \brief Build a new expression list in parentheses. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildParenListExpr(SourceLocation LParenLoc, + MultiExprArg SubExprs, + SourceLocation RParenLoc) { + return getSema().ActOnParenOrParenListExpr(LParenLoc, RParenLoc, + move(SubExprs)); + } + + /// \brief Build a new address-of-label expression. + /// + /// By default, performs semantic analysis, using the name of the label + /// rather than attempting to map the label statement itself. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildAddrLabelExpr(SourceLocation AmpAmpLoc, + SourceLocation LabelLoc, LabelDecl *Label) { + return getSema().ActOnAddrLabel(AmpAmpLoc, LabelLoc, Label); + } + + /// \brief Build a new GNU statement expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildStmtExpr(SourceLocation LParenLoc, + Stmt *SubStmt, + SourceLocation RParenLoc) { + return getSema().ActOnStmtExpr(LParenLoc, SubStmt, RParenLoc); + } + + /// \brief Build a new __builtin_choose_expr expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildChooseExpr(SourceLocation BuiltinLoc, + Expr *Cond, Expr *LHS, Expr *RHS, + SourceLocation RParenLoc) { + return SemaRef.ActOnChooseExpr(BuiltinLoc, + Cond, LHS, RHS, + RParenLoc); + } + + /// \brief Build a new generic selection expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs) { + return getSema().CreateGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr, Types, Exprs, + NumAssocs); + } + + /// \brief Build a new overloaded operator call expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// The semantic analysis provides the behavior of template instantiation, + /// copying with transformations that turn what looks like an overloaded + /// operator call into a use of a builtin operator, performing + /// argument-dependent lookup, etc. Subclasses may override this routine to + /// provide different behavior. + ExprResult RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr *Callee, + Expr *First, + Expr *Second); + + /// \brief Build a new C++ "named" cast expression, such as static_cast or + /// reinterpret_cast. + /// + /// By default, this routine dispatches to one of the more-specific routines + /// for a particular named case, e.g., RebuildCXXStaticCastExpr(). + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXNamedCastExpr(SourceLocation OpLoc, + Stmt::StmtClass Class, + SourceLocation LAngleLoc, + TypeSourceInfo *TInfo, + SourceLocation RAngleLoc, + SourceLocation LParenLoc, + Expr *SubExpr, + SourceLocation RParenLoc) { + switch (Class) { + case Stmt::CXXStaticCastExprClass: + return getDerived().RebuildCXXStaticCastExpr(OpLoc, LAngleLoc, TInfo, + RAngleLoc, LParenLoc, + SubExpr, RParenLoc); + + case Stmt::CXXDynamicCastExprClass: + return getDerived().RebuildCXXDynamicCastExpr(OpLoc, LAngleLoc, TInfo, + RAngleLoc, LParenLoc, + SubExpr, RParenLoc); + + case Stmt::CXXReinterpretCastExprClass: + return getDerived().RebuildCXXReinterpretCastExpr(OpLoc, LAngleLoc, TInfo, + RAngleLoc, LParenLoc, + SubExpr, + RParenLoc); + + case Stmt::CXXConstCastExprClass: + return getDerived().RebuildCXXConstCastExpr(OpLoc, LAngleLoc, TInfo, + RAngleLoc, LParenLoc, + SubExpr, RParenLoc); + + default: + assert(false && "Invalid C++ named cast"); + break; + } + + return ExprError(); + } + + /// \brief Build a new C++ static_cast expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXStaticCastExpr(SourceLocation OpLoc, + SourceLocation LAngleLoc, + TypeSourceInfo *TInfo, + SourceLocation RAngleLoc, + SourceLocation LParenLoc, + Expr *SubExpr, + SourceLocation RParenLoc) { + return getSema().BuildCXXNamedCast(OpLoc, tok::kw_static_cast, + TInfo, SubExpr, + SourceRange(LAngleLoc, RAngleLoc), + SourceRange(LParenLoc, RParenLoc)); + } + + /// \brief Build a new C++ dynamic_cast expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXDynamicCastExpr(SourceLocation OpLoc, + SourceLocation LAngleLoc, + TypeSourceInfo *TInfo, + SourceLocation RAngleLoc, + SourceLocation LParenLoc, + Expr *SubExpr, + SourceLocation RParenLoc) { + return getSema().BuildCXXNamedCast(OpLoc, tok::kw_dynamic_cast, + TInfo, SubExpr, + SourceRange(LAngleLoc, RAngleLoc), + SourceRange(LParenLoc, RParenLoc)); + } + + /// \brief Build a new C++ reinterpret_cast expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXReinterpretCastExpr(SourceLocation OpLoc, + SourceLocation LAngleLoc, + TypeSourceInfo *TInfo, + SourceLocation RAngleLoc, + SourceLocation LParenLoc, + Expr *SubExpr, + SourceLocation RParenLoc) { + return getSema().BuildCXXNamedCast(OpLoc, tok::kw_reinterpret_cast, + TInfo, SubExpr, + SourceRange(LAngleLoc, RAngleLoc), + SourceRange(LParenLoc, RParenLoc)); + } + + /// \brief Build a new C++ const_cast expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXConstCastExpr(SourceLocation OpLoc, + SourceLocation LAngleLoc, + TypeSourceInfo *TInfo, + SourceLocation RAngleLoc, + SourceLocation LParenLoc, + Expr *SubExpr, + SourceLocation RParenLoc) { + return getSema().BuildCXXNamedCast(OpLoc, tok::kw_const_cast, + TInfo, SubExpr, + SourceRange(LAngleLoc, RAngleLoc), + SourceRange(LParenLoc, RParenLoc)); + } + + /// \brief Build a new C++ functional-style cast expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, + SourceLocation LParenLoc, + Expr *Sub, + SourceLocation RParenLoc) { + return getSema().BuildCXXTypeConstructExpr(TInfo, LParenLoc, + MultiExprArg(&Sub, 1), + RParenLoc); + } + + /// \brief Build a new C++ typeid(type) expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, Operand, + RParenLoc); + } + + + /// \brief Build a new C++ typeid(expr) expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXTypeidExpr(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *Operand, + SourceLocation RParenLoc) { + return getSema().BuildCXXTypeId(TypeInfoType, TypeidLoc, Operand, + RParenLoc); + } + + /// \brief Build a new C++ __uuidof(type) expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType, + SourceLocation TypeidLoc, + TypeSourceInfo *Operand, + SourceLocation RParenLoc) { + return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand, + RParenLoc); + } + + /// \brief Build a new C++ __uuidof(expr) expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXUuidofExpr(QualType TypeInfoType, + SourceLocation TypeidLoc, + Expr *Operand, + SourceLocation RParenLoc) { + return getSema().BuildCXXUuidof(TypeInfoType, TypeidLoc, Operand, + RParenLoc); + } + + /// \brief Build a new C++ "this" expression. + /// + /// By default, builds a new "this" expression without performing any + /// semantic analysis. Subclasses may override this routine to provide + /// different behavior. + ExprResult RebuildCXXThisExpr(SourceLocation ThisLoc, + QualType ThisType, + bool isImplicit) { + return getSema().Owned( + new (getSema().Context) CXXThisExpr(ThisLoc, ThisType, + isImplicit)); + } + + /// \brief Build a new C++ throw expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXThrowExpr(SourceLocation ThrowLoc, Expr *Sub) { + return getSema().ActOnCXXThrow(ThrowLoc, Sub); + } + + /// \brief Build a new C++ default-argument expression. + /// + /// By default, builds a new default-argument expression, which does not + /// require any semantic analysis. Subclasses may override this routine to + /// provide different behavior. + ExprResult RebuildCXXDefaultArgExpr(SourceLocation Loc, + ParmVarDecl *Param) { + return getSema().Owned(CXXDefaultArgExpr::Create(getSema().Context, Loc, + Param)); + } + + /// \brief Build a new C++ zero-initialization expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXScalarValueInitExpr(TypeSourceInfo *TSInfo, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, + MultiExprArg(getSema(), 0, 0), + RParenLoc); + } + + /// \brief Build a new C++ "new" expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXNewExpr(SourceLocation StartLoc, + bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + SourceRange TypeIdParens, + QualType AllocatedType, + TypeSourceInfo *AllocatedTypeInfo, + Expr *ArraySize, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen) { + return getSema().BuildCXXNew(StartLoc, UseGlobal, + PlacementLParen, + move(PlacementArgs), + PlacementRParen, + TypeIdParens, + AllocatedType, + AllocatedTypeInfo, + ArraySize, + ConstructorLParen, + move(ConstructorArgs), + ConstructorRParen); + } + + /// \brief Build a new C++ "delete" expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXDeleteExpr(SourceLocation StartLoc, + bool IsGlobalDelete, + bool IsArrayForm, + Expr *Operand) { + return getSema().ActOnCXXDelete(StartLoc, IsGlobalDelete, IsArrayForm, + Operand); + } + + /// \brief Build a new unary type trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildUnaryTypeTrait(UnaryTypeTrait Trait, + SourceLocation StartLoc, + TypeSourceInfo *T, + SourceLocation RParenLoc) { + return getSema().BuildUnaryTypeTrait(Trait, StartLoc, T, RParenLoc); + } + + /// \brief Build a new binary type trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildBinaryTypeTrait(BinaryTypeTrait Trait, + SourceLocation StartLoc, + TypeSourceInfo *LhsT, + TypeSourceInfo *RhsT, + SourceLocation RParenLoc) { + return getSema().BuildBinaryTypeTrait(Trait, StartLoc, LhsT, RhsT, RParenLoc); + } + + /// \brief Build a new array type trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildArrayTypeTrait(ArrayTypeTrait Trait, + SourceLocation StartLoc, + TypeSourceInfo *TSInfo, + Expr *DimExpr, + SourceLocation RParenLoc) { + return getSema().BuildArrayTypeTrait(Trait, StartLoc, TSInfo, DimExpr, RParenLoc); + } + + /// \brief Build a new expression trait expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildExpressionTrait(ExpressionTrait Trait, + SourceLocation StartLoc, + Expr *Queried, + SourceLocation RParenLoc) { + return getSema().BuildExpressionTrait(Trait, StartLoc, Queried, RParenLoc); + } + + /// \brief Build a new (previously unresolved) declaration reference + /// expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildDependentScopeDeclRefExpr( + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + if (TemplateArgs) + return getSema().BuildQualifiedTemplateIdExpr(SS, NameInfo, + *TemplateArgs); + + return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo); + } + + /// \brief Build a new template-id expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs) { + return getSema().BuildTemplateIdExpr(SS, R, RequiresADL, TemplateArgs); + } + + /// \brief Build a new object-construction expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXConstructExpr(QualType T, + SourceLocation Loc, + CXXConstructorDecl *Constructor, + bool IsElidable, + MultiExprArg Args, + bool RequiresZeroInit, + CXXConstructExpr::ConstructionKind ConstructKind, + SourceRange ParenRange) { + ASTOwningVector<Expr*> ConvertedArgs(SemaRef); + if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc, + ConvertedArgs)) + return ExprError(); + + return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable, + move_arg(ConvertedArgs), + RequiresZeroInit, ConstructKind, + ParenRange); + } + + /// \brief Build a new object-construction expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXTemporaryObjectExpr(TypeSourceInfo *TSInfo, + SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation RParenLoc) { + return getSema().BuildCXXTypeConstructExpr(TSInfo, + LParenLoc, + move(Args), + RParenLoc); + } + + /// \brief Build a new object-construction expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXUnresolvedConstructExpr(TypeSourceInfo *TSInfo, + SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation RParenLoc) { + return getSema().BuildCXXTypeConstructExpr(TSInfo, + LParenLoc, + move(Args), + RParenLoc); + } + + /// \brief Build a new member reference expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXDependentScopeMemberExpr(Expr *BaseE, + QualType BaseType, + bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, + NamedDecl *FirstQualifierInScope, + const DeclarationNameInfo &MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, + OperatorLoc, IsArrow, + SS, FirstQualifierInScope, + MemberNameInfo, + TemplateArgs); + } + + /// \brief Build a new member reference expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildUnresolvedMemberExpr(Expr *BaseE, + QualType BaseType, + SourceLocation OperatorLoc, + bool IsArrow, + NestedNameSpecifierLoc QualifierLoc, + NamedDecl *FirstQualifierInScope, + LookupResult &R, + const TemplateArgumentListInfo *TemplateArgs) { + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + return SemaRef.BuildMemberReferenceExpr(BaseE, BaseType, + OperatorLoc, IsArrow, + SS, FirstQualifierInScope, + R, TemplateArgs); + } + + /// \brief Build a new noexcept expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildCXXNoexceptExpr(SourceRange Range, Expr *Arg) { + return SemaRef.BuildCXXNoexceptExpr(Range.getBegin(), Arg, Range.getEnd()); + } + + /// \brief Build a new expression to compute the length of a parameter pack. + ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack, + SourceLocation PackLoc, + SourceLocation RParenLoc, + unsigned Length) { + return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), + OperatorLoc, Pack, PackLoc, + RParenLoc, Length); + } + + /// \brief Build a new Objective-C @encode expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildObjCEncodeExpr(SourceLocation AtLoc, + TypeSourceInfo *EncodeTypeInfo, + SourceLocation RParenLoc) { + return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(AtLoc, EncodeTypeInfo, + RParenLoc)); + } + + /// \brief Build a new Objective-C class message. + ExprResult RebuildObjCMessageExpr(TypeSourceInfo *ReceiverTypeInfo, + Selector Sel, + SourceLocation SelectorLoc, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + MultiExprArg Args, + SourceLocation RBracLoc) { + return SemaRef.BuildClassMessage(ReceiverTypeInfo, + ReceiverTypeInfo->getType(), + /*SuperLoc=*/SourceLocation(), + Sel, Method, LBracLoc, SelectorLoc, + RBracLoc, move(Args)); + } + + /// \brief Build a new Objective-C instance message. + ExprResult RebuildObjCMessageExpr(Expr *Receiver, + Selector Sel, + SourceLocation SelectorLoc, + ObjCMethodDecl *Method, + SourceLocation LBracLoc, + MultiExprArg Args, + SourceLocation RBracLoc) { + return SemaRef.BuildInstanceMessage(Receiver, + Receiver->getType(), + /*SuperLoc=*/SourceLocation(), + Sel, Method, LBracLoc, SelectorLoc, + RBracLoc, move(Args)); + } + + /// \brief Build a new Objective-C ivar reference expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildObjCIvarRefExpr(Expr *BaseArg, ObjCIvarDecl *Ivar, + SourceLocation IvarLoc, + bool IsArrow, bool IsFreeIvar) { + // FIXME: We lose track of the IsFreeIvar bit. + CXXScopeSpec SS; + ExprResult Base = getSema().Owned(BaseArg); + LookupResult R(getSema(), Ivar->getDeclName(), IvarLoc, + Sema::LookupMemberName); + ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, + /*FIME:*/IvarLoc, + SS, 0, + false); + if (Result.isInvalid() || Base.isInvalid()) + return ExprError(); + + if (Result.get()) + return move(Result); + + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), + /*FIXME:*/IvarLoc, IsArrow, SS, + /*FirstQualifierInScope=*/0, + R, + /*TemplateArgs=*/0); + } + + /// \brief Build a new Objective-C property reference expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildObjCPropertyRefExpr(Expr *BaseArg, + ObjCPropertyDecl *Property, + SourceLocation PropertyLoc) { + CXXScopeSpec SS; + ExprResult Base = getSema().Owned(BaseArg); + LookupResult R(getSema(), Property->getDeclName(), PropertyLoc, + Sema::LookupMemberName); + bool IsArrow = false; + ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, + /*FIME:*/PropertyLoc, + SS, 0, false); + if (Result.isInvalid() || Base.isInvalid()) + return ExprError(); + + if (Result.get()) + return move(Result); + + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), + /*FIXME:*/PropertyLoc, IsArrow, + SS, + /*FirstQualifierInScope=*/0, + R, + /*TemplateArgs=*/0); + } + + /// \brief Build a new Objective-C property reference expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildObjCPropertyRefExpr(Expr *Base, QualType T, + ObjCMethodDecl *Getter, + ObjCMethodDecl *Setter, + SourceLocation PropertyLoc) { + // Since these expressions can only be value-dependent, we do not + // need to perform semantic analysis again. + return Owned( + new (getSema().Context) ObjCPropertyRefExpr(Getter, Setter, T, + VK_LValue, OK_ObjCProperty, + PropertyLoc, Base)); + } + + /// \brief Build a new Objective-C "isa" expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildObjCIsaExpr(Expr *BaseArg, SourceLocation IsaLoc, + bool IsArrow) { + CXXScopeSpec SS; + ExprResult Base = getSema().Owned(BaseArg); + LookupResult R(getSema(), &getSema().Context.Idents.get("isa"), IsaLoc, + Sema::LookupMemberName); + ExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, + /*FIME:*/IsaLoc, + SS, 0, false); + if (Result.isInvalid() || Base.isInvalid()) + return ExprError(); + + if (Result.get()) + return move(Result); + + return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), + /*FIXME:*/IsaLoc, IsArrow, SS, + /*FirstQualifierInScope=*/0, + R, + /*TemplateArgs=*/0); + } + + /// \brief Build a new shuffle vector expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildShuffleVectorExpr(SourceLocation BuiltinLoc, + MultiExprArg SubExprs, + SourceLocation RParenLoc) { + // Find the declaration for __builtin_shufflevector + const IdentifierInfo &Name + = SemaRef.Context.Idents.get("__builtin_shufflevector"); + TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl(); + DeclContext::lookup_result Lookup = TUDecl->lookup(DeclarationName(&Name)); + assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?"); + + // Build a reference to the __builtin_shufflevector builtin + FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); + ExprResult Callee + = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), + VK_LValue, BuiltinLoc)); + Callee = SemaRef.UsualUnaryConversions(Callee.take()); + if (Callee.isInvalid()) + return ExprError(); + + // Build the CallExpr + unsigned NumSubExprs = SubExprs.size(); + Expr **Subs = (Expr **)SubExprs.release(); + ExprResult TheCall = SemaRef.Owned( + new (SemaRef.Context) CallExpr(SemaRef.Context, Callee.take(), + Subs, NumSubExprs, + Builtin->getCallResultType(), + Expr::getValueKindForType(Builtin->getResultType()), + RParenLoc)); + + // Type-check the __builtin_shufflevector expression. + return SemaRef.SemaBuiltinShuffleVector(cast<CallExpr>(TheCall.take())); + } + + /// \brief Build a new template argument pack expansion. + /// + /// By default, performs semantic analysis to build a new pack expansion + /// for a template argument. Subclasses may override this routine to provide + /// different behavior. + TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern, + SourceLocation EllipsisLoc, + llvm::Optional<unsigned> NumExpansions) { + switch (Pattern.getArgument().getKind()) { + case TemplateArgument::Expression: { + ExprResult Result + = getSema().CheckPackExpansion(Pattern.getSourceExpression(), + EllipsisLoc, NumExpansions); + if (Result.isInvalid()) + return TemplateArgumentLoc(); + + return TemplateArgumentLoc(Result.get(), Result.get()); + } + + case TemplateArgument::Template: + return TemplateArgumentLoc(TemplateArgument( + Pattern.getArgument().getAsTemplate(), + NumExpansions), + Pattern.getTemplateQualifierLoc(), + Pattern.getTemplateNameLoc(), + EllipsisLoc); + + case TemplateArgument::Null: + case TemplateArgument::Integral: + case TemplateArgument::Declaration: + case TemplateArgument::Pack: + case TemplateArgument::TemplateExpansion: + llvm_unreachable("Pack expansion pattern has no parameter packs"); + + case TemplateArgument::Type: + if (TypeSourceInfo *Expansion + = getSema().CheckPackExpansion(Pattern.getTypeSourceInfo(), + EllipsisLoc, + NumExpansions)) + return TemplateArgumentLoc(TemplateArgument(Expansion->getType()), + Expansion); + break; + } + + return TemplateArgumentLoc(); + } + + /// \brief Build a new expression pack expansion. + /// + /// By default, performs semantic analysis to build a new pack expansion + /// for an expression. Subclasses may override this routine to provide + /// different behavior. + ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, + llvm::Optional<unsigned> NumExpansions) { + return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions); + } + +private: + TypeLoc TransformTypeInObjectScope(TypeLoc TL, + QualType ObjectType, + NamedDecl *FirstQualifierInScope, + CXXScopeSpec &SS); + + TypeSourceInfo *TransformTypeInObjectScope(TypeSourceInfo *TSInfo, + QualType ObjectType, + NamedDecl *FirstQualifierInScope, + CXXScopeSpec &SS); +}; + +template<typename Derived> +StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { + if (!S) + return SemaRef.Owned(S); + + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: break; + + // Transform individual statement nodes +#define STMT(Node, Parent) \ + case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(S)); +#define ABSTRACT_STMT(Node) +#define EXPR(Node, Parent) +#include "clang/AST/StmtNodes.inc" + + // Transform expressions by calling TransformExpr. +#define STMT(Node, Parent) +#define ABSTRACT_STMT(Stmt) +#define EXPR(Node, Parent) case Stmt::Node##Class: +#include "clang/AST/StmtNodes.inc" + { + ExprResult E = getDerived().TransformExpr(cast<Expr>(S)); + if (E.isInvalid()) + return StmtError(); + + return getSema().ActOnExprStmt(getSema().MakeFullExpr(E.take())); + } + } + + return SemaRef.Owned(S); +} + + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) { + if (!E) + return SemaRef.Owned(E); + + switch (E->getStmtClass()) { + case Stmt::NoStmtClass: break; +#define STMT(Node, Parent) case Stmt::Node##Class: break; +#define ABSTRACT_STMT(Stmt) +#define EXPR(Node, Parent) \ + case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E)); +#include "clang/AST/StmtNodes.inc" + } + + return SemaRef.Owned(E); +} + +template<typename Derived> +bool TreeTransform<Derived>::TransformExprs(Expr **Inputs, + unsigned NumInputs, + bool IsCall, + llvm::SmallVectorImpl<Expr *> &Outputs, + bool *ArgChanged) { + for (unsigned I = 0; I != NumInputs; ++I) { + // If requested, drop call arguments that need to be dropped. + if (IsCall && getDerived().DropCallArgument(Inputs[I])) { + if (ArgChanged) + *ArgChanged = true; + + break; + } + + if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(Inputs[I])) { + Expr *Pattern = Expansion->getPattern(); + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional<unsigned> OrigNumExpansions + = Expansion->getNumExpansions(); + llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(), + Pattern->getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + Expand, RetainExpansion, + NumExpansions)) + return true; + + if (!Expand) { + // The transform has determined that we should perform a simple + // transformation on the pack expansion, producing another pack + // expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + ExprResult OutPattern = getDerived().TransformExpr(Pattern); + if (OutPattern.isInvalid()) + return true; + + ExprResult Out = getDerived().RebuildPackExpansion(OutPattern.get(), + Expansion->getEllipsisLoc(), + NumExpansions); + if (Out.isInvalid()) + return true; + + if (ArgChanged) + *ArgChanged = true; + Outputs.push_back(Out.get()); + continue; + } + + // The transform has determined that we should perform an elementwise + // expansion of the pattern. Do so. + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + ExprResult Out = getDerived().TransformExpr(Pattern); + if (Out.isInvalid()) + return true; + + if (Out.get()->containsUnexpandedParameterPack()) { + Out = RebuildPackExpansion(Out.get(), Expansion->getEllipsisLoc(), + OrigNumExpansions); + if (Out.isInvalid()) + return true; + } + + if (ArgChanged) + *ArgChanged = true; + Outputs.push_back(Out.get()); + } + + continue; + } + + ExprResult Result = getDerived().TransformExpr(Inputs[I]); + if (Result.isInvalid()) + return true; + + if (Result.get() != Inputs[I] && ArgChanged) + *ArgChanged = true; + + Outputs.push_back(Result.get()); + } + + return false; +} + +template<typename Derived> +NestedNameSpecifierLoc +TreeTransform<Derived>::TransformNestedNameSpecifierLoc( + NestedNameSpecifierLoc NNS, + QualType ObjectType, + NamedDecl *FirstQualifierInScope) { + llvm::SmallVector<NestedNameSpecifierLoc, 4> Qualifiers; + for (NestedNameSpecifierLoc Qualifier = NNS; Qualifier; + Qualifier = Qualifier.getPrefix()) + Qualifiers.push_back(Qualifier); + + CXXScopeSpec SS; + while (!Qualifiers.empty()) { + NestedNameSpecifierLoc Q = Qualifiers.pop_back_val(); + NestedNameSpecifier *QNNS = Q.getNestedNameSpecifier(); + + switch (QNNS->getKind()) { + case NestedNameSpecifier::Identifier: + if (SemaRef.BuildCXXNestedNameSpecifier(/*Scope=*/0, + *QNNS->getAsIdentifier(), + Q.getLocalBeginLoc(), + Q.getLocalEndLoc(), + ObjectType, false, SS, + FirstQualifierInScope, false)) + return NestedNameSpecifierLoc(); + + break; + + case NestedNameSpecifier::Namespace: { + NamespaceDecl *NS + = cast_or_null<NamespaceDecl>( + getDerived().TransformDecl( + Q.getLocalBeginLoc(), + QNNS->getAsNamespace())); + SS.Extend(SemaRef.Context, NS, Q.getLocalBeginLoc(), Q.getLocalEndLoc()); + break; + } + + case NestedNameSpecifier::NamespaceAlias: { + NamespaceAliasDecl *Alias + = cast_or_null<NamespaceAliasDecl>( + getDerived().TransformDecl(Q.getLocalBeginLoc(), + QNNS->getAsNamespaceAlias())); + SS.Extend(SemaRef.Context, Alias, Q.getLocalBeginLoc(), + Q.getLocalEndLoc()); + break; + } + + case NestedNameSpecifier::Global: + // There is no meaningful transformation that one could perform on the + // global scope. + SS.MakeGlobal(SemaRef.Context, Q.getBeginLoc()); + break; + + case NestedNameSpecifier::TypeSpecWithTemplate: + case NestedNameSpecifier::TypeSpec: { + TypeLoc TL = TransformTypeInObjectScope(Q.getTypeLoc(), ObjectType, + FirstQualifierInScope, SS); + + if (!TL) + return NestedNameSpecifierLoc(); + + if (TL.getType()->isDependentType() || TL.getType()->isRecordType() || + (SemaRef.getLangOptions().CPlusPlus0x && + TL.getType()->isEnumeralType())) { + assert(!TL.getType().hasLocalQualifiers() && + "Can't get cv-qualifiers here"); + SS.Extend(SemaRef.Context, /*FIXME:*/SourceLocation(), TL, + Q.getLocalEndLoc()); + break; + } + // If the nested-name-specifier is an invalid type def, don't emit an + // error because a previous error should have already been emitted. + TypedefTypeLoc* TTL = dyn_cast<TypedefTypeLoc>(&TL); + if (!TTL || !TTL->getTypedefNameDecl()->isInvalidDecl()) { + SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag) + << TL.getType() << SS.getRange(); + } + return NestedNameSpecifierLoc(); + } + } + + // The qualifier-in-scope and object type only apply to the leftmost entity. + FirstQualifierInScope = 0; + ObjectType = QualType(); + } + + // Don't rebuild the nested-name-specifier if we don't have to. + if (SS.getScopeRep() == NNS.getNestedNameSpecifier() && + !getDerived().AlwaysRebuild()) + return NNS; + + // If we can re-use the source-location data from the original + // nested-name-specifier, do so. + if (SS.location_size() == NNS.getDataLength() && + memcmp(SS.location_data(), NNS.getOpaqueData(), SS.location_size()) == 0) + return NestedNameSpecifierLoc(SS.getScopeRep(), NNS.getOpaqueData()); + + // Allocate new nested-name-specifier location information. + return SS.getWithLocInContext(SemaRef.Context); +} + +template<typename Derived> +DeclarationNameInfo +TreeTransform<Derived> +::TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo) { + DeclarationName Name = NameInfo.getName(); + if (!Name) + return DeclarationNameInfo(); + + switch (Name.getNameKind()) { + case DeclarationName::Identifier: + case DeclarationName::ObjCZeroArgSelector: + case DeclarationName::ObjCOneArgSelector: + case DeclarationName::ObjCMultiArgSelector: + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXLiteralOperatorName: + case DeclarationName::CXXUsingDirective: + return NameInfo; + + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + case DeclarationName::CXXConversionFunctionName: { + TypeSourceInfo *NewTInfo; + CanQualType NewCanTy; + if (TypeSourceInfo *OldTInfo = NameInfo.getNamedTypeInfo()) { + NewTInfo = getDerived().TransformType(OldTInfo); + if (!NewTInfo) + return DeclarationNameInfo(); + NewCanTy = SemaRef.Context.getCanonicalType(NewTInfo->getType()); + } + else { + NewTInfo = 0; + TemporaryBase Rebase(*this, NameInfo.getLoc(), Name); + QualType NewT = getDerived().TransformType(Name.getCXXNameType()); + if (NewT.isNull()) + return DeclarationNameInfo(); + NewCanTy = SemaRef.Context.getCanonicalType(NewT); + } + + DeclarationName NewName + = SemaRef.Context.DeclarationNames.getCXXSpecialName(Name.getNameKind(), + NewCanTy); + DeclarationNameInfo NewNameInfo(NameInfo); + NewNameInfo.setName(NewName); + NewNameInfo.setNamedTypeInfo(NewTInfo); + return NewNameInfo; + } + } + + assert(0 && "Unknown name kind."); + return DeclarationNameInfo(); +} + +template<typename Derived> +TemplateName +TreeTransform<Derived>::TransformTemplateName(CXXScopeSpec &SS, + TemplateName Name, + SourceLocation NameLoc, + QualType ObjectType, + NamedDecl *FirstQualifierInScope) { + if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) { + TemplateDecl *Template = QTN->getTemplateDecl(); + assert(Template && "qualified template name must refer to a template"); + + TemplateDecl *TransTemplate + = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, + Template)); + if (!TransTemplate) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + SS.getScopeRep() == QTN->getQualifier() && + TransTemplate == Template) + return Name; + + return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(), + TransTemplate); + } + + if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) { + if (SS.getScopeRep()) { + // These apply to the scope specifier, not the template. + ObjectType = QualType(); + FirstQualifierInScope = 0; + } + + if (!getDerived().AlwaysRebuild() && + SS.getScopeRep() == DTN->getQualifier() && + ObjectType.isNull()) + return Name; + + if (DTN->isIdentifier()) { + return getDerived().RebuildTemplateName(SS, + *DTN->getIdentifier(), + NameLoc, + ObjectType, + FirstQualifierInScope); + } + + return getDerived().RebuildTemplateName(SS, DTN->getOperator(), NameLoc, + ObjectType); + } + + if (TemplateDecl *Template = Name.getAsTemplateDecl()) { + TemplateDecl *TransTemplate + = cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc, + Template)); + if (!TransTemplate) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + TransTemplate == Template) + return Name; + + return TemplateName(TransTemplate); + } + + if (SubstTemplateTemplateParmPackStorage *SubstPack + = Name.getAsSubstTemplateTemplateParmPack()) { + TemplateTemplateParmDecl *TransParam + = cast_or_null<TemplateTemplateParmDecl>( + getDerived().TransformDecl(NameLoc, SubstPack->getParameterPack())); + if (!TransParam) + return TemplateName(); + + if (!getDerived().AlwaysRebuild() && + TransParam == SubstPack->getParameterPack()) + return Name; + + return getDerived().RebuildTemplateName(TransParam, + SubstPack->getArgumentPack()); + } + + // These should be getting filtered out before they reach the AST. + llvm_unreachable("overloaded function decl survived to here"); + return TemplateName(); +} + +template<typename Derived> +void TreeTransform<Derived>::InventTemplateArgumentLoc( + const TemplateArgument &Arg, + TemplateArgumentLoc &Output) { + SourceLocation Loc = getDerived().getBaseLocation(); + switch (Arg.getKind()) { + case TemplateArgument::Null: + llvm_unreachable("null template argument in TreeTransform"); + break; + + case TemplateArgument::Type: + Output = TemplateArgumentLoc(Arg, + SemaRef.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc)); + + break; + + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { + NestedNameSpecifierLocBuilder Builder; + TemplateName Template = Arg.getAsTemplate(); + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) + Builder.MakeTrivial(SemaRef.Context, DTN->getQualifier(), Loc); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + Builder.MakeTrivial(SemaRef.Context, QTN->getQualifier(), Loc); + + if (Arg.getKind() == TemplateArgument::Template) + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc); + else + Output = TemplateArgumentLoc(Arg, + Builder.getWithLocInContext(SemaRef.Context), + Loc, Loc); + + break; + } + + case TemplateArgument::Expression: + Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); + break; + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + case TemplateArgument::Pack: + Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); + break; + } +} + +template<typename Derived> +bool TreeTransform<Derived>::TransformTemplateArgument( + const TemplateArgumentLoc &Input, + TemplateArgumentLoc &Output) { + const TemplateArgument &Arg = Input.getArgument(); + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Integral: + Output = Input; + return false; + + case TemplateArgument::Type: { + TypeSourceInfo *DI = Input.getTypeSourceInfo(); + if (DI == NULL) + DI = InventTypeSourceInfo(Input.getArgument().getAsType()); + + DI = getDerived().TransformType(DI); + if (!DI) return true; + + Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); + return false; + } + + case TemplateArgument::Declaration: { + // FIXME: we should never have to transform one of these. + DeclarationName Name; + if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) + Name = ND->getDeclName(); + TemporaryBase Rebase(*this, Input.getLocation(), Name); + Decl *D = getDerived().TransformDecl(Input.getLocation(), Arg.getAsDecl()); + if (!D) return true; + + Expr *SourceExpr = Input.getSourceDeclExpression(); + if (SourceExpr) { + EnterExpressionEvaluationContext Unevaluated(getSema(), + Sema::Unevaluated); + ExprResult E = getDerived().TransformExpr(SourceExpr); + SourceExpr = (E.isInvalid() ? 0 : E.take()); + } + + Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr); + return false; + } + + case TemplateArgument::Template: { + NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc(); + if (QualifierLoc) { + QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc); + if (!QualifierLoc) + return true; + } + + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + TemplateName Template + = getDerived().TransformTemplateName(SS, Arg.getAsTemplate(), + Input.getTemplateNameLoc()); + if (Template.isNull()) + return true; + + Output = TemplateArgumentLoc(TemplateArgument(Template), QualifierLoc, + Input.getTemplateNameLoc()); + return false; + } + + case TemplateArgument::TemplateExpansion: + llvm_unreachable("Caller should expand pack expansions"); + + case TemplateArgument::Expression: { + // Template argument expressions are not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(getSema(), + Sema::Unevaluated); + + Expr *InputExpr = Input.getSourceExpression(); + if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); + + ExprResult E = getDerived().TransformExpr(InputExpr); + if (E.isInvalid()) return true; + Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take()); + return false; + } + + case TemplateArgument::Pack: { + llvm::SmallVector<TemplateArgument, 4> TransformedArgs; + TransformedArgs.reserve(Arg.pack_size()); + for (TemplateArgument::pack_iterator A = Arg.pack_begin(), + AEnd = Arg.pack_end(); + A != AEnd; ++A) { + + // FIXME: preserve source information here when we start + // caring about parameter packs. + + TemplateArgumentLoc InputArg; + TemplateArgumentLoc OutputArg; + getDerived().InventTemplateArgumentLoc(*A, InputArg); + if (getDerived().TransformTemplateArgument(InputArg, OutputArg)) + return true; + + TransformedArgs.push_back(OutputArg.getArgument()); + } + + TemplateArgument *TransformedArgsPtr + = new (getSema().Context) TemplateArgument[TransformedArgs.size()]; + std::copy(TransformedArgs.begin(), TransformedArgs.end(), + TransformedArgsPtr); + Output = TemplateArgumentLoc(TemplateArgument(TransformedArgsPtr, + TransformedArgs.size()), + Input.getLocInfo()); + return false; + } + } + + // Work around bogus GCC warning + return true; +} + +/// \brief Iterator adaptor that invents template argument location information +/// for each of the template arguments in its underlying iterator. +template<typename Derived, typename InputIterator> +class TemplateArgumentLocInventIterator { + TreeTransform<Derived> &Self; + InputIterator Iter; + +public: + typedef TemplateArgumentLoc value_type; + typedef TemplateArgumentLoc reference; + typedef typename std::iterator_traits<InputIterator>::difference_type + difference_type; + typedef std::input_iterator_tag iterator_category; + + class pointer { + TemplateArgumentLoc Arg; + + public: + explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { } + + const TemplateArgumentLoc *operator->() const { return &Arg; } + }; + + TemplateArgumentLocInventIterator() { } + + explicit TemplateArgumentLocInventIterator(TreeTransform<Derived> &Self, + InputIterator Iter) + : Self(Self), Iter(Iter) { } + + TemplateArgumentLocInventIterator &operator++() { + ++Iter; + return *this; + } + + TemplateArgumentLocInventIterator operator++(int) { + TemplateArgumentLocInventIterator Old(*this); + ++(*this); + return Old; + } + + reference operator*() const { + TemplateArgumentLoc Result; + Self.InventTemplateArgumentLoc(*Iter, Result); + return Result; + } + + pointer operator->() const { return pointer(**this); } + + friend bool operator==(const TemplateArgumentLocInventIterator &X, + const TemplateArgumentLocInventIterator &Y) { + return X.Iter == Y.Iter; + } + + friend bool operator!=(const TemplateArgumentLocInventIterator &X, + const TemplateArgumentLocInventIterator &Y) { + return X.Iter != Y.Iter; + } +}; + +template<typename Derived> +template<typename InputIterator> +bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, + InputIterator Last, + TemplateArgumentListInfo &Outputs) { + for (; First != Last; ++First) { + TemplateArgumentLoc Out; + TemplateArgumentLoc In = *First; + + if (In.getArgument().getKind() == TemplateArgument::Pack) { + // Unpack argument packs, which we translate them into separate + // arguments. + // FIXME: We could do much better if we could guarantee that the + // TemplateArgumentLocInfo for the pack expansion would be usable for + // all of the template arguments in the argument pack. + typedef TemplateArgumentLocInventIterator<Derived, + TemplateArgument::pack_iterator> + PackLocIterator; + if (TransformTemplateArguments(PackLocIterator(*this, + In.getArgument().pack_begin()), + PackLocIterator(*this, + In.getArgument().pack_end()), + Outputs)) + return true; + + continue; + } + + if (In.getArgument().isPackExpansion()) { + // We have a pack expansion, for which we will be substituting into + // the pattern. + SourceLocation Ellipsis; + llvm::Optional<unsigned> OrigNumExpansions; + TemplateArgumentLoc Pattern + = In.getPackExpansionPattern(Ellipsis, OrigNumExpansions, + getSema().Context); + + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + if (getDerived().TryExpandParameterPacks(Ellipsis, + Pattern.getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + Expand, + RetainExpansion, + NumExpansions)) + return true; + + if (!Expand) { + // The transform has determined that we should perform a simple + // transformation on the pack expansion, producing another pack + // expansion. + TemplateArgumentLoc OutPattern; + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + if (getDerived().TransformTemplateArgument(Pattern, OutPattern)) + return true; + + Out = getDerived().RebuildPackExpansion(OutPattern, Ellipsis, + NumExpansions); + if (Out.getArgument().isNull()) + return true; + + Outputs.addArgument(Out); + continue; + } + + // The transform has determined that we should perform an elementwise + // expansion of the pattern. Do so. + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + + if (getDerived().TransformTemplateArgument(Pattern, Out)) + return true; + + if (Out.getArgument().containsUnexpandedParameterPack()) { + Out = getDerived().RebuildPackExpansion(Out, Ellipsis, + OrigNumExpansions); + if (Out.getArgument().isNull()) + return true; + } + + Outputs.addArgument(Out); + } + + // If we're supposed to retain a pack expansion, do so by temporarily + // forgetting the partially-substituted parameter pack. + if (RetainExpansion) { + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + + if (getDerived().TransformTemplateArgument(Pattern, Out)) + return true; + + Out = getDerived().RebuildPackExpansion(Out, Ellipsis, + OrigNumExpansions); + if (Out.getArgument().isNull()) + return true; + + Outputs.addArgument(Out); + } + + continue; + } + + // The simple case: + if (getDerived().TransformTemplateArgument(In, Out)) + return true; + + Outputs.addArgument(Out); + } + + return false; + +} + +//===----------------------------------------------------------------------===// +// Type transformation +//===----------------------------------------------------------------------===// + +template<typename Derived> +QualType TreeTransform<Derived>::TransformType(QualType T) { + if (getDerived().AlreadyTransformed(T)) + return T; + + // Temporary workaround. All of these transformations should + // eventually turn into transformations on TypeLocs. + TypeSourceInfo *DI = getSema().Context.getTrivialTypeSourceInfo(T, + getDerived().getBaseLocation()); + + TypeSourceInfo *NewDI = getDerived().TransformType(DI); + + if (!NewDI) + return QualType(); + + return NewDI->getType(); +} + +template<typename Derived> +TypeSourceInfo *TreeTransform<Derived>::TransformType(TypeSourceInfo *DI) { + if (getDerived().AlreadyTransformed(DI->getType())) + return DI; + + TypeLocBuilder TLB; + + TypeLoc TL = DI->getTypeLoc(); + TLB.reserve(TL.getFullDataSize()); + + QualType Result = getDerived().TransformType(TLB, TL); + if (Result.isNull()) + return 0; + + return TLB.getTypeSourceInfo(SemaRef.Context, Result); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) { + switch (T.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: \ + return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T)); +#include "clang/AST/TypeLocNodes.def" + } + + llvm_unreachable("unhandled type loc!"); + return QualType(); +} + +/// FIXME: By default, this routine adds type qualifiers only to types +/// that can have qualifiers, and silently suppresses those qualifiers +/// that are not permitted (e.g., qualifiers on reference or function +/// types). This is the right thing for template instantiation, but +/// probably not for other clients. +template<typename Derived> +QualType +TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, + QualifiedTypeLoc T) { + Qualifiers Quals = T.getType().getLocalQualifiers(); + + QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc()); + if (Result.isNull()) + return QualType(); + + // Silently suppress qualifiers if the result type can't be qualified. + // FIXME: this is the right thing for template instantiation, but + // probably not for other clients. + if (Result->isFunctionType() || Result->isReferenceType()) + return Result; + + if (!Quals.empty()) { + Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals); + TLB.push<QualifiedTypeLoc>(Result); + // No location information to preserve. + } + + return Result; +} + +template<typename Derived> +TypeLoc +TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, + QualType ObjectType, + NamedDecl *UnqualLookup, + CXXScopeSpec &SS) { + QualType T = TL.getType(); + if (getDerived().AlreadyTransformed(T)) + return TL; + + TypeLocBuilder TLB; + QualType Result; + + if (isa<TemplateSpecializationType>(T)) { + TemplateSpecializationTypeLoc SpecTL + = cast<TemplateSpecializationTypeLoc>(TL); + + TemplateName Template = + getDerived().TransformTemplateName(SS, + SpecTL.getTypePtr()->getTemplateName(), + SpecTL.getTemplateNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return TypeLoc(); + + Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, + Template); + } else if (isa<DependentTemplateSpecializationType>(T)) { + DependentTemplateSpecializationTypeLoc SpecTL + = cast<DependentTemplateSpecializationTypeLoc>(TL); + + TemplateName Template + = getDerived().RebuildTemplateName(SS, + *SpecTL.getTypePtr()->getIdentifier(), + SpecTL.getNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return TypeLoc(); + + Result = getDerived().TransformDependentTemplateSpecializationType(TLB, + SpecTL, + Template, + SS); + } else { + // Nothing special needs to be done for these. + Result = getDerived().TransformType(TLB, TL); + } + + if (Result.isNull()) + return TypeLoc(); + + return TLB.getTypeSourceInfo(SemaRef.Context, Result)->getTypeLoc(); +} + +template<typename Derived> +TypeSourceInfo * +TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo, + QualType ObjectType, + NamedDecl *UnqualLookup, + CXXScopeSpec &SS) { + // FIXME: Painfully copy-paste from the above! + + QualType T = TSInfo->getType(); + if (getDerived().AlreadyTransformed(T)) + return TSInfo; + + TypeLocBuilder TLB; + QualType Result; + + TypeLoc TL = TSInfo->getTypeLoc(); + if (isa<TemplateSpecializationType>(T)) { + TemplateSpecializationTypeLoc SpecTL + = cast<TemplateSpecializationTypeLoc>(TL); + + TemplateName Template + = getDerived().TransformTemplateName(SS, + SpecTL.getTypePtr()->getTemplateName(), + SpecTL.getTemplateNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return 0; + + Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, + Template); + } else if (isa<DependentTemplateSpecializationType>(T)) { + DependentTemplateSpecializationTypeLoc SpecTL + = cast<DependentTemplateSpecializationTypeLoc>(TL); + + TemplateName Template + = getDerived().RebuildTemplateName(SS, + *SpecTL.getTypePtr()->getIdentifier(), + SpecTL.getNameLoc(), + ObjectType, UnqualLookup); + if (Template.isNull()) + return 0; + + Result = getDerived().TransformDependentTemplateSpecializationType(TLB, + SpecTL, + Template, + SS); + } else { + // Nothing special needs to be done for these. + Result = getDerived().TransformType(TLB, TL); + } + + if (Result.isNull()) + return 0; + + return TLB.getTypeSourceInfo(SemaRef.Context, Result); +} + +template <class TyLoc> static inline +QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { + TyLoc NewT = TLB.push<TyLoc>(T.getType()); + NewT.setNameLoc(T.getNameLoc()); + return T.getType(); +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB, + BuiltinTypeLoc T) { + BuiltinTypeLoc NewT = TLB.push<BuiltinTypeLoc>(T.getType()); + NewT.setBuiltinLoc(T.getBuiltinLoc()); + if (T.needsExtraLocalData()) + NewT.getWrittenBuiltinSpecs() = T.getWrittenBuiltinSpecs(); + return T.getType(); +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB, + ComplexTypeLoc T) { + // FIXME: recurse? + return TransformTypeSpecType(TLB, T); +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB, + PointerTypeLoc TL) { + QualType PointeeType + = getDerived().TransformType(TLB, TL.getPointeeLoc()); + if (PointeeType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (PointeeType->getAs<ObjCObjectType>()) { + // A dependent pointer type 'T *' has is being transformed such + // that an Objective-C class type is being replaced for 'T'. The + // resulting pointer type is an ObjCObjectPointerType, not a + // PointerType. + Result = SemaRef.Context.getObjCObjectPointerType(PointeeType); + + ObjCObjectPointerTypeLoc NewT = TLB.push<ObjCObjectPointerTypeLoc>(Result); + NewT.setStarLoc(TL.getStarLoc()); + return Result; + } + + if (getDerived().AlwaysRebuild() || + PointeeType != TL.getPointeeLoc().getType()) { + Result = getDerived().RebuildPointerType(PointeeType, TL.getSigilLoc()); + if (Result.isNull()) + return QualType(); + } + + PointerTypeLoc NewT = TLB.push<PointerTypeLoc>(Result); + NewT.setSigilLoc(TL.getSigilLoc()); + return Result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB, + BlockPointerTypeLoc TL) { + QualType PointeeType + = getDerived().TransformType(TLB, TL.getPointeeLoc()); + if (PointeeType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + PointeeType != TL.getPointeeLoc().getType()) { + Result = getDerived().RebuildBlockPointerType(PointeeType, + TL.getSigilLoc()); + if (Result.isNull()) + return QualType(); + } + + BlockPointerTypeLoc NewT = TLB.push<BlockPointerTypeLoc>(Result); + NewT.setSigilLoc(TL.getSigilLoc()); + return Result; +} + +/// Transforms a reference type. Note that somewhat paradoxically we +/// don't care whether the type itself is an l-value type or an r-value +/// type; we only care if the type was *written* as an l-value type +/// or an r-value type. +template<typename Derived> +QualType +TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB, + ReferenceTypeLoc TL) { + const ReferenceType *T = TL.getTypePtr(); + + // Note that this works with the pointee-as-written. + QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); + if (PointeeType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + PointeeType != T->getPointeeTypeAsWritten()) { + Result = getDerived().RebuildReferenceType(PointeeType, + T->isSpelledAsLValue(), + TL.getSigilLoc()); + if (Result.isNull()) + return QualType(); + } + + // r-value references can be rebuilt as l-value references. + ReferenceTypeLoc NewTL; + if (isa<LValueReferenceType>(Result)) + NewTL = TLB.push<LValueReferenceTypeLoc>(Result); + else + NewTL = TLB.push<RValueReferenceTypeLoc>(Result); + NewTL.setSigilLoc(TL.getSigilLoc()); + + return Result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB, + LValueReferenceTypeLoc TL) { + return TransformReferenceType(TLB, TL); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB, + RValueReferenceTypeLoc TL) { + return TransformReferenceType(TLB, TL); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, + MemberPointerTypeLoc TL) { + QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); + if (PointeeType.isNull()) + return QualType(); + + TypeSourceInfo* OldClsTInfo = TL.getClassTInfo(); + TypeSourceInfo* NewClsTInfo = 0; + if (OldClsTInfo) { + NewClsTInfo = getDerived().TransformType(OldClsTInfo); + if (!NewClsTInfo) + return QualType(); + } + + const MemberPointerType *T = TL.getTypePtr(); + QualType OldClsType = QualType(T->getClass(), 0); + QualType NewClsType; + if (NewClsTInfo) + NewClsType = NewClsTInfo->getType(); + else { + NewClsType = getDerived().TransformType(OldClsType); + if (NewClsType.isNull()) + return QualType(); + } + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + PointeeType != T->getPointeeType() || + NewClsType != OldClsType) { + Result = getDerived().RebuildMemberPointerType(PointeeType, NewClsType, + TL.getStarLoc()); + if (Result.isNull()) + return QualType(); + } + + MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result); + NewTL.setSigilLoc(TL.getSigilLoc()); + NewTL.setClassTInfo(NewClsTInfo); + + return Result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB, + ConstantArrayTypeLoc TL) { + const ConstantArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); + if (ElementType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildConstantArrayType(ElementType, + T->getSizeModifier(), + T->getSize(), + T->getIndexTypeCVRQualifiers(), + TL.getBracketsRange()); + if (Result.isNull()) + return QualType(); + } + + ConstantArrayTypeLoc NewTL = TLB.push<ConstantArrayTypeLoc>(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + + Expr *Size = TL.getSizeExpr(); + if (Size) { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + Size = getDerived().TransformExpr(Size).template takeAs<Expr>(); + } + NewTL.setSizeExpr(Size); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformIncompleteArrayType( + TypeLocBuilder &TLB, + IncompleteArrayTypeLoc TL) { + const IncompleteArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); + if (ElementType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildIncompleteArrayType(ElementType, + T->getSizeModifier(), + T->getIndexTypeCVRQualifiers(), + TL.getBracketsRange()); + if (Result.isNull()) + return QualType(); + } + + IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + NewTL.setSizeExpr(0); + + return Result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB, + VariableArrayTypeLoc TL) { + const VariableArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); + if (ElementType.isNull()) + return QualType(); + + // Array bounds are not potentially evaluated contexts + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult SizeResult + = getDerived().TransformExpr(T->getSizeExpr()); + if (SizeResult.isInvalid()) + return QualType(); + + Expr *Size = SizeResult.take(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType() || + Size != T->getSizeExpr()) { + Result = getDerived().RebuildVariableArrayType(ElementType, + T->getSizeModifier(), + Size, + T->getIndexTypeCVRQualifiers(), + TL.getBracketsRange()); + if (Result.isNull()) + return QualType(); + } + + VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + NewTL.setSizeExpr(Size); + + return Result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB, + DependentSizedArrayTypeLoc TL) { + const DependentSizedArrayType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc()); + if (ElementType.isNull()) + return QualType(); + + // Array bounds are not potentially evaluated contexts + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + // Prefer the expression from the TypeLoc; the other may have been uniqued. + Expr *origSize = TL.getSizeExpr(); + if (!origSize) origSize = T->getSizeExpr(); + + ExprResult sizeResult + = getDerived().TransformExpr(origSize); + if (sizeResult.isInvalid()) + return QualType(); + + Expr *size = sizeResult.get(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType() || + size != origSize) { + Result = getDerived().RebuildDependentSizedArrayType(ElementType, + T->getSizeModifier(), + size, + T->getIndexTypeCVRQualifiers(), + TL.getBracketsRange()); + if (Result.isNull()) + return QualType(); + } + + // We might have any sort of array type now, but fortunately they + // all have the same location layout. + ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result); + NewTL.setLBracketLoc(TL.getLBracketLoc()); + NewTL.setRBracketLoc(TL.getRBracketLoc()); + NewTL.setSizeExpr(size); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType( + TypeLocBuilder &TLB, + DependentSizedExtVectorTypeLoc TL) { + const DependentSizedExtVectorType *T = TL.getTypePtr(); + + // FIXME: ext vector locs should be nested + QualType ElementType = getDerived().TransformType(T->getElementType()); + if (ElementType.isNull()) + return QualType(); + + // Vector sizes are not potentially evaluated contexts + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); + if (Size.isInvalid()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType() || + Size.get() != T->getSizeExpr()) { + Result = getDerived().RebuildDependentSizedExtVectorType(ElementType, + Size.take(), + T->getAttributeLoc()); + if (Result.isNull()) + return QualType(); + } + + // Result might be dependent or not. + if (isa<DependentSizedExtVectorType>(Result)) { + DependentSizedExtVectorTypeLoc NewTL + = TLB.push<DependentSizedExtVectorTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } else { + ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + } + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB, + VectorTypeLoc TL) { + const VectorType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(T->getElementType()); + if (ElementType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(), + T->getVectorKind()); + if (Result.isNull()) + return QualType(); + } + + VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB, + ExtVectorTypeLoc TL) { + const VectorType *T = TL.getTypePtr(); + QualType ElementType = getDerived().TransformType(T->getElementType()); + if (ElementType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ElementType != T->getElementType()) { + Result = getDerived().RebuildExtVectorType(ElementType, + T->getNumElements(), + /*FIXME*/ SourceLocation()); + if (Result.isNull()) + return QualType(); + } + + ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +ParmVarDecl * +TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, + int indexAdjustment, + llvm::Optional<unsigned> NumExpansions) { + TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); + TypeSourceInfo *NewDI = 0; + + if (NumExpansions && isa<PackExpansionType>(OldDI->getType())) { + // If we're substituting into a pack expansion type and we know the + TypeLoc OldTL = OldDI->getTypeLoc(); + PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL); + + TypeLocBuilder TLB; + TypeLoc NewTL = OldDI->getTypeLoc(); + TLB.reserve(NewTL.getFullDataSize()); + + QualType Result = getDerived().TransformType(TLB, + OldExpansionTL.getPatternLoc()); + if (Result.isNull()) + return 0; + + Result = RebuildPackExpansionType(Result, + OldExpansionTL.getPatternLoc().getSourceRange(), + OldExpansionTL.getEllipsisLoc(), + NumExpansions); + if (Result.isNull()) + return 0; + + PackExpansionTypeLoc NewExpansionTL + = TLB.push<PackExpansionTypeLoc>(Result); + NewExpansionTL.setEllipsisLoc(OldExpansionTL.getEllipsisLoc()); + NewDI = TLB.getTypeSourceInfo(SemaRef.Context, Result); + } else + NewDI = getDerived().TransformType(OldDI); + if (!NewDI) + return 0; + + if (NewDI == OldDI && indexAdjustment == 0) + return OldParm; + + ParmVarDecl *newParm = ParmVarDecl::Create(SemaRef.Context, + OldParm->getDeclContext(), + OldParm->getInnerLocStart(), + OldParm->getLocation(), + OldParm->getIdentifier(), + NewDI->getType(), + NewDI, + OldParm->getStorageClass(), + OldParm->getStorageClassAsWritten(), + /* DefArg */ NULL); + newParm->setScopeInfo(OldParm->getFunctionScopeDepth(), + OldParm->getFunctionScopeIndex() + indexAdjustment); + return newParm; +} + +template<typename Derived> +bool TreeTransform<Derived>:: + TransformFunctionTypeParams(SourceLocation Loc, + ParmVarDecl **Params, unsigned NumParams, + const QualType *ParamTypes, + llvm::SmallVectorImpl<QualType> &OutParamTypes, + llvm::SmallVectorImpl<ParmVarDecl*> *PVars) { + int indexAdjustment = 0; + + for (unsigned i = 0; i != NumParams; ++i) { + if (ParmVarDecl *OldParm = Params[i]) { + assert(OldParm->getFunctionScopeIndex() == i); + + llvm::Optional<unsigned> NumExpansions; + ParmVarDecl *NewParm = 0; + if (OldParm->isParameterPack()) { + // We have a function parameter pack that may need to be expanded. + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + + // Find the parameter packs that could be expanded. + TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc(); + PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(TL); + TypeLoc Pattern = ExpansionTL.getPatternLoc(); + SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); + assert(Unexpanded.size() > 0 && "Could not find parameter packs!"); + + // Determine whether we should expand the parameter packs. + bool ShouldExpand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> OrigNumExpansions + = ExpansionTL.getTypePtr()->getNumExpansions(); + NumExpansions = OrigNumExpansions; + if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), + Pattern.getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + ShouldExpand, + RetainExpansion, + NumExpansions)) { + return true; + } + + if (ShouldExpand) { + // Expand the function parameter pack into multiple, separate + // parameters. + getDerived().ExpandingFunctionParameterPack(OldParm); + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + ParmVarDecl *NewParm + = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment++, + OrigNumExpansions); + if (!NewParm) + return true; + + OutParamTypes.push_back(NewParm->getType()); + if (PVars) + PVars->push_back(NewParm); + } + + // If we're supposed to retain a pack expansion, do so by temporarily + // forgetting the partially-substituted parameter pack. + if (RetainExpansion) { + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + ParmVarDecl *NewParm + = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment++, + OrigNumExpansions); + if (!NewParm) + return true; + + OutParamTypes.push_back(NewParm->getType()); + if (PVars) + PVars->push_back(NewParm); + } + + // The next parameter should have the same adjustment as the + // last thing we pushed, but we post-incremented indexAdjustment + // on every push. Also, if we push nothing, the adjustment should + // go down by one. + indexAdjustment--; + + // We're done with the pack expansion. + continue; + } + + // We'll substitute the parameter now without expanding the pack + // expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment, + NumExpansions); + } else { + NewParm = getDerived().TransformFunctionTypeParam(OldParm, + indexAdjustment, + llvm::Optional<unsigned>()); + } + + if (!NewParm) + return true; + + OutParamTypes.push_back(NewParm->getType()); + if (PVars) + PVars->push_back(NewParm); + continue; + } + + // Deal with the possibility that we don't have a parameter + // declaration for this parameter. + QualType OldType = ParamTypes[i]; + bool IsPackExpansion = false; + llvm::Optional<unsigned> NumExpansions; + QualType NewType; + if (const PackExpansionType *Expansion + = dyn_cast<PackExpansionType>(OldType)) { + // We have a function parameter pack that may need to be expanded. + QualType Pattern = Expansion->getPattern(); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + getSema().collectUnexpandedParameterPacks(Pattern, Unexpanded); + + // Determine whether we should expand the parameter packs. + bool ShouldExpand = false; + bool RetainExpansion = false; + if (getDerived().TryExpandParameterPacks(Loc, SourceRange(), + Unexpanded.data(), + Unexpanded.size(), + ShouldExpand, + RetainExpansion, + NumExpansions)) { + return true; + } + + if (ShouldExpand) { + // Expand the function parameter pack into multiple, separate + // parameters. + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); + QualType NewType = getDerived().TransformType(Pattern); + if (NewType.isNull()) + return true; + + OutParamTypes.push_back(NewType); + if (PVars) + PVars->push_back(0); + } + + // We're done with the pack expansion. + continue; + } + + // If we're supposed to retain a pack expansion, do so by temporarily + // forgetting the partially-substituted parameter pack. + if (RetainExpansion) { + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + QualType NewType = getDerived().TransformType(Pattern); + if (NewType.isNull()) + return true; + + OutParamTypes.push_back(NewType); + if (PVars) + PVars->push_back(0); + } + + // We'll substitute the parameter now without expanding the pack + // expansion. + OldType = Expansion->getPattern(); + IsPackExpansion = true; + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1); + NewType = getDerived().TransformType(OldType); + } else { + NewType = getDerived().TransformType(OldType); + } + + if (NewType.isNull()) + return true; + + if (IsPackExpansion) + NewType = getSema().Context.getPackExpansionType(NewType, + NumExpansions); + + OutParamTypes.push_back(NewType); + if (PVars) + PVars->push_back(0); + } + +#ifndef NDEBUG + if (PVars) { + for (unsigned i = 0, e = PVars->size(); i != e; ++i) + if (ParmVarDecl *parm = (*PVars)[i]) + assert(parm->getFunctionScopeIndex() == i); + } +#endif + + return false; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, + FunctionProtoTypeLoc TL) { + // Transform the parameters and return type. + // + // We instantiate in source order, with the return type first followed by + // the parameters, because users tend to expect this (even if they shouldn't + // rely on it!). + // + // When the function has a trailing return type, we instantiate the + // parameters before the return type, since the return type can then refer + // to the parameters themselves (via decltype, sizeof, etc.). + // + llvm::SmallVector<QualType, 4> ParamTypes; + llvm::SmallVector<ParmVarDecl*, 4> ParamDecls; + const FunctionProtoType *T = TL.getTypePtr(); + + QualType ResultType; + + if (TL.getTrailingReturn()) { + if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), + TL.getParmArray(), + TL.getNumArgs(), + TL.getTypePtr()->arg_type_begin(), + ParamTypes, &ParamDecls)) + return QualType(); + + ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); + if (ResultType.isNull()) + return QualType(); + } + else { + ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); + if (ResultType.isNull()) + return QualType(); + + if (getDerived().TransformFunctionTypeParams(TL.getBeginLoc(), + TL.getParmArray(), + TL.getNumArgs(), + TL.getTypePtr()->arg_type_begin(), + ParamTypes, &ParamDecls)) + return QualType(); + } + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ResultType != T->getResultType() || + T->getNumArgs() != ParamTypes.size() || + !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) { + Result = getDerived().RebuildFunctionProtoType(ResultType, + ParamTypes.data(), + ParamTypes.size(), + T->isVariadic(), + T->getTypeQuals(), + T->getRefQualifier(), + T->getExtInfo()); + if (Result.isNull()) + return QualType(); + } + + FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result); + NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); + NewTL.setTrailingReturn(TL.getTrailingReturn()); + for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i) + NewTL.setArg(i, ParamDecls[i]); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformFunctionNoProtoType( + TypeLocBuilder &TLB, + FunctionNoProtoTypeLoc TL) { + const FunctionNoProtoType *T = TL.getTypePtr(); + QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); + if (ResultType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + ResultType != T->getResultType()) + Result = getDerived().RebuildFunctionNoProtoType(ResultType); + + FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result); + NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); + NewTL.setTrailingReturn(false); + + return Result; +} + +template<typename Derived> QualType +TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB, + UnresolvedUsingTypeLoc TL) { + const UnresolvedUsingType *T = TL.getTypePtr(); + Decl *D = getDerived().TransformDecl(TL.getNameLoc(), T->getDecl()); + if (!D) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || D != T->getDecl()) { + Result = getDerived().RebuildUnresolvedUsingType(D); + if (Result.isNull()) + return QualType(); + } + + // We might get an arbitrary type spec type back. We should at + // least always get a type spec type, though. + TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB, + TypedefTypeLoc TL) { + const TypedefType *T = TL.getTypePtr(); + TypedefNameDecl *Typedef + = cast_or_null<TypedefNameDecl>(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); + if (!Typedef) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Typedef != T->getDecl()) { + Result = getDerived().RebuildTypedefType(Typedef); + if (Result.isNull()) + return QualType(); + } + + TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB, + TypeOfExprTypeLoc TL) { + // typeof expressions are not potentially evaluated contexts + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr()); + if (E.isInvalid()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + E.get() != TL.getUnderlyingExpr()) { + Result = getDerived().RebuildTypeOfExprType(E.get(), TL.getTypeofLoc()); + if (Result.isNull()) + return QualType(); + } + else E.take(); + + TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result); + NewTL.setTypeofLoc(TL.getTypeofLoc()); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB, + TypeOfTypeLoc TL) { + TypeSourceInfo* Old_Under_TI = TL.getUnderlyingTInfo(); + TypeSourceInfo* New_Under_TI = getDerived().TransformType(Old_Under_TI); + if (!New_Under_TI) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || New_Under_TI != Old_Under_TI) { + Result = getDerived().RebuildTypeOfType(New_Under_TI->getType()); + if (Result.isNull()) + return QualType(); + } + + TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result); + NewTL.setTypeofLoc(TL.getTypeofLoc()); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + NewTL.setUnderlyingTInfo(New_Under_TI); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB, + DecltypeTypeLoc TL) { + const DecltypeType *T = TL.getTypePtr(); + + // decltype expressions are not potentially evaluated contexts + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr()); + if (E.isInvalid()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + E.get() != T->getUnderlyingExpr()) { + Result = getDerived().RebuildDecltypeType(E.get(), TL.getNameLoc()); + if (Result.isNull()) + return QualType(); + } + else E.take(); + + DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformUnaryTransformType( + TypeLocBuilder &TLB, + UnaryTransformTypeLoc TL) { + QualType Result = TL.getType(); + if (Result->isDependentType()) { + const UnaryTransformType *T = TL.getTypePtr(); + QualType NewBase = + getDerived().TransformType(TL.getUnderlyingTInfo())->getType(); + Result = getDerived().RebuildUnaryTransformType(NewBase, + T->getUTTKind(), + TL.getKWLoc()); + if (Result.isNull()) + return QualType(); + } + + UnaryTransformTypeLoc NewTL = TLB.push<UnaryTransformTypeLoc>(Result); + NewTL.setKWLoc(TL.getKWLoc()); + NewTL.setParensRange(TL.getParensRange()); + NewTL.setUnderlyingTInfo(TL.getUnderlyingTInfo()); + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB, + AutoTypeLoc TL) { + const AutoType *T = TL.getTypePtr(); + QualType OldDeduced = T->getDeducedType(); + QualType NewDeduced; + if (!OldDeduced.isNull()) { + NewDeduced = getDerived().TransformType(OldDeduced); + if (NewDeduced.isNull()) + return QualType(); + } + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || NewDeduced != OldDeduced) { + Result = getDerived().RebuildAutoType(NewDeduced); + if (Result.isNull()) + return QualType(); + } + + AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB, + RecordTypeLoc TL) { + const RecordType *T = TL.getTypePtr(); + RecordDecl *Record + = cast_or_null<RecordDecl>(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); + if (!Record) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Record != T->getDecl()) { + Result = getDerived().RebuildRecordType(Record); + if (Result.isNull()) + return QualType(); + } + + RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB, + EnumTypeLoc TL) { + const EnumType *T = TL.getTypePtr(); + EnumDecl *Enum + = cast_or_null<EnumDecl>(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); + if (!Enum) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Enum != T->getDecl()) { + Result = getDerived().RebuildEnumType(Enum); + if (Result.isNull()) + return QualType(); + } + + EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformInjectedClassNameType( + TypeLocBuilder &TLB, + InjectedClassNameTypeLoc TL) { + Decl *D = getDerived().TransformDecl(TL.getNameLoc(), + TL.getTypePtr()->getDecl()); + if (!D) return QualType(); + + QualType T = SemaRef.Context.getTypeDeclType(cast<TypeDecl>(D)); + TLB.pushTypeSpec(T).setNameLoc(TL.getNameLoc()); + return T; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformTemplateTypeParmType( + TypeLocBuilder &TLB, + TemplateTypeParmTypeLoc TL) { + return TransformTypeSpecType(TLB, TL); +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType( + TypeLocBuilder &TLB, + SubstTemplateTypeParmTypeLoc TL) { + const SubstTemplateTypeParmType *T = TL.getTypePtr(); + + // Substitute into the replacement type, which itself might involve something + // that needs to be transformed. This only tends to occur with default + // template arguments of template template parameters. + TemporaryBase Rebase(*this, TL.getNameLoc(), DeclarationName()); + QualType Replacement = getDerived().TransformType(T->getReplacementType()); + if (Replacement.isNull()) + return QualType(); + + // Always canonicalize the replacement type. + Replacement = SemaRef.Context.getCanonicalType(Replacement); + QualType Result + = SemaRef.Context.getSubstTemplateTypeParmType(T->getReplacedParameter(), + Replacement); + + // Propagate type-source information. + SubstTemplateTypeParmTypeLoc NewTL + = TLB.push<SubstTemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType( + TypeLocBuilder &TLB, + SubstTemplateTypeParmPackTypeLoc TL) { + return TransformTypeSpecType(TLB, TL); +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformTemplateSpecializationType( + TypeLocBuilder &TLB, + TemplateSpecializationTypeLoc TL) { + const TemplateSpecializationType *T = TL.getTypePtr(); + + // The nested-name-specifier never matters in a TemplateSpecializationType, + // because we can't have a dependent nested-name-specifier anyway. + CXXScopeSpec SS; + TemplateName Template + = getDerived().TransformTemplateName(SS, T->getTemplateName(), + TL.getTemplateNameLoc()); + if (Template.isNull()) + return QualType(); + + return getDerived().TransformTemplateSpecializationType(TLB, TL, Template); +} + +namespace { + /// \brief Simple iterator that traverses the template arguments in a + /// container that provides a \c getArgLoc() member function. + /// + /// This iterator is intended to be used with the iterator form of + /// \c TreeTransform<Derived>::TransformTemplateArguments(). + template<typename ArgLocContainer> + class TemplateArgumentLocContainerIterator { + ArgLocContainer *Container; + unsigned Index; + + public: + typedef TemplateArgumentLoc value_type; + typedef TemplateArgumentLoc reference; + typedef int difference_type; + typedef std::input_iterator_tag iterator_category; + + class pointer { + TemplateArgumentLoc Arg; + + public: + explicit pointer(TemplateArgumentLoc Arg) : Arg(Arg) { } + + const TemplateArgumentLoc *operator->() const { + return &Arg; + } + }; + + + TemplateArgumentLocContainerIterator() {} + + TemplateArgumentLocContainerIterator(ArgLocContainer &Container, + unsigned Index) + : Container(&Container), Index(Index) { } + + TemplateArgumentLocContainerIterator &operator++() { + ++Index; + return *this; + } + + TemplateArgumentLocContainerIterator operator++(int) { + TemplateArgumentLocContainerIterator Old(*this); + ++(*this); + return Old; + } + + TemplateArgumentLoc operator*() const { + return Container->getArgLoc(Index); + } + + pointer operator->() const { + return pointer(Container->getArgLoc(Index)); + } + + friend bool operator==(const TemplateArgumentLocContainerIterator &X, + const TemplateArgumentLocContainerIterator &Y) { + return X.Container == Y.Container && X.Index == Y.Index; + } + + friend bool operator!=(const TemplateArgumentLocContainerIterator &X, + const TemplateArgumentLocContainerIterator &Y) { + return !(X == Y); + } + }; +} + + +template <typename Derived> +QualType TreeTransform<Derived>::TransformTemplateSpecializationType( + TypeLocBuilder &TLB, + TemplateSpecializationTypeLoc TL, + TemplateName Template) { + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + typedef TemplateArgumentLocContainerIterator<TemplateSpecializationTypeLoc> + ArgIterator; + if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), + ArgIterator(TL, TL.getNumArgs()), + NewTemplateArgs)) + return QualType(); + + // FIXME: maybe don't rebuild if all the template arguments are the same. + + QualType Result = + getDerived().RebuildTemplateSpecializationType(Template, + TL.getTemplateNameLoc(), + NewTemplateArgs); + + if (!Result.isNull()) { + // Specializations of template template parameters are represented as + // TemplateSpecializationTypes, and substitution of type alias templates + // within a dependent context can transform them into + // DependentTemplateSpecializationTypes. + if (isa<DependentTemplateSpecializationType>(Result)) { + DependentTemplateSpecializationTypeLoc NewTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getTemplateNameLoc()); + NewTL.setQualifierLoc(NestedNameSpecifierLoc()); + NewTL.setNameLoc(TL.getTemplateNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + return Result; + } + + TemplateSpecializationTypeLoc NewTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + } + + return Result; +} + +template <typename Derived> +QualType TreeTransform<Derived>::TransformDependentTemplateSpecializationType( + TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + TemplateName Template, + CXXScopeSpec &SS) { + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + typedef TemplateArgumentLocContainerIterator< + DependentTemplateSpecializationTypeLoc> ArgIterator; + if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), + ArgIterator(TL, TL.getNumArgs()), + NewTemplateArgs)) + return QualType(); + + // FIXME: maybe don't rebuild if all the template arguments are the same. + + if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) { + QualType Result + = getSema().Context.getDependentTemplateSpecializationType( + TL.getTypePtr()->getKeyword(), + DTN->getQualifier(), + DTN->getIdentifier(), + NewTemplateArgs); + + DependentTemplateSpecializationTypeLoc NewTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + + NewTL.setQualifierLoc(SS.getWithLocInContext(SemaRef.Context)); + NewTL.setNameLoc(TL.getNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + return Result; + } + + QualType Result + = getDerived().RebuildTemplateSpecializationType(Template, + TL.getNameLoc(), + NewTemplateArgs); + + if (!Result.isNull()) { + /// FIXME: Wrap this in an elaborated-type-specifier? + TemplateSpecializationTypeLoc NewTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + NewTL.setTemplateNameLoc(TL.getNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + } + + return Result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, + ElaboratedTypeLoc TL) { + const ElaboratedType *T = TL.getTypePtr(); + + NestedNameSpecifierLoc QualifierLoc; + // NOTE: the qualifier in an ElaboratedType is optional. + if (TL.getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) + return QualType(); + } + + QualType NamedT = getDerived().TransformType(TLB, TL.getNamedTypeLoc()); + if (NamedT.isNull()) + return QualType(); + + // C++0x [dcl.type.elab]p2: + // If the identifier resolves to a typedef-name or the simple-template-id + // resolves to an alias template specialization, the + // elaborated-type-specifier is ill-formed. + if (T->getKeyword() != ETK_None && T->getKeyword() != ETK_Typename) { + if (const TemplateSpecializationType *TST = + NamedT->getAs<TemplateSpecializationType>()) { + TemplateName Template = TST->getTemplateName(); + if (TypeAliasTemplateDecl *TAT = + dyn_cast_or_null<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) { + SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(), + diag::err_tag_reference_non_tag) << 4; + SemaRef.Diag(TAT->getLocation(), diag::note_declared_at); + } + } + } + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + QualifierLoc != TL.getQualifierLoc() || + NamedT != T->getNamedType()) { + Result = getDerived().RebuildElaboratedType(TL.getKeywordLoc(), + T->getKeyword(), + QualifierLoc, NamedT); + if (Result.isNull()) + return QualType(); + } + + ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierLoc(QualifierLoc); + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformAttributedType( + TypeLocBuilder &TLB, + AttributedTypeLoc TL) { + const AttributedType *oldType = TL.getTypePtr(); + QualType modifiedType = getDerived().TransformType(TLB, TL.getModifiedLoc()); + if (modifiedType.isNull()) + return QualType(); + + QualType result = TL.getType(); + + // FIXME: dependent operand expressions? + if (getDerived().AlwaysRebuild() || + modifiedType != oldType->getModifiedType()) { + // TODO: this is really lame; we should really be rebuilding the + // equivalent type from first principles. + QualType equivalentType + = getDerived().TransformType(oldType->getEquivalentType()); + if (equivalentType.isNull()) + return QualType(); + result = SemaRef.Context.getAttributedType(oldType->getAttrKind(), + modifiedType, + equivalentType); + } + + AttributedTypeLoc newTL = TLB.push<AttributedTypeLoc>(result); + newTL.setAttrNameLoc(TL.getAttrNameLoc()); + if (TL.hasAttrOperand()) + newTL.setAttrOperandParensRange(TL.getAttrOperandParensRange()); + if (TL.hasAttrExprOperand()) + newTL.setAttrExprOperand(TL.getAttrExprOperand()); + else if (TL.hasAttrEnumOperand()) + newTL.setAttrEnumOperandLoc(TL.getAttrEnumOperandLoc()); + + return result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformParenType(TypeLocBuilder &TLB, + ParenTypeLoc TL) { + QualType Inner = getDerived().TransformType(TLB, TL.getInnerLoc()); + if (Inner.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Inner != TL.getInnerLoc().getType()) { + Result = getDerived().RebuildParenType(Inner); + if (Result.isNull()) + return QualType(); + } + + ParenTypeLoc NewTL = TLB.push<ParenTypeLoc>(Result); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, + DependentNameTypeLoc TL) { + const DependentNameType *T = TL.getTypePtr(); + + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) + return QualType(); + + QualType Result + = getDerived().RebuildDependentNameType(T->getKeyword(), + TL.getKeywordLoc(), + QualifierLoc, + T->getIdentifier(), + TL.getNameLoc()); + if (Result.isNull()) + return QualType(); + + if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) { + QualType NamedT = ElabT->getNamedType(); + TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); + + ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierLoc(QualifierLoc); + } else { + DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierLoc(QualifierLoc); + NewTL.setNameLoc(TL.getNameLoc()); + } + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>:: + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL) { + NestedNameSpecifierLoc QualifierLoc; + if (TL.getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(TL.getQualifierLoc()); + if (!QualifierLoc) + return QualType(); + } + + return getDerived() + .TransformDependentTemplateSpecializationType(TLB, TL, QualifierLoc); +} + +template<typename Derived> +QualType TreeTransform<Derived>:: +TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + NestedNameSpecifierLoc QualifierLoc) { + const DependentTemplateSpecializationType *T = TL.getTypePtr(); + + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + + typedef TemplateArgumentLocContainerIterator< + DependentTemplateSpecializationTypeLoc> ArgIterator; + if (getDerived().TransformTemplateArguments(ArgIterator(TL, 0), + ArgIterator(TL, TL.getNumArgs()), + NewTemplateArgs)) + return QualType(); + + QualType Result + = getDerived().RebuildDependentTemplateSpecializationType(T->getKeyword(), + QualifierLoc, + T->getIdentifier(), + TL.getNameLoc(), + NewTemplateArgs); + if (Result.isNull()) + return QualType(); + + if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) { + QualType NamedT = ElabT->getNamedType(); + + // Copy information relevant to the template specialization. + TemplateSpecializationTypeLoc NamedTL + = TLB.push<TemplateSpecializationTypeLoc>(NamedT); + NamedTL.setTemplateNameLoc(TL.getNameLoc()); + NamedTL.setLAngleLoc(TL.getLAngleLoc()); + NamedTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + NamedTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); + + // Copy information relevant to the elaborated type. + ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierLoc(QualifierLoc); + } else if (isa<DependentTemplateSpecializationType>(Result)) { + DependentTemplateSpecializationTypeLoc SpecTL + = TLB.push<DependentTemplateSpecializationTypeLoc>(Result); + SpecTL.setKeywordLoc(TL.getKeywordLoc()); + SpecTL.setQualifierLoc(QualifierLoc); + SpecTL.setNameLoc(TL.getNameLoc()); + SpecTL.setLAngleLoc(TL.getLAngleLoc()); + SpecTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); + } else { + TemplateSpecializationTypeLoc SpecTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + SpecTL.setTemplateNameLoc(TL.getNameLoc()); + SpecTL.setLAngleLoc(TL.getLAngleLoc()); + SpecTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = NewTemplateArgs.size(); I != E; ++I) + SpecTL.setArgLocInfo(I, NewTemplateArgs[I].getLocInfo()); + } + return Result; +} + +template<typename Derived> +QualType TreeTransform<Derived>::TransformPackExpansionType(TypeLocBuilder &TLB, + PackExpansionTypeLoc TL) { + QualType Pattern + = getDerived().TransformType(TLB, TL.getPatternLoc()); + if (Pattern.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + Pattern != TL.getPatternLoc().getType()) { + Result = getDerived().RebuildPackExpansionType(Pattern, + TL.getPatternLoc().getSourceRange(), + TL.getEllipsisLoc(), + TL.getTypePtr()->getNumExpansions()); + if (Result.isNull()) + return QualType(); + } + + PackExpansionTypeLoc NewT = TLB.push<PackExpansionTypeLoc>(Result); + NewT.setEllipsisLoc(TL.getEllipsisLoc()); + return Result; +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB, + ObjCInterfaceTypeLoc TL) { + // ObjCInterfaceType is never dependent. + TLB.pushFullCopy(TL); + return TL.getType(); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformObjCObjectType(TypeLocBuilder &TLB, + ObjCObjectTypeLoc TL) { + // ObjCObjectType is never dependent. + TLB.pushFullCopy(TL); + return TL.getType(); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB, + ObjCObjectPointerTypeLoc TL) { + // ObjCObjectPointerType is never dependent. + TLB.pushFullCopy(TL); + return TL.getType(); +} + +//===----------------------------------------------------------------------===// +// Statement transformation +//===----------------------------------------------------------------------===// +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformNullStmt(NullStmt *S) { + return SemaRef.Owned(S); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S) { + return getDerived().TransformCompoundStmt(S, false); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, + bool IsStmtExpr) { + bool SubStmtInvalid = false; + bool SubStmtChanged = false; + ASTOwningVector<Stmt*> Statements(getSema()); + for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end(); + B != BEnd; ++B) { + StmtResult Result = getDerived().TransformStmt(*B); + if (Result.isInvalid()) { + // Immediately fail if this was a DeclStmt, since it's very + // likely that this will cause problems for future statements. + if (isa<DeclStmt>(*B)) + return StmtError(); + + // Otherwise, just keep processing substatements and fail later. + SubStmtInvalid = true; + continue; + } + + SubStmtChanged = SubStmtChanged || Result.get() != *B; + Statements.push_back(Result.takeAs<Stmt>()); + } + + if (SubStmtInvalid) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && + !SubStmtChanged) + return SemaRef.Owned(S); + + return getDerived().RebuildCompoundStmt(S->getLBracLoc(), + move_arg(Statements), + S->getRBracLoc(), + IsStmtExpr); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCaseStmt(CaseStmt *S) { + ExprResult LHS, RHS; + { + // The case value expressions are not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + // Transform the left-hand case value. + LHS = getDerived().TransformExpr(S->getLHS()); + if (LHS.isInvalid()) + return StmtError(); + + // Transform the right-hand case value (for the GNU case-range extension). + RHS = getDerived().TransformExpr(S->getRHS()); + if (RHS.isInvalid()) + return StmtError(); + } + + // Build the case statement. + // Case statements are always rebuilt so that they will attached to their + // transformed switch statement. + StmtResult Case = getDerived().RebuildCaseStmt(S->getCaseLoc(), + LHS.get(), + S->getEllipsisLoc(), + RHS.get(), + S->getColonLoc()); + if (Case.isInvalid()) + return StmtError(); + + // Transform the statement following the case + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + if (SubStmt.isInvalid()) + return StmtError(); + + // Attach the body to the case statement + return getDerived().RebuildCaseStmtBody(Case.get(), SubStmt.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformDefaultStmt(DefaultStmt *S) { + // Transform the statement following the default case + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + if (SubStmt.isInvalid()) + return StmtError(); + + // Default statements are always rebuilt + return getDerived().RebuildDefaultStmt(S->getDefaultLoc(), S->getColonLoc(), + SubStmt.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) { + StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt()); + if (SubStmt.isInvalid()) + return StmtError(); + + Decl *LD = getDerived().TransformDecl(S->getDecl()->getLocation(), + S->getDecl()); + if (!LD) + return StmtError(); + + + // FIXME: Pass the real colon location in. + return getDerived().RebuildLabelStmt(S->getIdentLoc(), + cast<LabelDecl>(LD), SourceLocation(), + SubStmt.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformIfStmt(IfStmt *S) { + // Transform the condition + ExprResult Cond; + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition( + S->getConditionVariable()->getLocation(), + S->getConditionVariable())); + if (!ConditionVar) + return StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return StmtError(); + + // Convert the condition to a boolean value. + if (S->getCond()) { + ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getIfLoc(), + Cond.get()); + if (CondE.isInvalid()) + return StmtError(); + + Cond = CondE.get(); + } + } + + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take())); + if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) + return StmtError(); + + // Transform the "then" branch. + StmtResult Then = getDerived().TransformStmt(S->getThen()); + if (Then.isInvalid()) + return StmtError(); + + // Transform the "else" branch. + StmtResult Else = getDerived().TransformStmt(S->getElse()); + if (Else.isInvalid()) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && + FullCond.get() == S->getCond() && + ConditionVar == S->getConditionVariable() && + Then.get() == S->getThen() && + Else.get() == S->getElse()) + return SemaRef.Owned(S); + + return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar, + Then.get(), + S->getElseLoc(), Else.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) { + // Transform the condition. + ExprResult Cond; + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition( + S->getConditionVariable()->getLocation(), + S->getConditionVariable())); + if (!ConditionVar) + return StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return StmtError(); + } + + // Rebuild the switch statement. + StmtResult Switch + = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Cond.get(), + ConditionVar); + if (Switch.isInvalid()) + return StmtError(); + + // Transform the body of the switch statement. + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + // Complete the switch statement. + return getDerived().RebuildSwitchStmtBody(S->getSwitchLoc(), Switch.get(), + Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) { + // Transform the condition + ExprResult Cond; + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition( + S->getConditionVariable()->getLocation(), + S->getConditionVariable())); + if (!ConditionVar) + return StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return StmtError(); + + if (S->getCond()) { + // Convert the condition to a boolean value. + ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getWhileLoc(), + Cond.get()); + if (CondE.isInvalid()) + return StmtError(); + Cond = CondE; + } + } + + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take())); + if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) + return StmtError(); + + // Transform the body + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && + FullCond.get() == S->getCond() && + ConditionVar == S->getConditionVariable() && + Body.get() == S->getBody()) + return Owned(S); + + return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, + ConditionVar, Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformDoStmt(DoStmt *S) { + // Transform the body + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + // Transform the condition + ExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && + Cond.get() == S->getCond() && + Body.get() == S->getBody()) + return SemaRef.Owned(S); + + return getDerived().RebuildDoStmt(S->getDoLoc(), Body.get(), S->getWhileLoc(), + /*FIXME:*/S->getWhileLoc(), Cond.get(), + S->getRParenLoc()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformForStmt(ForStmt *S) { + // Transform the initialization statement + StmtResult Init = getDerived().TransformStmt(S->getInit()); + if (Init.isInvalid()) + return StmtError(); + + // Transform the condition + ExprResult Cond; + VarDecl *ConditionVar = 0; + if (S->getConditionVariable()) { + ConditionVar + = cast_or_null<VarDecl>( + getDerived().TransformDefinition( + S->getConditionVariable()->getLocation(), + S->getConditionVariable())); + if (!ConditionVar) + return StmtError(); + } else { + Cond = getDerived().TransformExpr(S->getCond()); + + if (Cond.isInvalid()) + return StmtError(); + + if (S->getCond()) { + // Convert the condition to a boolean value. + ExprResult CondE = getSema().ActOnBooleanCondition(0, S->getForLoc(), + Cond.get()); + if (CondE.isInvalid()) + return StmtError(); + + Cond = CondE.get(); + } + } + + Sema::FullExprArg FullCond(getSema().MakeFullExpr(Cond.take())); + if (!S->getConditionVariable() && S->getCond() && !FullCond.get()) + return StmtError(); + + // Transform the increment + ExprResult Inc = getDerived().TransformExpr(S->getInc()); + if (Inc.isInvalid()) + return StmtError(); + + Sema::FullExprArg FullInc(getSema().MakeFullExpr(Inc.get())); + if (S->getInc() && !FullInc.get()) + return StmtError(); + + // Transform the body + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && + Init.get() == S->getInit() && + FullCond.get() == S->getCond() && + Inc.get() == S->getInc() && + Body.get() == S->getBody()) + return SemaRef.Owned(S); + + return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(), + Init.get(), FullCond, ConditionVar, + FullInc, S->getRParenLoc(), Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformGotoStmt(GotoStmt *S) { + Decl *LD = getDerived().TransformDecl(S->getLabel()->getLocation(), + S->getLabel()); + if (!LD) + return StmtError(); + + // Goto statements must always be rebuilt, to resolve the label. + return getDerived().RebuildGotoStmt(S->getGotoLoc(), S->getLabelLoc(), + cast<LabelDecl>(LD)); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformIndirectGotoStmt(IndirectGotoStmt *S) { + ExprResult Target = getDerived().TransformExpr(S->getTarget()); + if (Target.isInvalid()) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && + Target.get() == S->getTarget()) + return SemaRef.Owned(S); + + return getDerived().RebuildIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(), + Target.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformContinueStmt(ContinueStmt *S) { + return SemaRef.Owned(S); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformBreakStmt(BreakStmt *S) { + return SemaRef.Owned(S); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformReturnStmt(ReturnStmt *S) { + ExprResult Result = getDerived().TransformExpr(S->getRetValue()); + if (Result.isInvalid()) + return StmtError(); + + // FIXME: We always rebuild the return statement because there is no way + // to tell whether the return type of the function has changed. + return getDerived().RebuildReturnStmt(S->getReturnLoc(), Result.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) { + bool DeclChanged = false; + llvm::SmallVector<Decl *, 4> Decls; + for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); + D != DEnd; ++D) { + Decl *Transformed = getDerived().TransformDefinition((*D)->getLocation(), + *D); + if (!Transformed) + return StmtError(); + + if (Transformed != *D) + DeclChanged = true; + + Decls.push_back(Transformed); + } + + if (!getDerived().AlwaysRebuild() && !DeclChanged) + return SemaRef.Owned(S); + + return getDerived().RebuildDeclStmt(Decls.data(), Decls.size(), + S->getStartLoc(), S->getEndLoc()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) { + + ASTOwningVector<Expr*> Constraints(getSema()); + ASTOwningVector<Expr*> Exprs(getSema()); + llvm::SmallVector<IdentifierInfo *, 4> Names; + + ExprResult AsmString; + ASTOwningVector<Expr*> Clobbers(getSema()); + + bool ExprsChanged = false; + + // Go through the outputs. + for (unsigned I = 0, E = S->getNumOutputs(); I != E; ++I) { + Names.push_back(S->getOutputIdentifier(I)); + + // No need to transform the constraint literal. + Constraints.push_back(S->getOutputConstraintLiteral(I)); + + // Transform the output expr. + Expr *OutputExpr = S->getOutputExpr(I); + ExprResult Result = getDerived().TransformExpr(OutputExpr); + if (Result.isInvalid()) + return StmtError(); + + ExprsChanged |= Result.get() != OutputExpr; + + Exprs.push_back(Result.get()); + } + + // Go through the inputs. + for (unsigned I = 0, E = S->getNumInputs(); I != E; ++I) { + Names.push_back(S->getInputIdentifier(I)); + + // No need to transform the constraint literal. + Constraints.push_back(S->getInputConstraintLiteral(I)); + + // Transform the input expr. + Expr *InputExpr = S->getInputExpr(I); + ExprResult Result = getDerived().TransformExpr(InputExpr); + if (Result.isInvalid()) + return StmtError(); + + ExprsChanged |= Result.get() != InputExpr; + + Exprs.push_back(Result.get()); + } + + if (!getDerived().AlwaysRebuild() && !ExprsChanged) + return SemaRef.Owned(S); + + // Go through the clobbers. + for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I) + Clobbers.push_back(S->getClobber(I)); + + // No need to transform the asm string literal. + AsmString = SemaRef.Owned(S->getAsmString()); + + return getDerived().RebuildAsmStmt(S->getAsmLoc(), + S->isSimple(), + S->isVolatile(), + S->getNumOutputs(), + S->getNumInputs(), + Names.data(), + move_arg(Constraints), + move_arg(Exprs), + AsmString.get(), + move_arg(Clobbers), + S->getRParenLoc(), + S->isMSAsm()); +} + + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) { + // Transform the body of the @try. + StmtResult TryBody = getDerived().TransformStmt(S->getTryBody()); + if (TryBody.isInvalid()) + return StmtError(); + + // Transform the @catch statements (if present). + bool AnyCatchChanged = false; + ASTOwningVector<Stmt*> CatchStmts(SemaRef); + for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { + StmtResult Catch = getDerived().TransformStmt(S->getCatchStmt(I)); + if (Catch.isInvalid()) + return StmtError(); + if (Catch.get() != S->getCatchStmt(I)) + AnyCatchChanged = true; + CatchStmts.push_back(Catch.release()); + } + + // Transform the @finally statement (if present). + StmtResult Finally; + if (S->getFinallyStmt()) { + Finally = getDerived().TransformStmt(S->getFinallyStmt()); + if (Finally.isInvalid()) + return StmtError(); + } + + // If nothing changed, just retain this statement. + if (!getDerived().AlwaysRebuild() && + TryBody.get() == S->getTryBody() && + !AnyCatchChanged && + Finally.get() == S->getFinallyStmt()) + return SemaRef.Owned(S); + + // Build a new statement. + return getDerived().RebuildObjCAtTryStmt(S->getAtTryLoc(), TryBody.get(), + move_arg(CatchStmts), Finally.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformObjCAtCatchStmt(ObjCAtCatchStmt *S) { + // Transform the @catch parameter, if there is one. + VarDecl *Var = 0; + if (VarDecl *FromVar = S->getCatchParamDecl()) { + TypeSourceInfo *TSInfo = 0; + if (FromVar->getTypeSourceInfo()) { + TSInfo = getDerived().TransformType(FromVar->getTypeSourceInfo()); + if (!TSInfo) + return StmtError(); + } + + QualType T; + if (TSInfo) + T = TSInfo->getType(); + else { + T = getDerived().TransformType(FromVar->getType()); + if (T.isNull()) + return StmtError(); + } + + Var = getDerived().RebuildObjCExceptionDecl(FromVar, TSInfo, T); + if (!Var) + return StmtError(); + } + + StmtResult Body = getDerived().TransformStmt(S->getCatchBody()); + if (Body.isInvalid()) + return StmtError(); + + return getDerived().RebuildObjCAtCatchStmt(S->getAtCatchLoc(), + S->getRParenLoc(), + Var, Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { + // Transform the body. + StmtResult Body = getDerived().TransformStmt(S->getFinallyBody()); + if (Body.isInvalid()) + return StmtError(); + + // If nothing changed, just retain this statement. + if (!getDerived().AlwaysRebuild() && + Body.get() == S->getFinallyBody()) + return SemaRef.Owned(S); + + // Build a new statement. + return getDerived().RebuildObjCAtFinallyStmt(S->getAtFinallyLoc(), + Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformObjCAtThrowStmt(ObjCAtThrowStmt *S) { + ExprResult Operand; + if (S->getThrowExpr()) { + Operand = getDerived().TransformExpr(S->getThrowExpr()); + if (Operand.isInvalid()) + return StmtError(); + } + + if (!getDerived().AlwaysRebuild() && + Operand.get() == S->getThrowExpr()) + return getSema().Owned(S); + + return getDerived().RebuildObjCAtThrowStmt(S->getThrowLoc(), Operand.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformObjCAtSynchronizedStmt( + ObjCAtSynchronizedStmt *S) { + // Transform the object we are locking. + ExprResult Object = getDerived().TransformExpr(S->getSynchExpr()); + if (Object.isInvalid()) + return StmtError(); + + // Transform the body. + StmtResult Body = getDerived().TransformStmt(S->getSynchBody()); + if (Body.isInvalid()) + return StmtError(); + + // If nothing change, just retain the current statement. + if (!getDerived().AlwaysRebuild() && + Object.get() == S->getSynchExpr() && + Body.get() == S->getSynchBody()) + return SemaRef.Owned(S); + + // Build a new statement. + return getDerived().RebuildObjCAtSynchronizedStmt(S->getAtSynchronizedLoc(), + Object.get(), Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformObjCForCollectionStmt( + ObjCForCollectionStmt *S) { + // Transform the element statement. + StmtResult Element = getDerived().TransformStmt(S->getElement()); + if (Element.isInvalid()) + return StmtError(); + + // Transform the collection expression. + ExprResult Collection = getDerived().TransformExpr(S->getCollection()); + if (Collection.isInvalid()) + return StmtError(); + + // Transform the body. + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + // If nothing changed, just retain this statement. + if (!getDerived().AlwaysRebuild() && + Element.get() == S->getElement() && + Collection.get() == S->getCollection() && + Body.get() == S->getBody()) + return SemaRef.Owned(S); + + // Build a new statement. + return getDerived().RebuildObjCForCollectionStmt(S->getForLoc(), + /*FIXME:*/S->getForLoc(), + Element.get(), + Collection.get(), + S->getRParenLoc(), + Body.get()); +} + + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCXXCatchStmt(CXXCatchStmt *S) { + // Transform the exception declaration, if any. + VarDecl *Var = 0; + if (S->getExceptionDecl()) { + VarDecl *ExceptionDecl = S->getExceptionDecl(); + TypeSourceInfo *T = getDerived().TransformType( + ExceptionDecl->getTypeSourceInfo()); + if (!T) + return StmtError(); + + Var = getDerived().RebuildExceptionDecl(ExceptionDecl, T, + ExceptionDecl->getInnerLocStart(), + ExceptionDecl->getLocation(), + ExceptionDecl->getIdentifier()); + if (!Var || Var->isInvalidDecl()) + return StmtError(); + } + + // Transform the actual exception handler. + StmtResult Handler = getDerived().TransformStmt(S->getHandlerBlock()); + if (Handler.isInvalid()) + return StmtError(); + + if (!getDerived().AlwaysRebuild() && + !Var && + Handler.get() == S->getHandlerBlock()) + return SemaRef.Owned(S); + + return getDerived().RebuildCXXCatchStmt(S->getCatchLoc(), + Var, + Handler.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { + // Transform the try block itself. + StmtResult TryBlock + = getDerived().TransformCompoundStmt(S->getTryBlock()); + if (TryBlock.isInvalid()) + return StmtError(); + + // Transform the handlers. + bool HandlerChanged = false; + ASTOwningVector<Stmt*> Handlers(SemaRef); + for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) { + StmtResult Handler + = getDerived().TransformCXXCatchStmt(S->getHandler(I)); + if (Handler.isInvalid()) + return StmtError(); + + HandlerChanged = HandlerChanged || Handler.get() != S->getHandler(I); + Handlers.push_back(Handler.takeAs<Stmt>()); + } + + if (!getDerived().AlwaysRebuild() && + TryBlock.get() == S->getTryBlock() && + !HandlerChanged) + return SemaRef.Owned(S); + + return getDerived().RebuildCXXTryStmt(S->getTryLoc(), TryBlock.get(), + move_arg(Handlers)); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformCXXForRangeStmt(CXXForRangeStmt *S) { + StmtResult Range = getDerived().TransformStmt(S->getRangeStmt()); + if (Range.isInvalid()) + return StmtError(); + + StmtResult BeginEnd = getDerived().TransformStmt(S->getBeginEndStmt()); + if (BeginEnd.isInvalid()) + return StmtError(); + + ExprResult Cond = getDerived().TransformExpr(S->getCond()); + if (Cond.isInvalid()) + return StmtError(); + + ExprResult Inc = getDerived().TransformExpr(S->getInc()); + if (Inc.isInvalid()) + return StmtError(); + + StmtResult LoopVar = getDerived().TransformStmt(S->getLoopVarStmt()); + if (LoopVar.isInvalid()) + return StmtError(); + + StmtResult NewStmt = S; + if (getDerived().AlwaysRebuild() || + Range.get() != S->getRangeStmt() || + BeginEnd.get() != S->getBeginEndStmt() || + Cond.get() != S->getCond() || + Inc.get() != S->getInc() || + LoopVar.get() != S->getLoopVarStmt()) + NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getColonLoc(), Range.get(), + BeginEnd.get(), Cond.get(), + Inc.get(), LoopVar.get(), + S->getRParenLoc()); + + StmtResult Body = getDerived().TransformStmt(S->getBody()); + if (Body.isInvalid()) + return StmtError(); + + // Body has changed but we didn't rebuild the for-range statement. Rebuild + // it now so we have a new statement to attach the body to. + if (Body.get() != S->getBody() && NewStmt.get() == S) + NewStmt = getDerived().RebuildCXXForRangeStmt(S->getForLoc(), + S->getColonLoc(), Range.get(), + BeginEnd.get(), Cond.get(), + Inc.get(), LoopVar.get(), + S->getRParenLoc()); + + if (NewStmt.get() == S) + return SemaRef.Owned(S); + + return FinishCXXForRangeStmt(NewStmt.get(), Body.get()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHTryStmt(SEHTryStmt *S) { + StmtResult TryBlock; // = getDerived().TransformCompoundStmt(S->getTryBlock()); + if(TryBlock.isInvalid()) return StmtError(); + + StmtResult Handler = getDerived().TransformSEHHandler(S->getHandler()); + if(!getDerived().AlwaysRebuild() && + TryBlock.get() == S->getTryBlock() && + Handler.get() == S->getHandler()) + return SemaRef.Owned(S); + + return getDerived().RebuildSEHTryStmt(S->getIsCXXTry(), + S->getTryLoc(), + TryBlock.take(), + Handler.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHFinallyStmt(SEHFinallyStmt *S) { + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHFinallyStmt(S->getFinallyLoc(), + Block.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHExceptStmt(SEHExceptStmt *S) { + ExprResult FilterExpr = getDerived().TransformExpr(S->getFilterExpr()); + if(FilterExpr.isInvalid()) return StmtError(); + + StmtResult Block; // = getDerived().TransformCompoundStatement(S->getBlock()); + if(Block.isInvalid()) return StmtError(); + + return getDerived().RebuildSEHExceptStmt(S->getExceptLoc(), + FilterExpr.take(), + Block.take()); +} + +template<typename Derived> +StmtResult +TreeTransform<Derived>::TransformSEHHandler(Stmt *Handler) { + if(isa<SEHFinallyStmt>(Handler)) + return getDerived().TransformSEHFinallyStmt(cast<SEHFinallyStmt>(Handler)); + else + return getDerived().TransformSEHExceptStmt(cast<SEHExceptStmt>(Handler)); +} + +//===----------------------------------------------------------------------===// +// Expression transformation +//===----------------------------------------------------------------------===// +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { + NestedNameSpecifierLoc QualifierLoc; + if (E->getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + if (!QualifierLoc) + return ExprError(); + } + + ValueDecl *ND + = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(), + E->getDecl())); + if (!ND) + return ExprError(); + + DeclarationNameInfo NameInfo = E->getNameInfo(); + if (NameInfo.getName()) { + NameInfo = getDerived().TransformDeclarationNameInfo(NameInfo); + if (!NameInfo.getName()) + return ExprError(); + } + + if (!getDerived().AlwaysRebuild() && + QualifierLoc == E->getQualifierLoc() && + ND == E->getDecl() && + NameInfo.getName() == E->getDecl()->getDeclName() && + !E->hasExplicitTemplateArgs()) { + + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); + + return SemaRef.Owned(E); + } + + TemplateArgumentListInfo TransArgs, *TemplateArgs = 0; + if (E->hasExplicitTemplateArgs()) { + TemplateArgs = &TransArgs; + TransArgs.setLAngleLoc(E->getLAngleLoc()); + TransArgs.setRAngleLoc(E->getRAngleLoc()); + if (getDerived().TransformTemplateArguments(E->getTemplateArgs(), + E->getNumTemplateArgs(), + TransArgs)) + return ExprError(); + } + + return getDerived().RebuildDeclRefExpr(QualifierLoc, ND, NameInfo, + TemplateArgs); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformGenericSelectionExpr(GenericSelectionExpr *E) { + ExprResult ControllingExpr = + getDerived().TransformExpr(E->getControllingExpr()); + if (ControllingExpr.isInvalid()) + return ExprError(); + + llvm::SmallVector<Expr *, 4> AssocExprs; + llvm::SmallVector<TypeSourceInfo *, 4> AssocTypes; + for (unsigned i = 0; i != E->getNumAssocs(); ++i) { + TypeSourceInfo *TS = E->getAssocTypeSourceInfo(i); + if (TS) { + TypeSourceInfo *AssocType = getDerived().TransformType(TS); + if (!AssocType) + return ExprError(); + AssocTypes.push_back(AssocType); + } else { + AssocTypes.push_back(0); + } + + ExprResult AssocExpr = getDerived().TransformExpr(E->getAssocExpr(i)); + if (AssocExpr.isInvalid()) + return ExprError(); + AssocExprs.push_back(AssocExpr.release()); + } + + return getDerived().RebuildGenericSelectionExpr(E->getGenericLoc(), + E->getDefaultLoc(), + E->getRParenLoc(), + ControllingExpr.release(), + AssocTypes.data(), + AssocExprs.data(), + E->getNumAssocs()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) { + ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildParenExpr(SubExpr.get(), E->getLParen(), + E->getRParen()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) { + ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getSubExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildUnaryOperator(E->getOperatorLoc(), + E->getOpcode(), + SubExpr.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformOffsetOfExpr(OffsetOfExpr *E) { + // Transform the type. + TypeSourceInfo *Type = getDerived().TransformType(E->getTypeSourceInfo()); + if (!Type) + return ExprError(); + + // Transform all of the components into components similar to what the + // parser uses. + // FIXME: It would be slightly more efficient in the non-dependent case to + // just map FieldDecls, rather than requiring the rebuilder to look for + // the fields again. However, __builtin_offsetof is rare enough in + // template code that we don't care. + bool ExprChanged = false; + typedef Sema::OffsetOfComponent Component; + typedef OffsetOfExpr::OffsetOfNode Node; + llvm::SmallVector<Component, 4> Components; + for (unsigned I = 0, N = E->getNumComponents(); I != N; ++I) { + const Node &ON = E->getComponent(I); + Component Comp; + Comp.isBrackets = true; + Comp.LocStart = ON.getSourceRange().getBegin(); + Comp.LocEnd = ON.getSourceRange().getEnd(); + switch (ON.getKind()) { + case Node::Array: { + Expr *FromIndex = E->getIndexExpr(ON.getArrayExprIndex()); + ExprResult Index = getDerived().TransformExpr(FromIndex); + if (Index.isInvalid()) + return ExprError(); + + ExprChanged = ExprChanged || Index.get() != FromIndex; + Comp.isBrackets = true; + Comp.U.E = Index.get(); + break; + } + + case Node::Field: + case Node::Identifier: + Comp.isBrackets = false; + Comp.U.IdentInfo = ON.getFieldName(); + if (!Comp.U.IdentInfo) + continue; + + break; + + case Node::Base: + // Will be recomputed during the rebuild. + continue; + } + + Components.push_back(Comp); + } + + // If nothing changed, retain the existing expression. + if (!getDerived().AlwaysRebuild() && + Type == E->getTypeSourceInfo() && + !ExprChanged) + return SemaRef.Owned(E); + + // Build a new offsetof expression. + return getDerived().RebuildOffsetOfExpr(E->getOperatorLoc(), Type, + Components.data(), Components.size(), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformOpaqueValueExpr(OpaqueValueExpr *E) { + assert(getDerived().AlreadyTransformed(E->getType()) && + "opaque value expression requires transformation"); + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr( + UnaryExprOrTypeTraitExpr *E) { + if (E->isArgumentType()) { + TypeSourceInfo *OldT = E->getArgumentTypeInfo(); + + TypeSourceInfo *NewT = getDerived().TransformType(OldT); + if (!NewT) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && OldT == NewT) + return SemaRef.Owned(E); + + return getDerived().RebuildUnaryExprOrTypeTrait(NewT, E->getOperatorLoc(), + E->getKind(), + E->getSourceRange()); + } + + ExprResult SubExpr; + { + // C++0x [expr.sizeof]p1: + // The operand is either an expression, which is an unevaluated operand + // [...] + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + SubExpr = getDerived().TransformExpr(E->getArgumentExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getArgumentExpr()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildUnaryExprOrTypeTrait(SubExpr.get(), + E->getOperatorLoc(), + E->getKind(), + E->getSourceRange()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) { + ExprResult LHS = getDerived().TransformExpr(E->getLHS()); + if (LHS.isInvalid()) + return ExprError(); + + ExprResult RHS = getDerived().TransformExpr(E->getRHS()); + if (RHS.isInvalid()) + return ExprError(); + + + if (!getDerived().AlwaysRebuild() && + LHS.get() == E->getLHS() && + RHS.get() == E->getRHS()) + return SemaRef.Owned(E); + + return getDerived().RebuildArraySubscriptExpr(LHS.get(), + /*FIXME:*/E->getLHS()->getLocStart(), + RHS.get(), + E->getRBracketLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { + // Transform the callee. + ExprResult Callee = getDerived().TransformExpr(E->getCallee()); + if (Callee.isInvalid()) + return ExprError(); + + // Transform arguments. + bool ArgChanged = false; + ASTOwningVector<Expr*> Args(SemaRef); + if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, + &ArgChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Callee.get() == E->getCallee() && + !ArgChanged) + return SemaRef.Owned(E); + + // FIXME: Wrong source location information for the '('. + SourceLocation FakeLParenLoc + = ((Expr *)Callee.get())->getSourceRange().getBegin(); + return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc, + move_arg(Args), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + NestedNameSpecifierLoc QualifierLoc; + if (E->hasQualifier()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + + if (!QualifierLoc) + return ExprError(); + } + + ValueDecl *Member + = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getMemberLoc(), + E->getMemberDecl())); + if (!Member) + return ExprError(); + + NamedDecl *FoundDecl = E->getFoundDecl(); + if (FoundDecl == E->getMemberDecl()) { + FoundDecl = Member; + } else { + FoundDecl = cast_or_null<NamedDecl>( + getDerived().TransformDecl(E->getMemberLoc(), FoundDecl)); + if (!FoundDecl) + return ExprError(); + } + + if (!getDerived().AlwaysRebuild() && + Base.get() == E->getBase() && + QualifierLoc == E->getQualifierLoc() && + Member == E->getMemberDecl() && + FoundDecl == E->getFoundDecl() && + !E->hasExplicitTemplateArgs()) { + + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member); + return SemaRef.Owned(E); + } + + TemplateArgumentListInfo TransArgs; + if (E->hasExplicitTemplateArgs()) { + TransArgs.setLAngleLoc(E->getLAngleLoc()); + TransArgs.setRAngleLoc(E->getRAngleLoc()); + if (getDerived().TransformTemplateArguments(E->getTemplateArgs(), + E->getNumTemplateArgs(), + TransArgs)) + return ExprError(); + } + + // FIXME: Bogus source location for the operator + SourceLocation FakeOperatorLoc + = SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd()); + + // FIXME: to do this check properly, we will need to preserve the + // first-qualifier-in-scope here, just in case we had a dependent + // base (and therefore couldn't do the check) and a + // nested-name-qualifier (and therefore could do the lookup). + NamedDecl *FirstQualifierInScope = 0; + + return getDerived().RebuildMemberExpr(Base.get(), FakeOperatorLoc, + E->isArrow(), + QualifierLoc, + E->getMemberNameInfo(), + Member, + FoundDecl, + (E->hasExplicitTemplateArgs() + ? &TransArgs : 0), + FirstQualifierInScope); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { + ExprResult LHS = getDerived().TransformExpr(E->getLHS()); + if (LHS.isInvalid()) + return ExprError(); + + ExprResult RHS = getDerived().TransformExpr(E->getRHS()); + if (RHS.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + LHS.get() == E->getLHS() && + RHS.get() == E->getRHS()) + return SemaRef.Owned(E); + + return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(), + LHS.get(), RHS.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCompoundAssignOperator( + CompoundAssignOperator *E) { + return getDerived().TransformBinaryOperator(E); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>:: +TransformBinaryConditionalOperator(BinaryConditionalOperator *e) { + // Just rebuild the common and RHS expressions and see whether we + // get any changes. + + ExprResult commonExpr = getDerived().TransformExpr(e->getCommon()); + if (commonExpr.isInvalid()) + return ExprError(); + + ExprResult rhs = getDerived().TransformExpr(e->getFalseExpr()); + if (rhs.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + commonExpr.get() == e->getCommon() && + rhs.get() == e->getFalseExpr()) + return SemaRef.Owned(e); + + return getDerived().RebuildConditionalOperator(commonExpr.take(), + e->getQuestionLoc(), + 0, + e->getColonLoc(), + rhs.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) { + ExprResult Cond = getDerived().TransformExpr(E->getCond()); + if (Cond.isInvalid()) + return ExprError(); + + ExprResult LHS = getDerived().TransformExpr(E->getLHS()); + if (LHS.isInvalid()) + return ExprError(); + + ExprResult RHS = getDerived().TransformExpr(E->getRHS()); + if (RHS.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Cond.get() == E->getCond() && + LHS.get() == E->getLHS() && + RHS.get() == E->getRHS()) + return SemaRef.Owned(E); + + return getDerived().RebuildConditionalOperator(Cond.get(), + E->getQuestionLoc(), + LHS.get(), + E->getColonLoc(), + RHS.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) { + // Implicit casts are eliminated during transformation, since they + // will be recomputed by semantic analysis after transformation. + return getDerived().TransformExpr(E->getSubExprAsWritten()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) { + TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten()); + if (!Type) + return ExprError(); + + ExprResult SubExpr + = getDerived().TransformExpr(E->getSubExprAsWritten()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Type == E->getTypeInfoAsWritten() && + SubExpr.get() == E->getSubExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildCStyleCastExpr(E->getLParenLoc(), + Type, + E->getRParenLoc(), + SubExpr.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) { + TypeSourceInfo *OldT = E->getTypeSourceInfo(); + TypeSourceInfo *NewT = getDerived().TransformType(OldT); + if (!NewT) + return ExprError(); + + ExprResult Init = getDerived().TransformExpr(E->getInitializer()); + if (Init.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + OldT == NewT && + Init.get() == E->getInitializer()) + return SemaRef.Owned(E); + + // Note: the expression type doesn't necessarily match the + // type-as-written, but that's okay, because it should always be + // derivable from the initializer. + + return getDerived().RebuildCompoundLiteralExpr(E->getLParenLoc(), NewT, + /*FIXME:*/E->getInitializer()->getLocEnd(), + Init.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) { + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Base.get() == E->getBase()) + return SemaRef.Owned(E); + + // FIXME: Bad source location + SourceLocation FakeOperatorLoc + = SemaRef.PP.getLocForEndOfToken(E->getBase()->getLocEnd()); + return getDerived().RebuildExtVectorElementExpr(Base.get(), FakeOperatorLoc, + E->getAccessorLoc(), + E->getAccessor()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { + bool InitChanged = false; + + ASTOwningVector<Expr*, 4> Inits(SemaRef); + if (getDerived().TransformExprs(E->getInits(), E->getNumInits(), false, + Inits, &InitChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && !InitChanged) + return SemaRef.Owned(E); + + return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits), + E->getRBraceLoc(), E->getType()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { + Designation Desig; + + // transform the initializer value + ExprResult Init = getDerived().TransformExpr(E->getInit()); + if (Init.isInvalid()) + return ExprError(); + + // transform the designators. + ASTOwningVector<Expr*, 4> ArrayExprs(SemaRef); + bool ExprChanged = false; + for (DesignatedInitExpr::designators_iterator D = E->designators_begin(), + DEnd = E->designators_end(); + D != DEnd; ++D) { + if (D->isFieldDesignator()) { + Desig.AddDesignator(Designator::getField(D->getFieldName(), + D->getDotLoc(), + D->getFieldLoc())); + continue; + } + + if (D->isArrayDesignator()) { + ExprResult Index = getDerived().TransformExpr(E->getArrayIndex(*D)); + if (Index.isInvalid()) + return ExprError(); + + Desig.AddDesignator(Designator::getArray(Index.get(), + D->getLBracketLoc())); + + ExprChanged = ExprChanged || Init.get() != E->getArrayIndex(*D); + ArrayExprs.push_back(Index.release()); + continue; + } + + assert(D->isArrayRangeDesignator() && "New kind of designator?"); + ExprResult Start + = getDerived().TransformExpr(E->getArrayRangeStart(*D)); + if (Start.isInvalid()) + return ExprError(); + + ExprResult End = getDerived().TransformExpr(E->getArrayRangeEnd(*D)); + if (End.isInvalid()) + return ExprError(); + + Desig.AddDesignator(Designator::getArrayRange(Start.get(), + End.get(), + D->getLBracketLoc(), + D->getEllipsisLoc())); + + ExprChanged = ExprChanged || Start.get() != E->getArrayRangeStart(*D) || + End.get() != E->getArrayRangeEnd(*D); + + ArrayExprs.push_back(Start.release()); + ArrayExprs.push_back(End.release()); + } + + if (!getDerived().AlwaysRebuild() && + Init.get() == E->getInit() && + !ExprChanged) + return SemaRef.Owned(E); + + return getDerived().RebuildDesignatedInitExpr(Desig, move_arg(ArrayExprs), + E->getEqualOrColonLoc(), + E->usesGNUSyntax(), Init.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformImplicitValueInitExpr( + ImplicitValueInitExpr *E) { + TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName()); + + // FIXME: Will we ever have proper type location here? Will we actually + // need to transform the type? + QualType T = getDerived().TransformType(E->getType()); + if (T.isNull()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getType()) + return SemaRef.Owned(E); + + return getDerived().RebuildImplicitValueInitExpr(T); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) { + TypeSourceInfo *TInfo = getDerived().TransformType(E->getWrittenTypeInfo()); + if (!TInfo) + return ExprError(); + + ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + TInfo == E->getWrittenTypeInfo() && + SubExpr.get() == E->getSubExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildVAArgExpr(E->getBuiltinLoc(), SubExpr.get(), + TInfo, E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) { + bool ArgumentChanged = false; + ASTOwningVector<Expr*, 4> Inits(SemaRef); + if (TransformExprs(E->getExprs(), E->getNumExprs(), true, Inits, + &ArgumentChanged)) + return ExprError(); + + return getDerived().RebuildParenListExpr(E->getLParenLoc(), + move_arg(Inits), + E->getRParenLoc()); +} + +/// \brief Transform an address-of-label expression. +/// +/// By default, the transformation of an address-of-label expression always +/// rebuilds the expression, so that the label identifier can be resolved to +/// the corresponding label statement by semantic analysis. +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) { + Decl *LD = getDerived().TransformDecl(E->getLabel()->getLocation(), + E->getLabel()); + if (!LD) + return ExprError(); + + return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(), + cast<LabelDecl>(LD)); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) { + StmtResult SubStmt + = getDerived().TransformCompoundStmt(E->getSubStmt(), true); + if (SubStmt.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + SubStmt.get() == E->getSubStmt()) + return SemaRef.Owned(E); + + return getDerived().RebuildStmtExpr(E->getLParenLoc(), + SubStmt.get(), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) { + ExprResult Cond = getDerived().TransformExpr(E->getCond()); + if (Cond.isInvalid()) + return ExprError(); + + ExprResult LHS = getDerived().TransformExpr(E->getLHS()); + if (LHS.isInvalid()) + return ExprError(); + + ExprResult RHS = getDerived().TransformExpr(E->getRHS()); + if (RHS.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Cond.get() == E->getCond() && + LHS.get() == E->getLHS() && + RHS.get() == E->getRHS()) + return SemaRef.Owned(E); + + return getDerived().RebuildChooseExpr(E->getBuiltinLoc(), + Cond.get(), LHS.get(), RHS.get(), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + switch (E->getOperator()) { + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + llvm_unreachable("new and delete operators cannot use CXXOperatorCallExpr"); + return ExprError(); + + case OO_Call: { + // This is a call to an object's operator(). + assert(E->getNumArgs() >= 1 && "Object call is missing arguments"); + + // Transform the object itself. + ExprResult Object = getDerived().TransformExpr(E->getArg(0)); + if (Object.isInvalid()) + return ExprError(); + + // FIXME: Poor location information + SourceLocation FakeLParenLoc + = SemaRef.PP.getLocForEndOfToken( + static_cast<Expr *>(Object.get())->getLocEnd()); + + // Transform the call arguments. + ASTOwningVector<Expr*> Args(SemaRef); + if (getDerived().TransformExprs(E->getArgs() + 1, E->getNumArgs() - 1, true, + Args)) + return ExprError(); + + return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc, + move_arg(Args), + E->getLocEnd()); + } + +#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ + case OO_##Name: +#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) +#include "clang/Basic/OperatorKinds.def" + case OO_Subscript: + // Handled below. + break; + + case OO_Conditional: + llvm_unreachable("conditional operator is not actually overloadable"); + return ExprError(); + + case OO_None: + case NUM_OVERLOADED_OPERATORS: + llvm_unreachable("not an overloaded operator?"); + return ExprError(); + } + + ExprResult Callee = getDerived().TransformExpr(E->getCallee()); + if (Callee.isInvalid()) + return ExprError(); + + ExprResult First = getDerived().TransformExpr(E->getArg(0)); + if (First.isInvalid()) + return ExprError(); + + ExprResult Second; + if (E->getNumArgs() == 2) { + Second = getDerived().TransformExpr(E->getArg(1)); + if (Second.isInvalid()) + return ExprError(); + } + + if (!getDerived().AlwaysRebuild() && + Callee.get() == E->getCallee() && + First.get() == E->getArg(0) && + (E->getNumArgs() != 2 || Second.get() == E->getArg(1))) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), + E->getOperatorLoc(), + Callee.get(), + First.get(), + Second.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) { + return getDerived().TransformCallExpr(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) { + // Transform the callee. + ExprResult Callee = getDerived().TransformExpr(E->getCallee()); + if (Callee.isInvalid()) + return ExprError(); + + // Transform exec config. + ExprResult EC = getDerived().TransformCallExpr(E->getConfig()); + if (EC.isInvalid()) + return ExprError(); + + // Transform arguments. + bool ArgChanged = false; + ASTOwningVector<Expr*> Args(SemaRef); + if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, + &ArgChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Callee.get() == E->getCallee() && + !ArgChanged) + return SemaRef.Owned(E); + + // FIXME: Wrong source location information for the '('. + SourceLocation FakeLParenLoc + = ((Expr *)Callee.get())->getSourceRange().getBegin(); + return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc, + move_arg(Args), + E->getRParenLoc(), EC.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { + TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten()); + if (!Type) + return ExprError(); + + ExprResult SubExpr + = getDerived().TransformExpr(E->getSubExprAsWritten()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Type == E->getTypeInfoAsWritten() && + SubExpr.get() == E->getSubExpr()) + return SemaRef.Owned(E); + + // FIXME: Poor source location information here. + SourceLocation FakeLAngleLoc + = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc()); + SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin(); + SourceLocation FakeRParenLoc + = SemaRef.PP.getLocForEndOfToken( + E->getSubExpr()->getSourceRange().getEnd()); + return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(), + E->getStmtClass(), + FakeLAngleLoc, + Type, + FakeRAngleLoc, + FakeRAngleLoc, + SubExpr.get(), + FakeRParenLoc); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXReinterpretCastExpr( + CXXReinterpretCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) { + return getDerived().TransformCXXNamedCastExpr(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXFunctionalCastExpr( + CXXFunctionalCastExpr *E) { + TypeSourceInfo *Type = getDerived().TransformType(E->getTypeInfoAsWritten()); + if (!Type) + return ExprError(); + + ExprResult SubExpr + = getDerived().TransformExpr(E->getSubExprAsWritten()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Type == E->getTypeInfoAsWritten() && + SubExpr.get() == E->getSubExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXFunctionalCastExpr(Type, + /*FIXME:*/E->getSubExpr()->getLocStart(), + SubExpr.get(), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { + if (E->isTypeOperand()) { + TypeSourceInfo *TInfo + = getDerived().TransformType(E->getTypeOperandSourceInfo()); + if (!TInfo) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + TInfo == E->getTypeOperandSourceInfo()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXTypeidExpr(E->getType(), + E->getLocStart(), + TInfo, + E->getLocEnd()); + } + + // We don't know whether the expression is potentially evaluated until + // after we perform semantic analysis, so the expression is potentially + // potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Sema::PotentiallyPotentiallyEvaluated); + + ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + SubExpr.get() == E->getExprOperand()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXTypeidExpr(E->getType(), + E->getLocStart(), + SubExpr.get(), + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXUuidofExpr(CXXUuidofExpr *E) { + if (E->isTypeOperand()) { + TypeSourceInfo *TInfo + = getDerived().TransformType(E->getTypeOperandSourceInfo()); + if (!TInfo) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + TInfo == E->getTypeOperandSourceInfo()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXUuidofExpr(E->getType(), + E->getLocStart(), + TInfo, + E->getLocEnd()); + } + + // We don't know whether the expression is potentially evaluated until + // after we perform semantic analysis, so the expression is potentially + // potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + + ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + SubExpr.get() == E->getExprOperand()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXUuidofExpr(E->getType(), + E->getLocStart(), + SubExpr.get(), + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr( + CXXNullPtrLiteralExpr *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { + DeclContext *DC = getSema().getFunctionLevelDeclContext(); + QualType T; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) + T = MD->getThisType(getSema().Context); + else + T = getSema().Context.getPointerType( + getSema().Context.getRecordType(cast<CXXRecordDecl>(DC))); + + if (!getDerived().AlwaysRebuild() && T == E->getType()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXThisExpr(E->getLocStart(), T, E->isImplicit()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) { + ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + SubExpr.get() == E->getSubExpr()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXThrowExpr(E->getThrowLoc(), SubExpr.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { + ParmVarDecl *Param + = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getLocStart(), + E->getParam())); + if (!Param) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + Param == E->getParam()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXDefaultArgExpr(E->getUsedLocation(), Param); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXScalarValueInitExpr( + CXXScalarValueInitExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); + if (!T) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getTypeSourceInfo()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXScalarValueInitExpr(T, + /*FIXME:*/T->getTypeLoc().getEndLoc(), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { + // Transform the type that we're allocating + TypeSourceInfo *AllocTypeInfo + = getDerived().TransformType(E->getAllocatedTypeSourceInfo()); + if (!AllocTypeInfo) + return ExprError(); + + // Transform the size of the array we're allocating (if any). + ExprResult ArraySize = getDerived().TransformExpr(E->getArraySize()); + if (ArraySize.isInvalid()) + return ExprError(); + + // Transform the placement arguments (if any). + bool ArgumentChanged = false; + ASTOwningVector<Expr*> PlacementArgs(SemaRef); + if (getDerived().TransformExprs(E->getPlacementArgs(), + E->getNumPlacementArgs(), true, + PlacementArgs, &ArgumentChanged)) + return ExprError(); + + // transform the constructor arguments (if any). + ASTOwningVector<Expr*> ConstructorArgs(SemaRef); + if (TransformExprs(E->getConstructorArgs(), E->getNumConstructorArgs(), true, + ConstructorArgs, &ArgumentChanged)) + return ExprError(); + + // Transform constructor, new operator, and delete operator. + CXXConstructorDecl *Constructor = 0; + if (E->getConstructor()) { + Constructor = cast_or_null<CXXConstructorDecl>( + getDerived().TransformDecl(E->getLocStart(), + E->getConstructor())); + if (!Constructor) + return ExprError(); + } + + FunctionDecl *OperatorNew = 0; + if (E->getOperatorNew()) { + OperatorNew = cast_or_null<FunctionDecl>( + getDerived().TransformDecl(E->getLocStart(), + E->getOperatorNew())); + if (!OperatorNew) + return ExprError(); + } + + FunctionDecl *OperatorDelete = 0; + if (E->getOperatorDelete()) { + OperatorDelete = cast_or_null<FunctionDecl>( + getDerived().TransformDecl(E->getLocStart(), + E->getOperatorDelete())); + if (!OperatorDelete) + return ExprError(); + } + + if (!getDerived().AlwaysRebuild() && + AllocTypeInfo == E->getAllocatedTypeSourceInfo() && + ArraySize.get() == E->getArraySize() && + Constructor == E->getConstructor() && + OperatorNew == E->getOperatorNew() && + OperatorDelete == E->getOperatorDelete() && + !ArgumentChanged) { + // Mark any declarations we need as referenced. + // FIXME: instantiation-specific. + if (Constructor) + SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + if (OperatorNew) + SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorNew); + if (OperatorDelete) + SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete); + return SemaRef.Owned(E); + } + + QualType AllocType = AllocTypeInfo->getType(); + if (!ArraySize.get()) { + // If no array size was specified, but the new expression was + // instantiated with an array type (e.g., "new T" where T is + // instantiated with "int[4]"), extract the outer bound from the + // array type as our array size. We do this with constant and + // dependently-sized array types. + const ArrayType *ArrayT = SemaRef.Context.getAsArrayType(AllocType); + if (!ArrayT) { + // Do nothing + } else if (const ConstantArrayType *ConsArrayT + = dyn_cast<ConstantArrayType>(ArrayT)) { + ArraySize + = SemaRef.Owned(IntegerLiteral::Create(SemaRef.Context, + ConsArrayT->getSize(), + SemaRef.Context.getSizeType(), + /*FIXME:*/E->getLocStart())); + AllocType = ConsArrayT->getElementType(); + } else if (const DependentSizedArrayType *DepArrayT + = dyn_cast<DependentSizedArrayType>(ArrayT)) { + if (DepArrayT->getSizeExpr()) { + ArraySize = SemaRef.Owned(DepArrayT->getSizeExpr()); + AllocType = DepArrayT->getElementType(); + } + } + } + + return getDerived().RebuildCXXNewExpr(E->getLocStart(), + E->isGlobalNew(), + /*FIXME:*/E->getLocStart(), + move_arg(PlacementArgs), + /*FIXME:*/E->getLocStart(), + E->getTypeIdParens(), + AllocType, + AllocTypeInfo, + ArraySize.get(), + /*FIXME:*/E->getLocStart(), + move_arg(ConstructorArgs), + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { + ExprResult Operand = getDerived().TransformExpr(E->getArgument()); + if (Operand.isInvalid()) + return ExprError(); + + // Transform the delete operator, if known. + FunctionDecl *OperatorDelete = 0; + if (E->getOperatorDelete()) { + OperatorDelete = cast_or_null<FunctionDecl>( + getDerived().TransformDecl(E->getLocStart(), + E->getOperatorDelete())); + if (!OperatorDelete) + return ExprError(); + } + + if (!getDerived().AlwaysRebuild() && + Operand.get() == E->getArgument() && + OperatorDelete == E->getOperatorDelete()) { + // Mark any declarations we need as referenced. + // FIXME: instantiation-specific. + if (OperatorDelete) + SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete); + + if (!E->getArgument()->isTypeDependent()) { + QualType Destroyed = SemaRef.Context.getBaseElementType( + E->getDestroyedType()); + if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) { + CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl()); + SemaRef.MarkDeclarationReferenced(E->getLocStart(), + SemaRef.LookupDestructor(Record)); + } + } + + return SemaRef.Owned(E); + } + + return getDerived().RebuildCXXDeleteExpr(E->getLocStart(), + E->isGlobalDelete(), + E->isArrayForm(), + Operand.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( + CXXPseudoDestructorExpr *E) { + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + ParsedType ObjectTypePtr; + bool MayBePseudoDestructor = false; + Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(), + E->getOperatorLoc(), + E->isArrow()? tok::arrow : tok::period, + ObjectTypePtr, + MayBePseudoDestructor); + if (Base.isInvalid()) + return ExprError(); + + QualType ObjectType = ObjectTypePtr.get(); + NestedNameSpecifierLoc QualifierLoc = E->getQualifierLoc(); + if (QualifierLoc) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(QualifierLoc, ObjectType); + if (!QualifierLoc) + return ExprError(); + } + CXXScopeSpec SS; + SS.Adopt(QualifierLoc); + + PseudoDestructorTypeStorage Destroyed; + if (E->getDestroyedTypeInfo()) { + TypeSourceInfo *DestroyedTypeInfo + = getDerived().TransformTypeInObjectScope(E->getDestroyedTypeInfo(), + ObjectType, 0, SS); + if (!DestroyedTypeInfo) + return ExprError(); + Destroyed = DestroyedTypeInfo; + } else if (ObjectType->isDependentType()) { + // We aren't likely to be able to resolve the identifier down to a type + // now anyway, so just retain the identifier. + Destroyed = PseudoDestructorTypeStorage(E->getDestroyedTypeIdentifier(), + E->getDestroyedTypeLoc()); + } else { + // Look for a destructor known with the given name. + ParsedType T = SemaRef.getDestructorName(E->getTildeLoc(), + *E->getDestroyedTypeIdentifier(), + E->getDestroyedTypeLoc(), + /*Scope=*/0, + SS, ObjectTypePtr, + false); + if (!T) + return ExprError(); + + Destroyed + = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.GetTypeFromParser(T), + E->getDestroyedTypeLoc()); + } + + TypeSourceInfo *ScopeTypeInfo = 0; + if (E->getScopeTypeInfo()) { + ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo()); + if (!ScopeTypeInfo) + return ExprError(); + } + + return getDerived().RebuildCXXPseudoDestructorExpr(Base.get(), + E->getOperatorLoc(), + E->isArrow(), + SS, + ScopeTypeInfo, + E->getColonColonLoc(), + E->getTildeLoc(), + Destroyed); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformUnresolvedLookupExpr( + UnresolvedLookupExpr *Old) { + LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), + Sema::LookupOrdinaryName); + + // Transform all the decls. + for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(), + E = Old->decls_end(); I != E; ++I) { + NamedDecl *InstD = static_cast<NamedDecl*>( + getDerived().TransformDecl(Old->getNameLoc(), + *I)); + if (!InstD) { + // Silently ignore these if a UsingShadowDecl instantiated to nothing. + // This can happen because of dependent hiding. + if (isa<UsingShadowDecl>(*I)) + continue; + else + return ExprError(); + } + + // Expand using declarations. + if (isa<UsingDecl>(InstD)) { + UsingDecl *UD = cast<UsingDecl>(InstD); + for (UsingDecl::shadow_iterator I = UD->shadow_begin(), + E = UD->shadow_end(); I != E; ++I) + R.addDecl(*I); + continue; + } + + R.addDecl(InstD); + } + + // Resolve a kind, but don't do any further analysis. If it's + // ambiguous, the callee needs to deal with it. + R.resolveKind(); + + // Rebuild the nested-name qualifier, if present. + CXXScopeSpec SS; + if (Old->getQualifierLoc()) { + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc()); + if (!QualifierLoc) + return ExprError(); + + SS.Adopt(QualifierLoc); + } + + if (Old->getNamingClass()) { + CXXRecordDecl *NamingClass + = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl( + Old->getNameLoc(), + Old->getNamingClass())); + if (!NamingClass) + return ExprError(); + + R.setNamingClass(NamingClass); + } + + // If we have no template arguments, it's a normal declaration name. + if (!Old->hasExplicitTemplateArgs()) + return getDerived().RebuildDeclarationNameExpr(SS, R, Old->requiresADL()); + + // If we have template arguments, rebuild them, then rebuild the + // templateid expression. + TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); + if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(), + Old->getNumTemplateArgs(), + TransArgs)) + return ExprError(); + + return getDerived().RebuildTemplateIdExpr(SS, R, Old->requiresADL(), + TransArgs); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); + if (!T) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getQueriedTypeSourceInfo()) + return SemaRef.Owned(E); + + return getDerived().RebuildUnaryTypeTrait(E->getTrait(), + E->getLocStart(), + T, + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformBinaryTypeTraitExpr(BinaryTypeTraitExpr *E) { + TypeSourceInfo *LhsT = getDerived().TransformType(E->getLhsTypeSourceInfo()); + if (!LhsT) + return ExprError(); + + TypeSourceInfo *RhsT = getDerived().TransformType(E->getRhsTypeSourceInfo()); + if (!RhsT) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + LhsT == E->getLhsTypeSourceInfo() && RhsT == E->getRhsTypeSourceInfo()) + return SemaRef.Owned(E); + + return getDerived().RebuildBinaryTypeTrait(E->getTrait(), + E->getLocStart(), + LhsT, RhsT, + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getQueriedTypeSourceInfo()); + if (!T) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getQueriedTypeSourceInfo()) + return SemaRef.Owned(E); + + ExprResult SubExpr; + { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + SubExpr = getDerived().TransformExpr(E->getDimensionExpression()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getDimensionExpression()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildArrayTypeTrait(E->getTrait(), + E->getLocStart(), + T, + SubExpr.get(), + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformExpressionTraitExpr(ExpressionTraitExpr *E) { + ExprResult SubExpr; + { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + SubExpr = getDerived().TransformExpr(E->getQueriedExpression()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getQueriedExpression()) + return SemaRef.Owned(E); + } + + return getDerived().RebuildExpressionTrait( + E->getTrait(), E->getLocStart(), SubExpr.get(), E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( + DependentScopeDeclRefExpr *E) { + NestedNameSpecifierLoc QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); + if (!QualifierLoc) + return ExprError(); + + // TODO: If this is a conversion-function-id, verify that the + // destination type name (if present) resolves the same way after + // instantiation as it did in the local scope. + + DeclarationNameInfo NameInfo + = getDerived().TransformDeclarationNameInfo(E->getNameInfo()); + if (!NameInfo.getName()) + return ExprError(); + + if (!E->hasExplicitTemplateArgs()) { + if (!getDerived().AlwaysRebuild() && + QualifierLoc == E->getQualifierLoc() && + // Note: it is sufficient to compare the Name component of NameInfo: + // if name has not changed, DNLoc has not changed either. + NameInfo.getName() == E->getDeclName()) + return SemaRef.Owned(E); + + return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, + NameInfo, + /*TemplateArgs*/ 0); + } + + TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); + if (getDerived().TransformTemplateArguments(E->getTemplateArgs(), + E->getNumTemplateArgs(), + TransArgs)) + return ExprError(); + + return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, + NameInfo, + &TransArgs); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { + // CXXConstructExprs are always implicit, so when we have a + // 1-argument construction we just transform that argument. + if (E->getNumArgs() == 1 || + (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) + return getDerived().TransformExpr(E->getArg(0)); + + TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); + + QualType T = getDerived().TransformType(E->getType()); + if (T.isNull()) + return ExprError(); + + CXXConstructorDecl *Constructor + = cast_or_null<CXXConstructorDecl>( + getDerived().TransformDecl(E->getLocStart(), + E->getConstructor())); + if (!Constructor) + return ExprError(); + + bool ArgumentChanged = false; + ASTOwningVector<Expr*> Args(SemaRef); + if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, + &ArgumentChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getType() && + Constructor == E->getConstructor() && + !ArgumentChanged) { + // Mark the constructor as referenced. + // FIXME: Instantiation-specific + SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + return SemaRef.Owned(E); + } + + return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(), + Constructor, E->isElidable(), + move_arg(Args), + E->requiresZeroInitialization(), + E->getConstructionKind(), + E->getParenRange()); +} + +/// \brief Transform a C++ temporary-binding expression. +/// +/// Since CXXBindTemporaryExpr nodes are implicitly generated, we just +/// transform the subexpression and return that. +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { + return getDerived().TransformExpr(E->getSubExpr()); +} + +/// \brief Transform a C++ expression that contains cleanups that should +/// be run after the expression is evaluated. +/// +/// Since ExprWithCleanups nodes are implicitly generated, we +/// just transform the subexpression and return that. +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformExprWithCleanups(ExprWithCleanups *E) { + return getDerived().TransformExpr(E->getSubExpr()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( + CXXTemporaryObjectExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); + if (!T) + return ExprError(); + + CXXConstructorDecl *Constructor + = cast_or_null<CXXConstructorDecl>( + getDerived().TransformDecl(E->getLocStart(), + E->getConstructor())); + if (!Constructor) + return ExprError(); + + bool ArgumentChanged = false; + ASTOwningVector<Expr*> Args(SemaRef); + Args.reserve(E->getNumArgs()); + if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, + &ArgumentChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getTypeSourceInfo() && + Constructor == E->getConstructor() && + !ArgumentChanged) { + // FIXME: Instantiation-specific + SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor); + return SemaRef.MaybeBindToTemporary(E); + } + + return getDerived().RebuildCXXTemporaryObjectExpr(T, + /*FIXME:*/T->getTypeLoc().getEndLoc(), + move_arg(Args), + E->getLocEnd()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( + CXXUnresolvedConstructExpr *E) { + TypeSourceInfo *T = getDerived().TransformType(E->getTypeSourceInfo()); + if (!T) + return ExprError(); + + bool ArgumentChanged = false; + ASTOwningVector<Expr*> Args(SemaRef); + Args.reserve(E->arg_size()); + if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args, + &ArgumentChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + T == E->getTypeSourceInfo() && + !ArgumentChanged) + return SemaRef.Owned(E); + + // FIXME: we're faking the locations of the commas + return getDerived().RebuildCXXUnresolvedConstructExpr(T, + E->getLParenLoc(), + move_arg(Args), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXDependentScopeMemberExpr( + CXXDependentScopeMemberExpr *E) { + // Transform the base of the expression. + ExprResult Base((Expr*) 0); + Expr *OldBase; + QualType BaseType; + QualType ObjectType; + if (!E->isImplicitAccess()) { + OldBase = E->getBase(); + Base = getDerived().TransformExpr(OldBase); + if (Base.isInvalid()) + return ExprError(); + + // Start the member reference and compute the object's type. + ParsedType ObjectTy; + bool MayBePseudoDestructor = false; + Base = SemaRef.ActOnStartCXXMemberReference(0, Base.get(), + E->getOperatorLoc(), + E->isArrow()? tok::arrow : tok::period, + ObjectTy, + MayBePseudoDestructor); + if (Base.isInvalid()) + return ExprError(); + + ObjectType = ObjectTy.get(); + BaseType = ((Expr*) Base.get())->getType(); + } else { + OldBase = 0; + BaseType = getDerived().TransformType(E->getBaseType()); + ObjectType = BaseType->getAs<PointerType>()->getPointeeType(); + } + + // Transform the first part of the nested-name-specifier that qualifies + // the member name. + NamedDecl *FirstQualifierInScope + = getDerived().TransformFirstQualifierInScope( + E->getFirstQualifierFoundInScope(), + E->getQualifierLoc().getBeginLoc()); + + NestedNameSpecifierLoc QualifierLoc; + if (E->getQualifier()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc(), + ObjectType, + FirstQualifierInScope); + if (!QualifierLoc) + return ExprError(); + } + + // TODO: If this is a conversion-function-id, verify that the + // destination type name (if present) resolves the same way after + // instantiation as it did in the local scope. + + DeclarationNameInfo NameInfo + = getDerived().TransformDeclarationNameInfo(E->getMemberNameInfo()); + if (!NameInfo.getName()) + return ExprError(); + + if (!E->hasExplicitTemplateArgs()) { + // This is a reference to a member without an explicitly-specified + // template argument list. Optimize for this common case. + if (!getDerived().AlwaysRebuild() && + Base.get() == OldBase && + BaseType == E->getBaseType() && + QualifierLoc == E->getQualifierLoc() && + NameInfo.getName() == E->getMember() && + FirstQualifierInScope == E->getFirstQualifierFoundInScope()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(), + BaseType, + E->isArrow(), + E->getOperatorLoc(), + QualifierLoc, + FirstQualifierInScope, + NameInfo, + /*TemplateArgs*/ 0); + } + + TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); + if (getDerived().TransformTemplateArguments(E->getTemplateArgs(), + E->getNumTemplateArgs(), + TransArgs)) + return ExprError(); + + return getDerived().RebuildCXXDependentScopeMemberExpr(Base.get(), + BaseType, + E->isArrow(), + E->getOperatorLoc(), + QualifierLoc, + FirstQualifierInScope, + NameInfo, + &TransArgs); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) { + // Transform the base of the expression. + ExprResult Base((Expr*) 0); + QualType BaseType; + if (!Old->isImplicitAccess()) { + Base = getDerived().TransformExpr(Old->getBase()); + if (Base.isInvalid()) + return ExprError(); + BaseType = ((Expr*) Base.get())->getType(); + } else { + BaseType = getDerived().TransformType(Old->getBaseType()); + } + + NestedNameSpecifierLoc QualifierLoc; + if (Old->getQualifierLoc()) { + QualifierLoc + = getDerived().TransformNestedNameSpecifierLoc(Old->getQualifierLoc()); + if (!QualifierLoc) + return ExprError(); + } + + LookupResult R(SemaRef, Old->getMemberNameInfo(), + Sema::LookupOrdinaryName); + + // Transform all the decls. + for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(), + E = Old->decls_end(); I != E; ++I) { + NamedDecl *InstD = static_cast<NamedDecl*>( + getDerived().TransformDecl(Old->getMemberLoc(), + *I)); + if (!InstD) { + // Silently ignore these if a UsingShadowDecl instantiated to nothing. + // This can happen because of dependent hiding. + if (isa<UsingShadowDecl>(*I)) + continue; + else { + R.clear(); + return ExprError(); + } + } + + // Expand using declarations. + if (isa<UsingDecl>(InstD)) { + UsingDecl *UD = cast<UsingDecl>(InstD); + for (UsingDecl::shadow_iterator I = UD->shadow_begin(), + E = UD->shadow_end(); I != E; ++I) + R.addDecl(*I); + continue; + } + + R.addDecl(InstD); + } + + R.resolveKind(); + + // Determine the naming class. + if (Old->getNamingClass()) { + CXXRecordDecl *NamingClass + = cast_or_null<CXXRecordDecl>(getDerived().TransformDecl( + Old->getMemberLoc(), + Old->getNamingClass())); + if (!NamingClass) + return ExprError(); + + R.setNamingClass(NamingClass); + } + + TemplateArgumentListInfo TransArgs; + if (Old->hasExplicitTemplateArgs()) { + TransArgs.setLAngleLoc(Old->getLAngleLoc()); + TransArgs.setRAngleLoc(Old->getRAngleLoc()); + if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(), + Old->getNumTemplateArgs(), + TransArgs)) + return ExprError(); + } + + // FIXME: to do this check properly, we will need to preserve the + // first-qualifier-in-scope here, just in case we had a dependent + // base (and therefore couldn't do the check) and a + // nested-name-qualifier (and therefore could do the lookup). + NamedDecl *FirstQualifierInScope = 0; + + return getDerived().RebuildUnresolvedMemberExpr(Base.get(), + BaseType, + Old->getOperatorLoc(), + Old->isArrow(), + QualifierLoc, + FirstQualifierInScope, + R, + (Old->hasExplicitTemplateArgs() + ? &TransArgs : 0)); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformCXXNoexceptExpr(CXXNoexceptExpr *E) { + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + ExprResult SubExpr = getDerived().TransformExpr(E->getOperand()); + if (SubExpr.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && SubExpr.get() == E->getOperand()) + return SemaRef.Owned(E); + + return getDerived().RebuildCXXNoexceptExpr(E->getSourceRange(),SubExpr.get()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformPackExpansionExpr(PackExpansionExpr *E) { + ExprResult Pattern = getDerived().TransformExpr(E->getPattern()); + if (Pattern.isInvalid()) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && Pattern.get() == E->getPattern()) + return SemaRef.Owned(E); + + return getDerived().RebuildPackExpansion(Pattern.get(), E->getEllipsisLoc(), + E->getNumExpansions()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { + // If E is not value-dependent, then nothing will change when we transform it. + // Note: This is an instantiation-centric view. + if (!E->isValueDependent()) + return SemaRef.Owned(E); + + // Note: None of the implementations of TryExpandParameterPacks can ever + // produce a diagnostic when given only a single unexpanded parameter pack, + // so + UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc()); + bool ShouldExpand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions; + if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), + &Unexpanded, 1, + ShouldExpand, RetainExpansion, + NumExpansions)) + return ExprError(); + + if (!ShouldExpand || RetainExpansion) + return SemaRef.Owned(E); + + // We now know the length of the parameter pack, so build a new expression + // that stores that length. + return getDerived().RebuildSizeOfPackExpr(E->getOperatorLoc(), E->getPack(), + E->getPackLoc(), E->getRParenLoc(), + *NumExpansions); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformSubstNonTypeTemplateParmPackExpr( + SubstNonTypeTemplateParmPackExpr *E) { + // Default behavior is to do nothing with this transformation. + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) { + TypeSourceInfo *EncodedTypeInfo + = getDerived().TransformType(E->getEncodedTypeSourceInfo()); + if (!EncodedTypeInfo) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + EncodedTypeInfo == E->getEncodedTypeSourceInfo()) + return SemaRef.Owned(E); + + return getDerived().RebuildObjCEncodeExpr(E->getAtLoc(), + EncodedTypeInfo, + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { + // Transform arguments. + bool ArgChanged = false; + ASTOwningVector<Expr*> Args(SemaRef); + Args.reserve(E->getNumArgs()); + if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), false, Args, + &ArgChanged)) + return ExprError(); + + if (E->getReceiverKind() == ObjCMessageExpr::Class) { + // Class message: transform the receiver type. + TypeSourceInfo *ReceiverTypeInfo + = getDerived().TransformType(E->getClassReceiverTypeInfo()); + if (!ReceiverTypeInfo) + return ExprError(); + + // If nothing changed, just retain the existing message send. + if (!getDerived().AlwaysRebuild() && + ReceiverTypeInfo == E->getClassReceiverTypeInfo() && !ArgChanged) + return SemaRef.Owned(E); + + // Build a new class message send. + return getDerived().RebuildObjCMessageExpr(ReceiverTypeInfo, + E->getSelector(), + E->getSelectorLoc(), + E->getMethodDecl(), + E->getLeftLoc(), + move_arg(Args), + E->getRightLoc()); + } + + // Instance message: transform the receiver + assert(E->getReceiverKind() == ObjCMessageExpr::Instance && + "Only class and instance messages may be instantiated"); + ExprResult Receiver + = getDerived().TransformExpr(E->getInstanceReceiver()); + if (Receiver.isInvalid()) + return ExprError(); + + // If nothing changed, just retain the existing message send. + if (!getDerived().AlwaysRebuild() && + Receiver.get() == E->getInstanceReceiver() && !ArgChanged) + return SemaRef.Owned(E); + + // Build a new instance message send. + return getDerived().RebuildObjCMessageExpr(Receiver.get(), + E->getSelector(), + E->getSelectorLoc(), + E->getMethodDecl(), + E->getLeftLoc(), + move_arg(Args), + E->getRightLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) { + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) { + // Transform the base expression. + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + // We don't need to transform the ivar; it will never change. + + // If nothing changed, just retain the existing expression. + if (!getDerived().AlwaysRebuild() && + Base.get() == E->getBase()) + return SemaRef.Owned(E); + + return getDerived().RebuildObjCIvarRefExpr(Base.get(), E->getDecl(), + E->getLocation(), + E->isArrow(), E->isFreeIvar()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { + // 'super' and types never change. Property never changes. Just + // retain the existing expression. + if (!E->isObjectReceiver()) + return SemaRef.Owned(E); + + // Transform the base expression. + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + // We don't need to transform the property; it will never change. + + // If nothing changed, just retain the existing expression. + if (!getDerived().AlwaysRebuild() && + Base.get() == E->getBase()) + return SemaRef.Owned(E); + + if (E->isExplicitProperty()) + return getDerived().RebuildObjCPropertyRefExpr(Base.get(), + E->getExplicitProperty(), + E->getLocation()); + + return getDerived().RebuildObjCPropertyRefExpr(Base.get(), + E->getType(), + E->getImplicitPropertyGetter(), + E->getImplicitPropertySetter(), + E->getLocation()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) { + // Transform the base expression. + ExprResult Base = getDerived().TransformExpr(E->getBase()); + if (Base.isInvalid()) + return ExprError(); + + // If nothing changed, just retain the existing expression. + if (!getDerived().AlwaysRebuild() && + Base.get() == E->getBase()) + return SemaRef.Owned(E); + + return getDerived().RebuildObjCIsaExpr(Base.get(), E->getIsaMemberLoc(), + E->isArrow()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { + bool ArgumentChanged = false; + ASTOwningVector<Expr*> SubExprs(SemaRef); + SubExprs.reserve(E->getNumSubExprs()); + if (getDerived().TransformExprs(E->getSubExprs(), E->getNumSubExprs(), false, + SubExprs, &ArgumentChanged)) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + !ArgumentChanged) + return SemaRef.Owned(E); + + return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(), + move_arg(SubExprs), + E->getRParenLoc()); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { + BlockDecl *oldBlock = E->getBlockDecl(); + + SemaRef.ActOnBlockStart(E->getCaretLocation(), /*Scope=*/0); + BlockScopeInfo *blockScope = SemaRef.getCurBlock(); + + blockScope->TheDecl->setIsVariadic(oldBlock->isVariadic()); + // We built a new blockScopeInfo in call to ActOnBlockStart + // in above, CapturesCXXThis need be set here from the block + // expression. + blockScope->CapturesCXXThis = oldBlock->capturesCXXThis(); + + llvm::SmallVector<ParmVarDecl*, 4> params; + llvm::SmallVector<QualType, 4> paramTypes; + + // Parameter substitution. + if (getDerived().TransformFunctionTypeParams(E->getCaretLocation(), + oldBlock->param_begin(), + oldBlock->param_size(), + 0, paramTypes, ¶ms)) + return true; + + const FunctionType *exprFunctionType = E->getFunctionType(); + QualType exprResultType = exprFunctionType->getResultType(); + if (!exprResultType.isNull()) { + if (!exprResultType->isDependentType()) + blockScope->ReturnType = exprResultType; + else if (exprResultType != getSema().Context.DependentTy) + blockScope->ReturnType = getDerived().TransformType(exprResultType); + } + + // If the return type has not been determined yet, leave it as a dependent + // type; it'll get set when we process the body. + if (blockScope->ReturnType.isNull()) + blockScope->ReturnType = getSema().Context.DependentTy; + + // Don't allow returning a objc interface by value. + if (blockScope->ReturnType->isObjCObjectType()) { + getSema().Diag(E->getCaretLocation(), + diag::err_object_cannot_be_passed_returned_by_value) + << 0 << blockScope->ReturnType; + return ExprError(); + } + + QualType functionType = getDerived().RebuildFunctionProtoType( + blockScope->ReturnType, + paramTypes.data(), + paramTypes.size(), + oldBlock->isVariadic(), + 0, RQ_None, + exprFunctionType->getExtInfo()); + blockScope->FunctionType = functionType; + + // Set the parameters on the block decl. + if (!params.empty()) + blockScope->TheDecl->setParams(params.data(), params.size()); + + // If the return type wasn't explicitly set, it will have been marked as a + // dependent type (DependentTy); clear out the return type setting so + // we will deduce the return type when type-checking the block's body. + if (blockScope->ReturnType == getSema().Context.DependentTy) + blockScope->ReturnType = QualType(); + + // Transform the body + StmtResult body = getDerived().TransformStmt(E->getBody()); + if (body.isInvalid()) + return ExprError(); + +#ifndef NDEBUG + // In builds with assertions, make sure that we captured everything we + // captured before. + if (!SemaRef.getDiagnostics().hasErrorOccurred()) { + for (BlockDecl::capture_iterator i = oldBlock->capture_begin(), + e = oldBlock->capture_end(); i != e; ++i) { + VarDecl *oldCapture = i->getVariable(); + + // Ignore parameter packs. + if (isa<ParmVarDecl>(oldCapture) && + cast<ParmVarDecl>(oldCapture)->isParameterPack()) + continue; + + VarDecl *newCapture = + cast<VarDecl>(getDerived().TransformDecl(E->getCaretLocation(), + oldCapture)); + assert(blockScope->CaptureMap.count(newCapture)); + } + } +#endif + + return SemaRef.ActOnBlockStmtExpr(E->getCaretLocation(), body.get(), + /*Scope=*/0); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { + ValueDecl *ND + = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(), + E->getDecl())); + if (!ND) + return ExprError(); + + if (!getDerived().AlwaysRebuild() && + ND == E->getDecl()) { + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); + + return SemaRef.Owned(E); + } + + DeclarationNameInfo NameInfo(E->getDecl()->getDeclName(), E->getLocation()); + return getDerived().RebuildDeclRefExpr(NestedNameSpecifierLoc(), + ND, NameInfo, 0); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformAsTypeExpr(AsTypeExpr *E) { + assert(false && "Cannot transform asType expressions yet"); + return SemaRef.Owned(E); +} + +//===----------------------------------------------------------------------===// +// Type reconstruction +//===----------------------------------------------------------------------===// + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType, + SourceLocation Star) { + return SemaRef.BuildPointerType(PointeeType, Star, + getDerived().getBaseEntity()); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType, + SourceLocation Star) { + return SemaRef.BuildBlockPointerType(PointeeType, Star, + getDerived().getBaseEntity()); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType, + bool WrittenAsLValue, + SourceLocation Sigil) { + return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, + Sigil, getDerived().getBaseEntity()); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, + QualType ClassType, + SourceLocation Sigil) { + return SemaRef.BuildMemberPointerType(PointeeType, ClassType, + Sigil, getDerived().getBaseEntity()); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + const llvm::APInt *Size, + Expr *SizeExpr, + unsigned IndexTypeQuals, + SourceRange BracketsRange) { + if (SizeExpr || !Size) + return SemaRef.BuildArrayType(ElementType, SizeMod, SizeExpr, + IndexTypeQuals, BracketsRange, + getDerived().getBaseEntity()); + + QualType Types[] = { + SemaRef.Context.UnsignedCharTy, SemaRef.Context.UnsignedShortTy, + SemaRef.Context.UnsignedIntTy, SemaRef.Context.UnsignedLongTy, + SemaRef.Context.UnsignedLongLongTy, SemaRef.Context.UnsignedInt128Ty + }; + const unsigned NumTypes = sizeof(Types) / sizeof(QualType); + QualType SizeType; + for (unsigned I = 0; I != NumTypes; ++I) + if (Size->getBitWidth() == SemaRef.Context.getIntWidth(Types[I])) { + SizeType = Types[I]; + break; + } + + IntegerLiteral ArraySize(SemaRef.Context, *Size, SizeType, + /*FIXME*/BracketsRange.getBegin()); + return SemaRef.BuildArrayType(ElementType, SizeMod, &ArraySize, + IndexTypeQuals, BracketsRange, + getDerived().getBaseEntity()); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + const llvm::APInt &Size, + unsigned IndexTypeQuals, + SourceRange BracketsRange) { + return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0, + IndexTypeQuals, BracketsRange); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + unsigned IndexTypeQuals, + SourceRange BracketsRange) { + return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0, + IndexTypeQuals, BracketsRange); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildVariableArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + Expr *SizeExpr, + unsigned IndexTypeQuals, + SourceRange BracketsRange) { + return getDerived().RebuildArrayType(ElementType, SizeMod, 0, + SizeExpr, + IndexTypeQuals, BracketsRange); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType, + ArrayType::ArraySizeModifier SizeMod, + Expr *SizeExpr, + unsigned IndexTypeQuals, + SourceRange BracketsRange) { + return getDerived().RebuildArrayType(ElementType, SizeMod, 0, + SizeExpr, + IndexTypeQuals, BracketsRange); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType, + unsigned NumElements, + VectorType::VectorKind VecKind) { + // FIXME: semantic checking! + return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType, + unsigned NumElements, + SourceLocation AttributeLoc) { + llvm::APInt numElements(SemaRef.Context.getIntWidth(SemaRef.Context.IntTy), + NumElements, true); + IntegerLiteral *VectorSize + = IntegerLiteral::Create(SemaRef.Context, numElements, SemaRef.Context.IntTy, + AttributeLoc); + return SemaRef.BuildExtVectorType(ElementType, VectorSize, AttributeLoc); +} + +template<typename Derived> +QualType +TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType, + Expr *SizeExpr, + SourceLocation AttributeLoc) { + return SemaRef.BuildExtVectorType(ElementType, SizeExpr, AttributeLoc); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T, + QualType *ParamTypes, + unsigned NumParamTypes, + bool Variadic, + unsigned Quals, + RefQualifierKind RefQualifier, + const FunctionType::ExtInfo &Info) { + return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic, + Quals, RefQualifier, + getDerived().getBaseLocation(), + getDerived().getBaseEntity(), + Info); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) { + return SemaRef.Context.getFunctionNoProtoType(T); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) { + assert(D && "no decl found"); + if (D->isInvalidDecl()) return QualType(); + + // FIXME: Doesn't account for ObjCInterfaceDecl! + TypeDecl *Ty; + if (isa<UsingDecl>(D)) { + UsingDecl *Using = cast<UsingDecl>(D); + assert(Using->isTypeName() && + "UnresolvedUsingTypenameDecl transformed to non-typename using"); + + // A valid resolved using typename decl points to exactly one type decl. + assert(++Using->shadow_begin() == Using->shadow_end()); + Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl()); + + } else { + assert(isa<UnresolvedUsingTypenameDecl>(D) && + "UnresolvedUsingTypenameDecl transformed to non-using decl"); + Ty = cast<UnresolvedUsingTypenameDecl>(D); + } + + return SemaRef.Context.getTypeDeclType(Ty); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildTypeOfExprType(Expr *E, + SourceLocation Loc) { + return SemaRef.BuildTypeofExprType(E, Loc); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildTypeOfType(QualType Underlying) { + return SemaRef.Context.getTypeOfType(Underlying); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildDecltypeType(Expr *E, + SourceLocation Loc) { + return SemaRef.BuildDecltypeType(E, Loc); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildUnaryTransformType(QualType BaseType, + UnaryTransformType::UTTKind UKind, + SourceLocation Loc) { + return SemaRef.BuildUnaryTransformType(BaseType, UKind, Loc); +} + +template<typename Derived> +QualType TreeTransform<Derived>::RebuildTemplateSpecializationType( + TemplateName Template, + SourceLocation TemplateNameLoc, + TemplateArgumentListInfo &TemplateArgs) { + return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, TemplateArgs); +} + +template<typename Derived> +TemplateName +TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, + bool TemplateKW, + TemplateDecl *Template) { + return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW, + Template); +} + +template<typename Derived> +TemplateName +TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, + const IdentifierInfo &Name, + SourceLocation NameLoc, + QualType ObjectType, + NamedDecl *FirstQualifierInScope) { + UnqualifiedId TemplateName; + TemplateName.setIdentifier(&Name, NameLoc); + Sema::TemplateTy Template; + getSema().ActOnDependentTemplateName(/*Scope=*/0, + /*FIXME:*/SourceLocation(), + SS, + TemplateName, + ParsedType::make(ObjectType), + /*EnteringContext=*/false, + Template); + return Template.get(); +} + +template<typename Derived> +TemplateName +TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS, + OverloadedOperatorKind Operator, + SourceLocation NameLoc, + QualType ObjectType) { + UnqualifiedId Name; + // FIXME: Bogus location information. + SourceLocation SymbolLocations[3] = { NameLoc, NameLoc, NameLoc }; + Name.setOperatorFunctionId(NameLoc, Operator, SymbolLocations); + Sema::TemplateTy Template; + getSema().ActOnDependentTemplateName(/*Scope=*/0, + /*FIXME:*/SourceLocation(), + SS, + Name, + ParsedType::make(ObjectType), + /*EnteringContext=*/false, + Template); + return Template.template getAsVal<TemplateName>(); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr *OrigCallee, + Expr *First, + Expr *Second) { + Expr *Callee = OrigCallee->IgnoreParenCasts(); + bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus); + + // Determine whether this should be a builtin operation. + if (Op == OO_Subscript) { + if (!First->getType()->isOverloadableType() && + !Second->getType()->isOverloadableType()) + return getSema().CreateBuiltinArraySubscriptExpr(First, + Callee->getLocStart(), + Second, OpLoc); + } else if (Op == OO_Arrow) { + // -> is never a builtin operation. + return SemaRef.BuildOverloadedArrowExpr(0, First, OpLoc); + } else if (Second == 0 || isPostIncDec) { + if (!First->getType()->isOverloadableType()) { + // The argument is not of overloadable type, so try to create a + // built-in unary operation. + UnaryOperatorKind Opc + = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); + + return getSema().CreateBuiltinUnaryOp(OpLoc, Opc, First); + } + } else { + if (!First->getType()->isOverloadableType() && + !Second->getType()->isOverloadableType()) { + // Neither of the arguments is an overloadable type, so try to + // create a built-in binary operation. + BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); + ExprResult Result + = SemaRef.CreateBuiltinBinOp(OpLoc, Opc, First, Second); + if (Result.isInvalid()) + return ExprError(); + + return move(Result); + } + } + + // Compute the transformed set of functions (and function templates) to be + // used during overload resolution. + UnresolvedSet<16> Functions; + + if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Callee)) { + assert(ULE->requiresADL()); + + // FIXME: Do we have to check + // IsAcceptableNonMemberOperatorCandidate for each of these? + Functions.append(ULE->decls_begin(), ULE->decls_end()); + } else { + Functions.addDecl(cast<DeclRefExpr>(Callee)->getDecl()); + } + + // Add any functions found via argument-dependent lookup. + Expr *Args[2] = { First, Second }; + unsigned NumArgs = 1 + (Second != 0); + + // Create the overloaded operator invocation for unary operators. + if (NumArgs == 1 || isPostIncDec) { + UnaryOperatorKind Opc + = UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); + return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, First); + } + + if (Op == OO_Subscript) + return SemaRef.CreateOverloadedArraySubscriptExpr(Callee->getLocStart(), + OpLoc, + First, + Second); + + // Create the overloaded operator invocation for binary operators. + BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); + ExprResult Result + = SemaRef.CreateOverloadedBinOp(OpLoc, Opc, Functions, Args[0], Args[1]); + if (Result.isInvalid()) + return ExprError(); + + return move(Result); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, + SourceLocation OperatorLoc, + bool isArrow, + CXXScopeSpec &SS, + TypeSourceInfo *ScopeType, + SourceLocation CCLoc, + SourceLocation TildeLoc, + PseudoDestructorTypeStorage Destroyed) { + QualType BaseType = Base->getType(); + if (Base->isTypeDependent() || Destroyed.getIdentifier() || + (!isArrow && !BaseType->getAs<RecordType>()) || + (isArrow && BaseType->getAs<PointerType>() && + !BaseType->getAs<PointerType>()->getPointeeType() + ->template getAs<RecordType>())){ + // This pseudo-destructor expression is still a pseudo-destructor. + return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc, + isArrow? tok::arrow : tok::period, + SS, ScopeType, CCLoc, TildeLoc, + Destroyed, + /*FIXME?*/true); + } + + TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo(); + DeclarationName Name(SemaRef.Context.DeclarationNames.getCXXDestructorName( + SemaRef.Context.getCanonicalType(DestroyedType->getType()))); + DeclarationNameInfo NameInfo(Name, Destroyed.getLocation()); + NameInfo.setNamedTypeInfo(DestroyedType); + + // FIXME: the ScopeType should be tacked onto SS. + + return getSema().BuildMemberReferenceExpr(Base, BaseType, + OperatorLoc, isArrow, + SS, /*FIXME: FirstQualifier*/ 0, + NameInfo, + /*TemplateArgs*/ 0); +} + +} // end namespace clang + +#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H diff --git a/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h new file mode 100644 index 0000000..3570737 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h @@ -0,0 +1,192 @@ +//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines TypeLocBuilder, a class for building TypeLocs +// bottom-up. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H +#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H + +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/ASTContext.h" + +namespace clang { + +class TypeLocBuilder { + enum { InlineCapacity = 8 * sizeof(SourceLocation) }; + + /// The underlying location-data buffer. Data grows from the end + /// of the buffer backwards. + char *Buffer; + + /// The capacity of the current buffer. + size_t Capacity; + + /// The index of the first occupied byte in the buffer. + size_t Index; + +#ifndef NDEBUG + /// The last type pushed on this builder. + QualType LastTy; +#endif + + /// The inline buffer. + char InlineBuffer[InlineCapacity]; + + public: + TypeLocBuilder() + : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {} + + ~TypeLocBuilder() { + if (Buffer != InlineBuffer) + delete[] Buffer; + } + + /// Ensures that this buffer has at least as much capacity as described. + void reserve(size_t Requested) { + if (Requested > Capacity) + // For now, match the request exactly. + grow(Requested); + } + + /// Pushes a copy of the given TypeLoc onto this builder. The builder + /// must be empty for this to work. + void pushFullCopy(TypeLoc L) { + size_t Size = L.getFullDataSize(); + TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size); + memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); + } + + /// Pushes uninitialized space for the given type. The builder must + /// be empty. + TypeLoc pushFullUninitialized(QualType T) { + return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T)); + } + + /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs + /// previously retrieved from this builder. + TypeSpecTypeLoc pushTypeSpec(QualType T) { + size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; + return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); + } + + /// Resets this builder to the newly-initialized state. + void clear() { +#ifndef NDEBUG + LastTy = QualType(); +#endif + Index = Capacity; + } + + /// Pushes space for a new TypeLoc of the given type. Invalidates + /// any TypeLocs previously retrieved from this builder. + template <class TyLocType> TyLocType push(QualType T) { + size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); + return cast<TyLocType>(pushImpl(T, LocalSize)); + } + + /// Creates a TypeSourceInfo for the given type. + TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); + memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); + return DI; + } + + /// \brief Copies the type-location information to the given AST context and + /// returns a \c TypeLoc referring into the AST context. + TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + void *Mem = Context.Allocate(FullDataSize); + memcpy(Mem, &Buffer[Index], FullDataSize); + return TypeLoc(T, Mem); + } + +private: + TypeLoc pushImpl(QualType T, size_t LocalSize) { +#ifndef NDEBUG + QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); + assert(TLast == LastTy && + "mismatch between last type and new type's inner type"); + LastTy = T; +#endif + + // If we need to grow, grow by a factor of 2. + if (LocalSize > Index) { + size_t RequiredCapacity = Capacity + (LocalSize - Index); + size_t NewCapacity = Capacity * 2; + while (RequiredCapacity > NewCapacity) + NewCapacity *= 2; + grow(NewCapacity); + } + + Index -= LocalSize; + + return getTypeLoc(T); + } + + /// Grow to the given capacity. + void grow(size_t NewCapacity) { + assert(NewCapacity > Capacity); + + // Allocate the new buffer and copy the old data into it. + char *NewBuffer = new char[NewCapacity]; + unsigned NewIndex = Index + NewCapacity - Capacity; + memcpy(&NewBuffer[NewIndex], + &Buffer[Index], + Capacity - Index); + + if (Buffer != InlineBuffer) + delete[] Buffer; + + Buffer = NewBuffer; + Capacity = NewCapacity; + Index = NewIndex; + } + + TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) { +#ifndef NDEBUG + assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder"); + LastTy = T; +#endif + assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder"); + + reserve(Size); + Index -= Size; + + return getTypeLoc(T); + } + + + // This is private because, when we kill off TypeSourceInfo in favor + // of TypeLoc, we'll want an interface that creates a TypeLoc given + // an ASTContext, and we don't want people to think they can just + // use this as an equivalent. + TypeLoc getTypeLoc(QualType T) { +#ifndef NDEBUG + assert(LastTy == T && "type doesn't match last type pushed!"); +#endif + return TypeLoc(T, &Buffer[Index]); + } +}; + +} + +#endif |