diff options
Diffstat (limited to 'lib/Sema')
44 files changed, 9996 insertions, 5154 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 801a1b1..00d3c47 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -14,42 +14,43 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/AnalysisBasedWarnings.h" -#include "clang/Sema/SemaInternal.h" -#include "clang/Sema/ScopeInfo.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/SourceLocation.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/Lexer.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/DeclObjC.h" #include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/StmtVisitor.h" #include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Analysis/AnalysisContext.h" -#include "clang/Analysis/CFG.h" -#include "clang/Analysis/Analyses/ReachableCode.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" +#include "clang/Analysis/Analyses/ReachableCode.h" #include "clang/Analysis/Analyses/ThreadSafety.h" -#include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Analyses/UninitializedValues.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/CFGStmtMap.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include <algorithm> +#include <deque> #include <iterator> #include <vector> -#include <deque> using namespace clang; @@ -157,7 +158,7 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { CFGBlock::const_reverse_iterator ri = B.rbegin(), re = B.rend(); for ( ; ri != re ; ++ri) - if (isa<CFGStmt>(*ri)) + if (ri->getAs<CFGStmt>()) break; // No more CFGElements in the block? @@ -171,7 +172,7 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { continue; } - CFGStmt CS = cast<CFGStmt>(*ri); + CFGStmt CS = ri->castAs<CFGStmt>(); const Stmt *S = CS.getStmt(); if (isa<ReturnStmt>(S)) { HasLiveReturn = true; @@ -329,8 +330,7 @@ static void CheckFallThroughForBody(Sema &S, const Decl *D, const Stmt *Body, if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { ReturnsVoid = FD->getResultType()->isVoidType(); - HasNoReturn = FD->hasAttr<NoReturnAttr>() || - FD->getType()->getAs<FunctionType>()->getNoReturnAttr(); + HasNoReturn = FD->isNoReturn(); } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { ReturnsVoid = MD->getResultType()->isVoidType(); @@ -505,7 +505,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, StringRef Str; SourceRange Range; - // FixIts to suppress the diagnosic by removing the dead condition. + // FixIts to suppress the diagnostic by removing the dead condition. // For all binary terminators, branch 0 is taken if the condition is true, // and branch 1 is taken if the condition is false. int RemoveDiagKind = -1; @@ -703,7 +703,38 @@ namespace { return FallthroughStmts; } + void fillReachableBlocks(CFG *Cfg) { + assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); + std::deque<const CFGBlock *> BlockQueue; + + ReachableBlocks.insert(&Cfg->getEntry()); + BlockQueue.push_back(&Cfg->getEntry()); + // Mark all case blocks reachable to avoid problems with switching on + // constants, covered enums, etc. + // These blocks can contain fall-through annotations, and we don't want to + // issue a warn_fallthrough_attr_unreachable for them. + for (CFG::iterator I = Cfg->begin(), E = Cfg->end(); I != E; ++I) { + const CFGBlock *B = *I; + const Stmt *L = B->getLabel(); + if (L && isa<SwitchCase>(L) && ReachableBlocks.insert(B)) + BlockQueue.push_back(B); + } + + while (!BlockQueue.empty()) { + const CFGBlock *P = BlockQueue.front(); + BlockQueue.pop_front(); + for (CFGBlock::const_succ_iterator I = P->succ_begin(), + E = P->succ_end(); + I != E; ++I) { + if (*I && ReachableBlocks.insert(*I)) + BlockQueue.push_back(*I); + } + } + } + bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) { + assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); + int UnannotatedCnt = 0; AnnotatedCnt = 0; @@ -723,16 +754,21 @@ namespace { if (SW && SW->getSubStmt() == B.getLabel() && P->begin() == P->end()) continue; // Previous case label has no statements, good. - if (P->pred_begin() == P->pred_end()) { // The block is unreachable. - // This only catches trivially unreachable blocks. - for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end(); - ElIt != ElEnd; ++ElIt) { - if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){ + const LabelStmt *L = dyn_cast_or_null<LabelStmt>(P->getLabel()); + if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) + continue; // Case label is preceded with a normal label, good. + + if (!ReachableBlocks.count(P)) { + for (CFGBlock::const_reverse_iterator ElemIt = P->rbegin(), + ElemEnd = P->rend(); + ElemIt != ElemEnd; ++ElemIt) { + if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) { if (const AttributedStmt *AS = asFallThroughAttr(CS->getStmt())) { S.Diag(AS->getLocStart(), diag::warn_fallthrough_attr_unreachable); markFallthroughVisited(AS); ++AnnotatedCnt; + break; } // Don't care about other unreachable statements. } @@ -781,6 +817,10 @@ namespace { return true; } + // We don't want to traverse local type declarations. We analyze their + // methods separately. + bool TraverseDecl(Decl *D) { return true; } + private: static const AttributedStmt *asFallThroughAttr(const Stmt *S) { @@ -797,7 +837,7 @@ namespace { for (CFGBlock::const_reverse_iterator ElemIt = B.rbegin(), ElemEnd = B.rend(); ElemIt != ElemEnd; ++ElemIt) { - if (const CFGStmt *CS = ElemIt->getAs<CFGStmt>()) + if (Optional<CFGStmt> CS = ElemIt->getAs<CFGStmt>()) return CS->getStmt(); } // Workaround to detect a statement thrown out by CFGBuilder: @@ -813,6 +853,7 @@ namespace { bool FoundSwitchStatements; AttrStmts FallthroughStmts; Sema &S; + llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks; }; } @@ -827,7 +868,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, // // NOTE: This an intermediate solution. There are on-going discussions on // how to properly support this warning outside of C++11 with an annotation. - if (!AC.getASTContext().getLangOpts().CPlusPlus0x) + if (!AC.getASTContext().getLangOpts().CPlusPlus11) return; FallthroughMapper FM(S); @@ -844,16 +885,18 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, if (!Cfg) return; - int AnnotatedCnt; + FM.fillReachableBlocks(Cfg); for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) { - const CFGBlock &B = **I; - const Stmt *Label = B.getLabel(); + const CFGBlock *B = *I; + const Stmt *Label = B->getLabel(); if (!Label || !isa<SwitchCase>(Label)) continue; - if (!FM.checkFallThroughIntoBlock(B, AnnotatedCnt)) + int AnnotatedCnt; + + if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt)) continue; S.Diag(Label->getLocStart(), @@ -864,9 +907,14 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, SourceLocation L = Label->getLocStart(); if (L.isMacroID()) continue; - if (S.getLangOpts().CPlusPlus0x) { - const Stmt *Term = B.getTerminator(); - if (!(B.empty() && Term && isa<BreakStmt>(Term))) { + if (S.getLangOpts().CPlusPlus11) { + const Stmt *Term = B->getTerminator(); + // Skip empty cases. + while (B->empty() && !Term && B->succ_size() == 1) { + B = *B->succ_begin(); + Term = B->getTerminator(); + } + if (!(B->empty() && Term && isa<BreakStmt>(Term))) { Preprocessor &PP = S.getPreprocessor(); TokenValue Tokens[] = { tok::l_square, tok::l_square, PP.getIdentifierInfo("clang"), @@ -1106,7 +1154,11 @@ struct SLocSort { class UninitValsDiagReporter : public UninitVariablesHandler { Sema &S; typedef SmallVector<UninitUse, 2> UsesVec; - typedef llvm::DenseMap<const VarDecl *, std::pair<UsesVec*, bool> > UsesMap; + typedef std::pair<UsesVec*, bool> MappedType; + // Prefer using MapVector to DenseMap, so that iteration order will be + // the same as insertion order. This is needed to obtain a deterministic + // order of diagnostics when calling flushDiagnostics(). + typedef llvm::MapVector<const VarDecl *, MappedType> UsesMap; UsesMap *uses; public: @@ -1115,11 +1167,11 @@ public: flushDiagnostics(); } - std::pair<UsesVec*, bool> &getUses(const VarDecl *vd) { + MappedType &getUses(const VarDecl *vd) { if (!uses) uses = new UsesMap(); - UsesMap::mapped_type &V = (*uses)[vd]; + MappedType &V = (*uses)[vd]; UsesVec *&vec = V.first; if (!vec) vec = new UsesVec(); @@ -1138,12 +1190,10 @@ public: void flushDiagnostics() { if (!uses) return; - - // FIXME: This iteration order, and thus the resulting diagnostic order, - // is nondeterministic. + for (UsesMap::iterator i = uses->begin(), e = uses->end(); i != e; ++i) { const VarDecl *vd = i->first; - const UsesMap::mapped_type &V = i->second; + const MappedType &V = i->second; UsesVec *vec = V.first; bool hasSelfInit = V.second; @@ -1198,7 +1248,7 @@ private: //===----------------------------------------------------------------------===// namespace clang { namespace thread_safety { -typedef llvm::SmallVector<PartialDiagnosticAt, 1> OptionalNotes; +typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; typedef std::list<DelayedDiag> DiagList; @@ -1423,7 +1473,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (cast<DeclContext>(D)->isDependentContext()) return; - if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) { + if (Diags.hasUncompilableErrorOccurred() || Diags.hasFatalErrorOccurred()) { // Flush out any possibly unreachable diagnostics. flushDiagnostics(S, fscope); return; @@ -1544,6 +1594,10 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, SourceLocation FL = AC.getDecl()->getLocation(); SourceLocation FEL = AC.getDecl()->getLocEnd(); thread_safety::ThreadSafetyReporter Reporter(S, FL, FEL); + if (Diags.getDiagnosticLevel(diag::warn_thread_safety_beta,D->getLocStart()) + != DiagnosticsEngine::Ignored) + Reporter.setIssueBetaWarnings(true); + thread_safety::runThreadSafetyAnalysis(AC, Reporter); Reporter.emitDiagnostics(); } diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index 7c79879..e227d4e 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -15,8 +15,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/Basic/IdentifierTable.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" using namespace clang; size_t AttributeList::allocated_size() const { @@ -125,3 +125,14 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, return ::getAttrKind(Buf); } + +unsigned AttributeList::getAttributeSpellingListIndex() const { + // Both variables will be used in tablegen generated + // attribute spell list index matching code. + StringRef Name = AttrName->getName(); + StringRef Scope = ScopeName ? ScopeName->getName() : ""; + +#include "clang/Sema/AttrSpellingListIndex.inc" + +} + diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 7cfe3ae..e92f767 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -38,6 +38,7 @@ add_clang_library(clangSema SemaLambda.cpp SemaLookup.cpp SemaObjCProperty.cpp + SemaOpenMP.cpp SemaOverload.cpp SemaPseudoObject.cpp SemaStmt.cpp @@ -58,6 +59,7 @@ add_dependencies(clangSema ClangAttrList ClangAttrParsedAttrList ClangAttrParsedAttrKinds + ClangAttrSpellingListIndex ClangAttrTemplateInstantiate ClangCommentNodes ClangDeclNodes diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 0a23601..19be1cb 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -11,15 +11,15 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/CodeCompleteConsumer.h" -#include "clang/Sema/Scope.h" -#include "clang/Sema/Sema.h" +#include "clang-c/Index.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/SmallString.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -267,8 +267,8 @@ const char *CodeCompletionAllocator::CopyString(Twine String) { return CopyString(String.toStringRef(Data)); } -StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) { - NamedDecl *ND = dyn_cast<NamedDecl>(DC); +StringRef CodeCompletionTUInfo::getParentName(const DeclContext *DC) { + const NamedDecl *ND = dyn_cast<NamedDecl>(DC); if (!ND) return StringRef(); @@ -283,9 +283,9 @@ StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) { return StringRef(); // Find the interesting names. - llvm::SmallVector<DeclContext *, 2> Contexts; + SmallVector<const DeclContext *, 2> Contexts; while (DC && !DC->isFunctionOrMethod()) { - if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { + if (const NamedDecl *ND = dyn_cast<NamedDecl>(DC)) { if (ND->getIdentifier()) Contexts.push_back(DC); } @@ -294,7 +294,7 @@ StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) { } { - llvm::SmallString<128> S; + SmallString<128> S; llvm::raw_svector_ostream OS(S); bool First = true; for (unsigned I = Contexts.size(); I != 0; --I) { @@ -304,12 +304,12 @@ StringRef CodeCompletionTUInfo::getParentName(DeclContext *DC) { OS << "::"; } - DeclContext *CurDC = Contexts[I-1]; - if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) + const DeclContext *CurDC = Contexts[I-1]; + if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC)) CurDC = CatImpl->getCategoryDecl(); - if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { - ObjCInterfaceDecl *Interface = Cat->getClassInterface(); + if (const ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) { + const ObjCInterfaceDecl *Interface = Cat->getClassInterface(); if (!Interface) { // Assign an empty StringRef but with non-null data to distinguish // between empty because we didn't process the DeclContext yet. @@ -377,7 +377,7 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, Chunks.push_back(Chunk(CK, Text)); } -void CodeCompletionBuilder::addParentContext(DeclContext *DC) { +void CodeCompletionBuilder::addParentContext(const DeclContext *DC) { if (DC->isTranslationUnit()) { return; } @@ -385,7 +385,7 @@ void CodeCompletionBuilder::addParentContext(DeclContext *DC) { if (DC->isFunctionOrMethod()) return; - NamedDecl *ND = dyn_cast<NamedDecl>(DC); + const NamedDecl *ND = dyn_cast<NamedDecl>(DC); if (!ND) return; @@ -396,33 +396,6 @@ void CodeCompletionBuilder::addBriefComment(StringRef Comment) { BriefComment = Allocator.CopyString(Comment); } -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 //===----------------------------------------------------------------------===// @@ -526,7 +499,7 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef, } /// \brief Retrieve the effective availability of the given declaration. -static AvailabilityResult getDeclAvailability(Decl *D) { +static AvailabilityResult getDeclAvailability(const Decl *D) { AvailabilityResult AR = D->getAvailability(); if (isa<EnumConstantDecl>(D)) AR = std::max(AR, cast<Decl>(D->getDeclContext())->getAvailability()); @@ -559,7 +532,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) { break; } - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration)) + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration)) if (Function->isDeleted()) Availability = CXAvailability_NotAvailable; diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index b3066eb..e1d55db 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -11,18 +11,18 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/LocInfoType.h" -#include "clang/Sema/ParsedTemplate.h" -#include "clang/Sema/SemaDiagnostic.h" -#include "clang/Sema/Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TypeLoc.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/LangOptions.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency! +#include "clang/Sema/LocInfoType.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include <cstring> @@ -169,6 +169,9 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, TypeResult TrailingReturnType) { + assert(!(TypeQuals & DeclSpec::TQ_atomic) && + "function cannot have _Atomic qualifier"); + DeclaratorChunk I; I.Kind = Function; I.Loc = LocalRangeBegin; @@ -280,6 +283,14 @@ bool Declarator::isDeclarationOfFunction() const { case TST_unspecified: case TST_void: case TST_wchar: + case TST_image1d_t: + case TST_image1d_array_t: + case TST_image1d_buffer_t: + case TST_image2d_t: + case TST_image2d_array_t: + case TST_image3d_t: + case TST_sampler_t: + case TST_event_t: return false; case TST_decltype: @@ -323,7 +334,8 @@ unsigned DeclSpec::getParsedSpecifiers() const { if (hasTypeSpecifier()) Res |= PQ_TypeSpecifier; - if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified) + if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified || + FS_noreturn_specified) Res |= PQ_FunctionSpecifier; return Res; } @@ -414,6 +426,14 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_underlyingType: return "__underlying_type"; case DeclSpec::TST_unknown_anytype: return "__unknown_anytype"; case DeclSpec::TST_atomic: return "_Atomic"; + case DeclSpec::TST_image1d_t: return "image1d_t"; + case DeclSpec::TST_image1d_array_t: return "image1d_array_t"; + case DeclSpec::TST_image1d_buffer_t: return "image1d_buffer_t"; + case DeclSpec::TST_image2d_t: return "image2d_t"; + case DeclSpec::TST_image2d_array_t: return "image2d_array_t"; + case DeclSpec::TST_image3d_t: return "image3d_t"; + case DeclSpec::TST_sampler_t: return "sampler_t"; + case DeclSpec::TST_event_t: return "event_t"; case DeclSpec::TST_error: return "(error)"; } llvm_unreachable("Unknown typespec!"); @@ -425,6 +445,7 @@ const char *DeclSpec::getSpecifierName(TQ T) { case DeclSpec::TQ_const: return "const"; case DeclSpec::TQ_restrict: return "restrict"; case DeclSpec::TQ_volatile: return "volatile"; + case DeclSpec::TQ_atomic: return "_Atomic"; } llvm_unreachable("Unknown typespec!"); } @@ -693,38 +714,44 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, TypeQualifiers |= T; switch (T) { - default: llvm_unreachable("Unknown type qualifier!"); - case TQ_const: TQ_constLoc = Loc; break; - case TQ_restrict: TQ_restrictLoc = Loc; break; - case TQ_volatile: TQ_volatileLoc = Loc; break; + case TQ_unspecified: break; + case TQ_const: TQ_constLoc = Loc; return false; + case TQ_restrict: TQ_restrictLoc = Loc; return false; + case TQ_volatile: TQ_volatileLoc = Loc; return false; + case TQ_atomic: TQ_atomicLoc = Loc; return false; } - return false; + + llvm_unreachable("Unknown type qualifier!"); } -bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID) { +bool DeclSpec::setFunctionSpecInline(SourceLocation Loc) { // 'inline inline' is ok. FS_inline_specified = true; FS_inlineLoc = Loc; return false; } -bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID) { +bool DeclSpec::setFunctionSpecVirtual(SourceLocation Loc) { // 'virtual virtual' is ok. FS_virtual_specified = true; FS_virtualLoc = Loc; return false; } -bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID) { +bool DeclSpec::setFunctionSpecExplicit(SourceLocation Loc) { // 'explicit explicit' is ok. FS_explicit_specified = true; FS_explicitLoc = Loc; return false; } +bool DeclSpec::setFunctionSpecNoreturn(SourceLocation Loc) { + // '_Noreturn _Noreturn' is ok. + FS_noreturn_specified = true; + FS_noreturnLoc = Loc; + return false; +} + bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { if (Friend_specified) { @@ -763,9 +790,10 @@ void DeclSpec::setProtocolQualifiers(Decl * const *Protos, SourceLocation *ProtoLocs, SourceLocation LAngleLoc) { if (NP == 0) return; - ProtocolQualifiers = new Decl*[NP]; + Decl **ProtoQuals = new Decl*[NP]; + memcpy(ProtoQuals, Protos, sizeof(Decl*)*NP); + ProtocolQualifiers = ProtoQuals; ProtocolLocs = new SourceLocation[NP]; - memcpy((void*)ProtocolQualifiers, Protos, sizeof(Decl*)*NP); memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP); NumProtocolQualifiers = NP; ProtocolLAngleLoc = LAngleLoc; @@ -787,15 +815,6 @@ void DeclSpec::SaveWrittenBuiltinSpecs() { } } -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, @@ -803,7 +822,6 @@ void DeclSpec::SaveStorageSpecifierAsWritten() { void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) { // Before possibly changing their values, save specs as written. SaveWrittenBuiltinSpecs(); - SaveStorageSpecifierAsWritten(); // Check the type specifier components first. @@ -913,15 +931,15 @@ void DeclSpec::Finish(DiagnosticsEngine &D, Preprocessor &PP) { if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().MicrosoftExt && TypeSpecType == TST_unspecified && StorageClassSpec == SCS_auto) { TypeSpecType = TST_auto; - StorageClassSpec = StorageClassSpecAsWritten = SCS_unspecified; + StorageClassSpec = SCS_unspecified; TSTLoc = TSTNameLoc = StorageClassSpecLoc; StorageClassSpecLoc = SourceLocation(); } // Diagnose if we've recovered from an ill-formed 'auto' storage class // specifier in a pre-C++0x dialect of C++. - if (!PP.getLangOpts().CPlusPlus0x && TypeSpecType == TST_auto) + if (!PP.getLangOpts().CPlusPlus11 && TypeSpecType == TST_auto) Diag(D, TSTLoc, diag::ext_auto_type_specifier); - if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus0x && + if (PP.getLangOpts().CPlusPlus && !PP.getLangOpts().CPlusPlus11 && StorageClassSpec == SCS_auto) Diag(D, StorageClassSpecLoc, diag::warn_auto_storage_class) << FixItHint::CreateRemoval(StorageClassSpecLoc); diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 7d55304..d44c1fb 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -13,12 +13,11 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/IdentifierResolver.h" -#include "clang/Sema/Scope.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclObjC.h" #include "clang/Basic/LangOptions.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Scope.h" using namespace clang; @@ -108,8 +107,7 @@ IdentifierResolver::~IdentifierResolver() { /// 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 IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, Scope *S, bool ExplicitInstantiationOrSpecialization) const { Ctx = Ctx->getRedeclContext(); @@ -304,6 +302,14 @@ static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) { // If the declarations are redeclarations of each other, keep the newest one. if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) { + // If either of these is the most recent declaration, use it. + Decl *MostRecent = Existing->getMostRecentDecl(); + if (Existing == MostRecent) + return DMK_Ignore; + + if (New == MostRecent) + return DMK_Replace; + // If the existing declaration is somewhere in the previous declaration // chain of the new declaration, then prefer the new declaration. for (Decl::redecl_iterator RD = New->redecls_begin(), diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index e2ec1cc..5f92cff 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -16,8 +16,8 @@ #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 "clang/AST/StmtObjC.h" #include "llvm/ADT/BitVector.h" using namespace clang; @@ -511,8 +511,14 @@ void JumpScopeChecker::VerifyJumps() { 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, 0, + SourceLocation Loc; + if (CaseStmt *CS = dyn_cast<CaseStmt>(SC)) + Loc = CS->getLocStart(); + else if (DefaultStmt *DS = dyn_cast<DefaultStmt>(SC)) + Loc = DS->getLocStart(); + else + Loc = SC->getLocStart(); + CheckJump(SS, SC, Loc, diag::err_switch_into_protected_scope, 0, diag::warn_cxx98_compat_switch_into_protected_scope); } } @@ -668,7 +674,7 @@ static bool IsMicrosoftJumpWarning(unsigned JumpDiag, unsigned InDiagNote) { /// Return true if a particular note should be downgraded to a compatibility /// warning in C++11 mode. static bool IsCXX98CompatWarning(Sema &S, unsigned InDiagNote) { - return S.getLangOpts().CPlusPlus0x && + return S.getLangOpts().CPlusPlus11 && InDiagNote == diag::note_protected_by_variable_non_pod; } diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp index f930fb3..d85624b 100644 --- a/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/lib/Sema/MultiplexExternalSemaSource.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/MultiplexExternalSemaSource.h" - #include "clang/AST/DeclContextInternals.h" #include "clang/Sema/Lookup.h" @@ -82,19 +81,12 @@ CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers( return 0; } -DeclContextLookupResult MultiplexExternalSemaSource:: +bool MultiplexExternalSemaSource:: FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) { - StoredDeclsList DeclsFound; - DeclContextLookupResult lookup; - for(size_t i = 0; i < Sources.size(); ++i) { - lookup = Sources[i]->FindExternalVisibleDeclsByName(DC, Name); - while(lookup.first != lookup.second) { - if (!DeclsFound.HandleRedeclaration(*lookup.first)) - DeclsFound.AddSubsequentDecl(*lookup.first); - lookup.first++; - } - } - return DeclsFound.getLookupResult(); + bool AnyDeclsFound = false; + for (size_t i = 0; i < Sources.size(); ++i) + AnyDeclsFound |= Sources[i]->FindExternalVisibleDeclsByName(DC, Name); + return AnyDeclsFound; } void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC){ @@ -201,6 +193,12 @@ void MultiplexExternalSemaSource::ReadKnownNamespaces( for(size_t i = 0; i < Sources.size(); ++i) Sources[i]->ReadKnownNamespaces(Namespaces); } + +void MultiplexExternalSemaSource::ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined){ + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadUndefinedButUsed(Undefined); +} bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){ for(size_t i = 0; i < Sources.size(); ++i) @@ -239,10 +237,10 @@ void MultiplexExternalSemaSource::ReadDynamicClasses( Sources[i]->ReadDynamicClasses(Decls); } -void MultiplexExternalSemaSource::ReadLocallyScopedExternalDecls( +void MultiplexExternalSemaSource::ReadLocallyScopedExternCDecls( SmallVectorImpl<NamedDecl*> &Decls) { for(size_t i = 0; i < Sources.size(); ++i) - Sources[i]->ReadLocallyScopedExternalDecls(Decls); + Sources[i]->ReadLocallyScopedExternCDecls(Decls); } void MultiplexExternalSemaSource::ReadReferencedSelectors( diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 13a33b7..6bab9e8 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -13,21 +13,7 @@ //===----------------------------------------------------------------------===// #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 "llvm/Support/CrashRecoveryContext.h" -#include "clang/Sema/CXXFieldCollector.h" -#include "clang/Sema/TemplateDeduction.h" -#include "clang/Sema/ExternalSemaSource.h" -#include "clang/Sema/MultiplexExternalSemaSource.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" @@ -36,11 +22,25 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/HeaderSearch.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/MultiplexExternalSemaSource.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/Sema/TemplateDeduction.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/CrashRecoveryContext.h" using namespace clang; using namespace sema; @@ -49,13 +49,14 @@ PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context, PrintingPolicy Policy = Context.getPrintingPolicy(); Policy.Bool = Context.getLangOpts().Bool; if (!Policy.Bool) { - if (MacroInfo *BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) { - Policy.Bool = BoolMacro->isObjectLike() && + if (const MacroInfo * + BoolMacro = PP.getMacroInfo(&Context.Idents.get("bool"))) { + Policy.Bool = BoolMacro->isObjectLike() && BoolMacro->getNumTokens() == 1 && BoolMacro->getReplacementToken(0).is(tok::kw__Bool); } } - + return Policy; } @@ -69,7 +70,7 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) - : TheTargetAttributesSema(0), ExternalSource(0), + : TheTargetAttributesSema(0), ExternalSource(0), isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), @@ -83,16 +84,16 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, NSStringDecl(0), StringWithUTF8StringMethod(0), NSArrayDecl(0), ArrayWithObjectsMethod(0), NSDictionaryDecl(0), DictionaryWithObjectsMethod(0), - GlobalNewDeleteDeclared(false), + GlobalNewDeleteDeclared(false), TUKind(TUKind), NumSFINAEErrors(0), InFunctionDeclarator(0), AccessCheckingSFINAE(false), InNonInstantiationSFINAEContext(false), NonInstantiationEntries(0), ArgumentPackSubstitutionIndex(-1), CurrentInstantiationScope(0), TyposCorrected(0), - AnalysisWarnings(*this) + AnalysisWarnings(*this), Ident_super(0) { TUScope = 0; - + LoadedExternalKnownNamespaces = false; for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I) NSNumberLiteralMethods[I] = 0; @@ -104,7 +105,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, FieldCollector.reset(new CXXFieldCollector()); // Tell diagnostics how to render things from the AST library. - PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, + PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context); ExprEvalContexts.push_back( @@ -117,18 +118,18 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, 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); // Initialize predefined 128-bit integer types, if needed. - if (PP.getTargetInfo().getPointerWidth(0) >= 64) { + if (PP.getTargetInfo().hasInt128Type()) { // If either of the 128-bit integer types are unavailable to name lookup, // define them now. DeclarationName Int128 = &Context.Idents.get("__int128_t"); @@ -139,7 +140,7 @@ void Sema::Initialize() { if (IdResolver.begin(UInt128) == IdResolver.end()) PushOnScopeChains(Context.getUInt128Decl(), TUScope); } - + // Initialize predefined Objective-C types: if (PP.getLangOpts().ObjC1) { @@ -154,7 +155,7 @@ void Sema::Initialize() { DeclarationName Id = &Context.Idents.get("id"); if (IdResolver.begin(Id) == IdResolver.end()) PushOnScopeChains(Context.getObjCIdDecl(), TUScope); - + // Create the built-in typedef for 'Class'. DeclarationName Class = &Context.Idents.get("Class"); if (IdResolver.begin(Class) == IdResolver.end()) @@ -181,7 +182,7 @@ Sema::~Sema() { 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(); @@ -209,7 +210,7 @@ bool Sema::makeUnavailableInSystemHeader(SourceLocation loc, // If we're in template instantiation, it's an error. if (!ActiveTemplateInstantiations.empty()) return false; - + // If that function's not in a system header, it's an error. if (!Context.getSourceManager().isInSystemHeader(loc)) return false; @@ -288,13 +289,13 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, // If this is a derived-to-base cast to a through a virtual base, we // need a vtable. - if (Kind == CK_DerivedToBase && + 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(), + MarkVTableUsed(E->getLocStart(), cast<CXXRecordDecl>(RecordTy->getDecl())); } @@ -328,7 +329,10 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { /// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector. static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { - if (D->isUsed()) + if (D->getMostRecentDecl()->isUsed()) + return true; + + if (D->hasExternalLinkage()) return true; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -348,7 +352,7 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { 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(); + const VarDecl *DeclToCheck = VD->getDefinition(); if (DeclToCheck) return !SemaRef->ShouldWarnIfUnusedFileScopedDecl(DeclToCheck); @@ -363,68 +367,91 @@ static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) { } namespace { - struct UndefinedInternal { - NamedDecl *decl; - FullSourceLoc useLoc; - - UndefinedInternal(NamedDecl *decl, FullSourceLoc useLoc) - : decl(decl), useLoc(useLoc) {} + struct SortUndefinedButUsed { + const SourceManager &SM; + explicit SortUndefinedButUsed(SourceManager &SM) : SM(SM) {} + + bool operator()(const std::pair<NamedDecl *, SourceLocation> &l, + const std::pair<NamedDecl *, SourceLocation> &r) const { + if (l.second.isValid() && !r.second.isValid()) + return true; + if (!l.second.isValid() && r.second.isValid()) + return false; + if (l.second != r.second) + return SM.isBeforeInTranslationUnit(l.second, r.second); + return SM.isBeforeInTranslationUnit(l.first->getLocation(), + r.first->getLocation()); + } }; - - 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. - 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; +/// Obtains a sorted list of functions that are undefined but ODR-used. +void Sema::getUndefinedButUsed( + SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) { + for (llvm::DenseMap<NamedDecl *, SourceLocation>::iterator + I = UndefinedButUsed.begin(), E = UndefinedButUsed.end(); + I != E; ++I) { + NamedDecl *ND = I->first; // Ignore attributes that have become invalid. - if (decl->isInvalidDecl()) continue; + if (ND->isInvalidDecl()) continue; // __attribute__((weakref)) is basically a definition. - if (decl->hasAttr<WeakRefAttr>()) continue; + if (ND->hasAttr<WeakRefAttr>()) continue; - if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { - if (fn->isPure() || fn->hasBody()) + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { + if (FD->isDefined()) + continue; + if (FD->hasExternalLinkage() && + !FD->getMostRecentDecl()->isInlined()) continue; } else { - if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly) + if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly) + continue; + if (ND->hasExternalLinkage()) 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)); + Undefined.push_back(std::make_pair(ND, I->second)); } - if (undefined.empty()) return; + // Sort (in order of use site) so that we're not dependent on the iteration + // order through an llvm::DenseMap. + std::sort(Undefined.begin(), Undefined.end(), + SortUndefinedButUsed(Context.getSourceManager())); +} + +/// checkUndefinedButUsed - Check for undefined objects with internal linkage +/// or that are inline. +static void checkUndefinedButUsed(Sema &S) { + if (S.UndefinedButUsed.empty()) return; + + // Collect all the still-undefined entities with internal linkage. + SmallVector<std::pair<NamedDecl *, SourceLocation>, 16> Undefined; + S.getUndefinedButUsed(Undefined); + 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 (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator + I = Undefined.begin(), E = Undefined.end(); I != E; ++I) { + NamedDecl *ND = I->first; - for (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); + if (ND->getLinkage() != ExternalLinkage) { + S.Diag(ND->getLocation(), diag::warn_undefined_internal) + << isa<VarDecl>(ND) << ND; + } else { + assert(cast<FunctionDecl>(ND)->getMostRecentDecl()->isInlined() && + "used object requires definition but isn't inline or internal?"); + S.Diag(ND->getLocation(), diag::warn_undefined_inline) << ND; + } + if (I->second.isValid()) + S.Diag(I->second, diag::note_used_here); } } void Sema::LoadExternalWeakUndeclaredIdentifiers() { if (!ExternalSource) return; - + SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs; ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs); for (unsigned I = 0, N = WeakIDs.size(); I != N; ++I) { @@ -432,7 +459,7 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() { = WeakUndeclaredIdentifiers.find(WeakIDs[I].first); if (Pos != WeakUndeclaredIdentifiers.end()) continue; - + WeakUndeclaredIdentifiers.insert(WeakIDs[I]); } } @@ -537,7 +564,7 @@ void Sema::ActOnEndOfTranslationUnit() { I != E; ++I) { assert(!(*I)->isDependentType() && "Should not see dependent types here!"); - if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(*I)) { + if (const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(*I)) { const FunctionDecl *Definition = 0; if (KeyFunction->hasBody(Definition)) MarkVTableUsed(Definition->getLocation(), *I, true); @@ -561,9 +588,9 @@ void Sema::ActOnEndOfTranslationUnit() { // 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(0, + UnusedFileScopedDecls.erase(std::remove_if(UnusedFileScopedDecls.begin(0, true), UnusedFileScopedDecls.end(), std::bind1st(std::ptr_fun(ShouldRemoveFromUnused), @@ -589,24 +616,31 @@ void Sema::ActOnEndOfTranslationUnit() { << I->first; } + if (LangOpts.CPlusPlus11 && + Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle, + SourceLocation()) + != DiagnosticsEngine::Ignored) + CheckDelegatingCtorCycles(); + if (TUKind == TU_Module) { // If we are building a module, resolve all of the exported declarations // now. if (Module *CurrentModule = PP.getCurrentModule()) { ModuleMap &ModMap = PP.getHeaderSearchInfo().getModuleMap(); - - llvm::SmallVector<Module *, 2> Stack; + + SmallVector<Module *, 2> Stack; Stack.push_back(CurrentModule); while (!Stack.empty()) { Module *Mod = Stack.back(); Stack.pop_back(); - - // Resolve the exported declarations. + + // Resolve the exported declarations and conflicts. // FIXME: Actually complain, once we figure out how to teach the - // diagnostic client to deal with complains in the module map at this + // diagnostic client to deal with complaints in the module map at this // point. ModMap.resolveExports(Mod, /*Complain=*/false); - + ModMap.resolveConflicts(Mod, /*Complain=*/false); + // Queue the submodules, so their exports will also be resolved. for (Module::submodule_iterator Sub = Mod->submodule_begin(), SubEnd = Mod->submodule_end(); @@ -615,12 +649,12 @@ void Sema::ActOnEndOfTranslationUnit() { } } } - + // Modules don't need any of the checking below. TUScope = 0; return; } - + // C99 6.9.2p2: // A declaration of an identifier for an object that has file // scope without an initializer, and without a storage-class @@ -633,10 +667,10 @@ void Sema::ActOnEndOfTranslationUnit() { // 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 (TentativeDefinitionsType::iterator + for (TentativeDefinitionsType::iterator T = TentativeDefinitions.begin(ExternalSource), TEnd = TentativeDefinitions.end(); - T != TEnd; ++T) + T != TEnd; ++T) { VarDecl *VD = (*T)->getActingDefinition(); @@ -673,12 +707,6 @@ void Sema::ActOnEndOfTranslationUnit() { } - if (LangOpts.CPlusPlus0x && - Diags.getDiagnosticLevel(diag::warn_delegating_ctor_cycle, - SourceLocation()) - != DiagnosticsEngine::Ignored) - CheckDelegatingCtorCycles(); - // If there were errors, disable 'unused' warnings since they will mostly be // noise. if (!Diags.hasErrorOccurred()) { @@ -688,7 +716,7 @@ void Sema::ActOnEndOfTranslationUnit() { E = UnusedFileScopedDecls.end(); I != E; ++I) { if (ShouldRemoveFromUnused(this, *I)) continue; - + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { const FunctionDecl *DiagD; if (!FD->hasBody(DiagD)) @@ -700,7 +728,7 @@ void Sema::ActOnEndOfTranslationUnit() { Diag(DiagD->getLocation(), diag::warn_unneeded_member_function) << DiagD->getDeclName(); else { - if (FD->getStorageClassAsWritten() == SC_Static && + if (FD->getStorageClass() == SC_Static && !FD->isInlineSpecified() && !SourceMgr.isFromMainFile( SourceMgr.getExpansionLoc(FD->getLocation()))) @@ -730,7 +758,9 @@ void Sema::ActOnEndOfTranslationUnit() { } } - checkUndefinedInternals(*this); + if (ExternalSource) + ExternalSource->ReadUndefinedButUsed(UndefinedButUsed); + checkUndefinedButUsed(*this); } if (Diags.getDiagnosticLevel(diag::warn_unused_private_field, @@ -809,13 +839,13 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) { // eliminnated. If it truly cannot be (for example, there is some reentrancy // issue I am not seeing yet), then there should at least be a clarifying // comment somewhere. - if (llvm::Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) { + if (Optional<TemplateDeductionInfo*> Info = isSFINAEContext()) { switch (DiagnosticIDs::getDiagnosticSFINAEResponse( Diags.getCurrentDiagID())) { case DiagnosticIDs::SFINAE_Report: // We'll report the diagnostic below. break; - + case DiagnosticIDs::SFINAE_SubstitutionFailure: // Count this failure so that we know that template argument deduction // has failed. @@ -832,13 +862,13 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) { Diags.setLastDiagnosticIgnored(); Diags.Clear(); return; - + case DiagnosticIDs::SFINAE_AccessControl: { // Per C++ Core Issue 1170, access control is part of SFINAE. // Additionally, the AccessCheckingSFINAE flag can be used to temporarily // make access control a part of SFINAE for the purposes of checking // type traits. - if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus0x) + if (!AccessCheckingSFINAE && !getLangOpts().CPlusPlus11) break; SourceLocation Loc = Diags.getCurrentDiagLoc(); @@ -882,10 +912,10 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) { return; } } - + // Set up the context's printing policy based on our current state. Context.setPrintingPolicy(getPrintingPolicy()); - + // Emit the diagnostic. if (!Diags.EmitCurrentDiagnostic()) return; @@ -944,10 +974,10 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) { /// \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 @@ -957,7 +987,7 @@ Scope *Sema::getScopeForContext(DeclContext *Ctx) { if (Ctx == Entity->getPrimaryContext()) return S; } - + return 0; } @@ -970,7 +1000,7 @@ void Sema::PushFunctionScope() { FunctionScopes.push_back(FunctionScopes.back()); return; } - + FunctionScopes.push_back(new FunctionScopeInfo(getDiagnostics())); } @@ -979,7 +1009,7 @@ void Sema::PushBlockScope(Scope *BlockScope, BlockDecl *Block) { BlockScope, Block)); } -void Sema::PushLambdaScope(CXXRecordDecl *Lambda, +void Sema::PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator) { FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda, CallOperator)); @@ -987,9 +1017,9 @@ void Sema::PushLambdaScope(CXXRecordDecl *Lambda, void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, const Decl *D, const BlockExpr *blkExpr) { - FunctionScopeInfo *Scope = FunctionScopes.pop_back_val(); + 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); @@ -1028,15 +1058,15 @@ bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const { BlockScopeInfo *Sema::getCurBlock() { if (FunctionScopes.empty()) return 0; - - return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); + + return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); } LambdaScopeInfo *Sema::getCurLambda() { if (FunctionScopes.empty()) return 0; - - return dyn_cast<LambdaScopeInfo>(FunctionScopes.back()); + + return dyn_cast<LambdaScopeInfo>(FunctionScopes.back()); } void Sema::ActOnComment(SourceRange Comment) { @@ -1071,7 +1101,11 @@ ExternalSemaSource::~ExternalSemaSource() {} void ExternalSemaSource::ReadMethodPool(Selector Sel) { } void ExternalSemaSource::ReadKnownNamespaces( - SmallVectorImpl<NamespaceDecl *> &Namespaces) { + SmallVectorImpl<NamespaceDecl *> &Namespaces) { +} + +void ExternalSemaSource::ReadUndefinedButUsed( + llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) { } void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { @@ -1248,7 +1282,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, // actually a CallExpr. SourceLocation ParenInsertionLoc = PP.getLocForEndOfToken(Range.getEnd()); - Diag(Loc, PD) + Diag(Loc, PD) << /*zero-arg*/ 1 << Range << (IsCallableWithAppend(E.get()) ? FixItHint::CreateInsertion(ParenInsertionLoc, "()") @@ -1269,3 +1303,9 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, E = ExprError(); return true; } + +IdentifierInfo *Sema::getSuperIdentifier() const { + if (!Ident_super) + Ident_super = &Context.Idents.get("super"); + return Ident_super; +} diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 58b1a51..79a9d3c 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -12,9 +12,6 @@ //===----------------------------------------------------------------------===// #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" @@ -22,6 +19,9 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DependentDiagnostic.h" #include "clang/AST/ExprCXX.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" using namespace clang; using namespace sema; @@ -217,6 +217,15 @@ struct AccessTarget : public AccessedEntity { return DeclaringClass; } + /// The "effective" naming class is the canonical non-anonymous + /// class containing the actual naming class. + const CXXRecordDecl *getEffectiveNamingClass() const { + const CXXRecordDecl *namingClass = getNamingClass(); + while (namingClass->isAnonymousStructOrUnion()) + namingClass = cast<CXXRecordDecl>(namingClass->getParent()); + return namingClass->getCanonicalDecl(); + } + private: void initialize() { HasInstanceContext = (isMemberAccess() && @@ -1023,8 +1032,7 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, assert(Target.isMemberAccess()); - const CXXRecordDecl *NamingClass = Target.getNamingClass(); - NamingClass = NamingClass->getCanonicalDecl(); + const CXXRecordDecl *NamingClass = Target.getEffectiveNamingClass(); for (EffectiveContext::record_iterator I = EC.Records.begin(), E = EC.Records.end(); I != E; ++I) { @@ -1089,129 +1097,173 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, return false; } +/// We are unable to access a given declaration due to its direct +/// access control; diagnose that. +static void diagnoseBadDirectAccess(Sema &S, + const EffectiveContext &EC, + AccessTarget &entity) { + assert(entity.isMemberAccess()); + NamedDecl *D = entity.getTargetDecl(); + + if (D->getAccess() == 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->getPreviousDecl(); + else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + PrevDecl = FD->getPreviousDecl(); + else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) + PrevDecl = TND->getPreviousDecl(); + else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) + break; + PrevDecl = TD->getPreviousDecl(); + } + 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 isImplicit = true; + for (CXXRecordDecl::decl_iterator + I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end(); + I != E; ++I) { + if (*I == ImmediateChild) break; + if (isa<AccessSpecDecl>(*I)) { + isImplicit = false; + break; + } + } + + S.Diag(D->getLocation(), diag::note_access_natural) + << (unsigned) (D->getAccess() == AS_protected) + << isImplicit; +} + /// 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(); + AccessTarget &entity) { + // Save the instance context to preserve invariants. + AccessTarget::SavedInstanceContext _ = entity.saveInstanceContext(); - NamedDecl *D = (Entity.isMemberAccess() ? Entity.getTargetDecl() : 0); - const CXXRecordDecl *DeclaringClass = Entity.getDeclaringClass(); + // This basically repeats the main algorithm but keeps some more + // information. - // 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->getPreviousDecl(); - else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - PrevDecl = FD->getPreviousDecl(); - else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D)) - PrevDecl = TND->getPreviousDecl(); - else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName()) - break; - PrevDecl = TD->getPreviousDecl(); - } - if (!PrevDecl) break; - D = PrevDecl; - } + // The natural access so far. + AccessSpecifier accessSoFar = AS_public; - 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; - } - } + // Check whether we have special rights to the declaring class. + if (entity.isMemberAccess()) { + NamedDecl *D = entity.getTargetDecl(); + accessSoFar = D->getAccess(); + const CXXRecordDecl *declaringClass = entity.getDeclaringClass(); - S.Diag(D->getLocation(), diag::note_access_natural) - << (unsigned) (Access == AS_protected) - << Implicit; - return; - } + switch (HasAccess(S, EC, declaringClass, accessSoFar, entity)) { + // If the declaration is accessible when named in its declaring + // class, then we must be constrained by the path. + case AR_accessible: + accessSoFar = AS_public; + entity.suppressInstanceContext(); + break; - case AR_accessible: break; + case AR_inaccessible: + if (accessSoFar == AS_private || + declaringClass == entity.getEffectiveNamingClass()) + return diagnoseBadDirectAccess(S, EC, entity); + break; case AR_dependent: - llvm_unreachable("can't diagnose dependent access failures"); + llvm_unreachable("cannot diagnose dependent access"); } } - CXXBasePaths Paths; - CXXBasePath &Path = *FindBestPath(S, EC, Entity, AS_public, Paths); + CXXBasePaths paths; + CXXBasePath &path = *FindBestPath(S, EC, entity, accessSoFar, paths); + assert(path.Access != AS_public); - CXXBasePath::iterator I = Path.end(), E = Path.begin(); - while (I != E) { - --I; + CXXBasePath::iterator i = path.end(), e = path.begin(); + CXXBasePath::iterator constrainingBase = i; + while (i != e) { + --i; - const CXXBaseSpecifier *BS = I->Base; - AccessSpecifier BaseAccess = BS->getAccessSpecifier(); + assert(accessSoFar != AS_none && accessSoFar != AS_private); - // If this is public inheritance, or the derived class is a friend, - // skip this step. - if (BaseAccess == AS_public) - continue; + // Is the entity accessible when named in the deriving class, as + // modified by the base specifier? + const CXXRecordDecl *derivingClass = i->Class->getCanonicalDecl(); + const CXXBaseSpecifier *base = i->Base; - switch (GetFriendKind(S, EC, I->Class)) { - case AR_accessible: continue; + // If the access to this base is worse than the access we have to + // the declaration, remember it. + AccessSpecifier baseAccess = base->getAccessSpecifier(); + if (baseAccess > accessSoFar) { + constrainingBase = i; + accessSoFar = baseAccess; + } + + switch (HasAccess(S, EC, derivingClass, accessSoFar, entity)) { case AR_inaccessible: break; + case AR_accessible: + accessSoFar = AS_public; + entity.suppressInstanceContext(); + constrainingBase = 0; + break; case AR_dependent: - llvm_unreachable("can't diagnose dependent access failures"); + llvm_unreachable("cannot diagnose dependent access"); } - // 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; + // If this was private inheritance, but we don't have access to + // the deriving class, we're done. + if (accessSoFar == AS_private) { + assert(baseAccess == AS_private); + assert(constrainingBase == i); + break; } } - llvm_unreachable("access not apparently constrained by path"); + // If we don't have a constraining base, the access failure must be + // due to the original declaration. + if (constrainingBase == path.end()) + return diagnoseBadDirectAccess(S, EC, entity); + + // 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 (entity.isMemberAccess() || + constrainingBase + 1 != path.end()) { + diagnostic = diag::note_access_constrained_by_path; + } else { + diagnostic = diag::note_access_natural; + } + + const CXXBaseSpecifier *base = constrainingBase->Base; + + S.Diag(base->getSourceRange().getBegin(), diagnostic) + << base->getSourceRange() + << (base->getAccessSpecifier() == AS_protected) + << (base->getAccessSpecifierAsWritten() == AS_none); + + if (entity.isMemberAccess()) + S.Diag(entity.getTargetDecl()->getLocation(), diag::note_field_decl); } static void DiagnoseBadAccess(Sema &S, SourceLocation Loc, @@ -1273,10 +1325,7 @@ 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(); + const CXXRecordDecl *NamingClass = Entity.getEffectiveNamingClass(); AccessSpecifier UnprivilegedAccess = Entity.getAccess(); assert(UnprivilegedAccess != AS_public && "public access not weeded out"); @@ -1317,7 +1366,13 @@ static AccessResult IsAccessible(Sema &S, FinalAccess = Target->getAccess(); switch (HasAccess(S, EC, DeclaringClass, FinalAccess, Entity)) { case AR_accessible: + // Target is accessible at EC when named in its declaring class. + // We can now hill-climb and simply check whether the declaring + // class is accessible as a base of the naming class. This is + // equivalent to checking the access of a notional public + // member with no instance context. FinalAccess = AS_public; + Entity.suppressInstanceContext(); break; case AR_inaccessible: break; case AR_dependent: return AR_dependent; // see above @@ -1325,8 +1380,6 @@ static AccessResult IsAccessible(Sema &S, if (DeclaringClass == NamingClass) return (FinalAccess == AS_public ? AR_accessible : AR_inaccessible); - - Entity.suppressInstanceContext(); } else { FinalAccess = AS_public; } diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index f1154c1..e12bbde0 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -13,11 +13,11 @@ //===----------------------------------------------------------------------===// #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" +#include "clang/Sema/Lookup.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -309,7 +309,8 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) { if (!VisContext) return; - if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility()) + NamedDecl *ND = dyn_cast<NamedDecl>(D); + if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue)) return; VisStack *Stack = static_cast<VisStack*>(VisContext); diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 15bfd1c..01ac8f7 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -12,21 +12,21 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/Template.h" +#include "TypeLocBuilder.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 "clang/Sema/Lookup.h" +#include "clang/Sema/Template.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, +static CXXRecordDecl *getCurrentInstantiationOf(QualType T, DeclContext *CurContext) { if (T.isNull()) return 0; @@ -34,16 +34,10 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T, const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); - if (!T->isDependentType()) + if (!Record->isDependentContext() || + Record->isCurrentInstantiation(CurContext)) 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(); @@ -84,8 +78,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, if (!SS.isSet() || SS.isInvalid()) return 0; - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + NestedNameSpecifier *NNS = SS.getScopeRep(); if (NNS->isDependent()) { // If this nested-name-specifier refers to the current // instantiation, return its DeclContext. @@ -164,9 +157,7 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return false; - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - return NNS->isDependent(); + return SS.getScopeRep()->isDependent(); } // \brief Determine whether this C++ scope specifier refers to an @@ -176,9 +167,7 @@ bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { if (!isDependentScopeSpecifier(SS)) return false; - NestedNameSpecifier *NNS - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - return getCurrentInstantiationOf(NNS) == 0; + return getCurrentInstantiationOf(SS.getScopeRep()) == 0; } /// \brief If the given nested name specifier refers to the current @@ -269,7 +258,7 @@ bool Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, /// \brief Determines whether the given declaration is an valid acceptable /// result for name lookup of a nested-name-specifier. -bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { +bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD) { if (!SD) return false; @@ -285,13 +274,13 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD)); if (T->isDependentType()) return true; - else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { + else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { if (TD->getUnderlyingType()->isRecordType() || - (Context.getLangOpts().CPlusPlus0x && + (Context.getLangOpts().CPlusPlus11 && TD->getUnderlyingType()->isEnumeralType())) return true; } else if (isa<RecordDecl>(SD) || - (Context.getLangOpts().CPlusPlus0x && isa<EnumDecl>(SD))) + (Context.getLangOpts().CPlusPlus11 && isa<EnumDecl>(SD))) return true; return false; @@ -540,7 +529,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NamedDecl *SD = Found.getAsSingle<NamedDecl>(); if (isAcceptableNestedNameSpecifier(SD)) { if (!ObjectType.isNull() && !ObjectTypeSearchedInScope && - !getLangOpts().CPlusPlus0x) { + !getLangOpts().CPlusPlus11) { // C++03 [basic.lookup.classref]p4: // [...] If the name is found in both contexts, the // class-name-or-namespace-name shall refer to the same entity. @@ -775,8 +764,7 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S, 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())); + assert(DTN->getQualifier() == SS.getScopeRep()); QualType T = Context.getDependentTemplateSpecializationType(ETK_None, DTN->getQualifier(), DTN->getIdentifier(), @@ -883,8 +871,7 @@ void Sema::RestoreNestedNameSpecifierAnnotation(void *AnnotationPtr, bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); - NestedNameSpecifier *Qualifier = - static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + NestedNameSpecifier *Qualifier = SS.getScopeRep(); // There are only two places a well-formed program may qualify a // declarator: first, when defining a namespace or class member diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index bf25c61..e2a4084 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -15,12 +15,13 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/Initialization.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/RecordLayout.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Sema/Initialization.h" #include "llvm/ADT/SmallVector.h" #include <set> using namespace clang; @@ -258,7 +259,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, } return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType, Op.ValueKind, Op.SrcExpr.take(), DestTInfo, - OpLoc, Parens.getEnd())); + OpLoc, Parens.getEnd(), + AngleBrackets)); case tok::kw_dynamic_cast: { if (!TypeDependent) { @@ -269,7 +271,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.take(), &Op.BasePath, DestTInfo, - OpLoc, Parens.getEnd())); + OpLoc, Parens.getEnd(), + AngleBrackets)); } case tok::kw_reinterpret_cast: { if (!TypeDependent) { @@ -280,7 +283,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.take(), 0, DestTInfo, OpLoc, - Parens.getEnd())); + Parens.getEnd(), + AngleBrackets)); } case tok::kw_static_cast: { if (!TypeDependent) { @@ -292,7 +296,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType, Op.ValueKind, Op.Kind, Op.SrcExpr.take(), &Op.BasePath, DestTInfo, - OpLoc, Parens.getEnd())); + OpLoc, Parens.getEnd(), + AngleBrackets)); } } } @@ -678,6 +683,98 @@ void CastOperation::CheckConstCast() { << SrcExpr.get()->getType() << DestType << OpRange; } +/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast +/// or downcast between respective pointers or references. +static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr, + QualType DestType, + SourceRange OpRange) { + QualType SrcType = SrcExpr->getType(); + // When casting from pointer or reference, get pointee type; use original + // type otherwise. + const CXXRecordDecl *SrcPointeeRD = SrcType->getPointeeCXXRecordDecl(); + const CXXRecordDecl *SrcRD = + SrcPointeeRD ? SrcPointeeRD : SrcType->getAsCXXRecordDecl(); + + // Examining subobjects for records is only possible if the complete and + // valid definition is available. Also, template instantiation is not + // allowed here. + if (!SrcRD || !SrcRD->isCompleteDefinition() || SrcRD->isInvalidDecl()) + return; + + const CXXRecordDecl *DestRD = DestType->getPointeeCXXRecordDecl(); + + if (!DestRD || !DestRD->isCompleteDefinition() || DestRD->isInvalidDecl()) + return; + + enum { + ReinterpretUpcast, + ReinterpretDowncast + } ReinterpretKind; + + CXXBasePaths BasePaths; + + if (SrcRD->isDerivedFrom(DestRD, BasePaths)) + ReinterpretKind = ReinterpretUpcast; + else if (DestRD->isDerivedFrom(SrcRD, BasePaths)) + ReinterpretKind = ReinterpretDowncast; + else + return; + + bool VirtualBase = true; + bool NonZeroOffset = false; + for (CXXBasePaths::const_paths_iterator I = BasePaths.begin(), + E = BasePaths.end(); + I != E; ++I) { + const CXXBasePath &Path = *I; + CharUnits Offset = CharUnits::Zero(); + bool IsVirtual = false; + for (CXXBasePath::const_iterator IElem = Path.begin(), EElem = Path.end(); + IElem != EElem; ++IElem) { + IsVirtual = IElem->Base->isVirtual(); + if (IsVirtual) + break; + const CXXRecordDecl *BaseRD = IElem->Base->getType()->getAsCXXRecordDecl(); + assert(BaseRD && "Base type should be a valid unqualified class type"); + // Don't check if any base has invalid declaration or has no definition + // since it has no layout info. + const CXXRecordDecl *Class = IElem->Class, + *ClassDefinition = Class->getDefinition(); + if (Class->isInvalidDecl() || !ClassDefinition || + !ClassDefinition->isCompleteDefinition()) + return; + + const ASTRecordLayout &DerivedLayout = + Self.Context.getASTRecordLayout(Class); + Offset += DerivedLayout.getBaseClassOffset(BaseRD); + } + if (!IsVirtual) { + // Don't warn if any path is a non-virtually derived base at offset zero. + if (Offset.isZero()) + return; + // Offset makes sense only for non-virtual bases. + else + NonZeroOffset = true; + } + VirtualBase = VirtualBase && IsVirtual; + } + + assert((VirtualBase || NonZeroOffset) && + "Should have returned if has non-virtual base with zero offset"); + + QualType BaseType = + ReinterpretKind == ReinterpretUpcast? DestType : SrcType; + QualType DerivedType = + ReinterpretKind == ReinterpretUpcast? SrcType : DestType; + + SourceLocation BeginLoc = OpRange.getBegin(); + Self.Diag(BeginLoc, diag::warn_reinterpret_different_from_static) + << DerivedType << BaseType << !VirtualBase << ReinterpretKind + << OpRange; + Self.Diag(BeginLoc, diag::note_reinterpret_updowncast_use_static) + << ReinterpretKind + << FixItHint::CreateReplacement(BeginLoc, "static_cast"); +} + /// 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 @@ -710,8 +807,10 @@ void CastOperation::CheckReinterpretCast() { diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType, /*listInitialization=*/false); } - } else if (tcr == TC_Success && Self.getLangOpts().ObjCAutoRefCount) { - checkObjCARCConversion(Sema::CCK_OtherCast); + } else if (tcr == TC_Success) { + if (Self.getLangOpts().ObjCAutoRefCount) + checkObjCARCConversion(Sema::CCK_OtherCast); + DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange); } } @@ -1479,6 +1578,8 @@ void Sema::CheckCompatibleReinterpretCast(QualType SrcType, QualType DestType, static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr, QualType DestType) { QualType SrcType = SrcExpr.get()->getType(); + if (Self.Context.hasSameType(SrcType, DestType)) + return; if (const PointerType *SrcPtrTy = SrcType->getAs<PointerType>()) if (SrcPtrTy->isObjCSelType()) { QualType DT = DestType; @@ -1773,7 +1874,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, // FIXME: Conditionally-supported behavior should be configurable in the // TargetInfo or similar. Self.Diag(OpRange.getBegin(), - Self.getLangOpts().CPlusPlus0x ? + Self.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) << OpRange; return TC_Success; @@ -1782,7 +1883,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, if (DestType->isFunctionPointerType()) { // See above. Self.Diag(OpRange.getBegin(), - Self.getLangOpts().CPlusPlus0x ? + Self.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_cast_fn_obj : diag::ext_cast_fn_obj) << OpRange; return TC_Success; @@ -2102,6 +2203,15 @@ void CastOperation::CheckCStyleCast() { } } + if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) { + if (DestType->isHalfType()) { + Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half) + << DestType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + } + // ARC imposes extra restrictions on casts. if (Self.getLangOpts().ObjCAutoRefCount) { checkObjCARCConversion(Sema::CCK_CStyleCast); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 692a210..4e11b3a 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -12,32 +12,31 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Lookup.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/EvaluatedExprVisitor.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/EvaluatedExprVisitor.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/Analysis/Analyses/FormatString.h" +#include "clang/Basic/CharInfo.h" +#include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Sema.h" #include "llvm/ADT/BitVector.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/ConvertUTF.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; @@ -488,8 +487,8 @@ bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, /// Handles the checks for format strings, non-POD arguments to vararg /// functions, and NULL arguments passed to non-NULL parameters. -void Sema::checkCall(NamedDecl *FDecl, Expr **Args, - unsigned NumArgs, +void Sema::checkCall(NamedDecl *FDecl, + ArrayRef<const Expr *> Args, unsigned NumProtoArgs, bool IsMemberFunction, SourceLocation Loc, @@ -503,41 +502,40 @@ void Sema::checkCall(NamedDecl *FDecl, Expr **Args, for (specific_attr_iterator<FormatAttr> I = FDecl->specific_attr_begin<FormatAttr>(), E = FDecl->specific_attr_end<FormatAttr>(); I != E ; ++I) - if (CheckFormatArguments(*I, Args, NumArgs, IsMemberFunction, CallType, - Loc, Range)) + if (CheckFormatArguments(*I, Args, IsMemberFunction, CallType, Loc, Range)) HandledFormatString = true; // Refuse POD arguments that weren't caught by the format string // checks above. if (!HandledFormatString && CallType != VariadicDoesNotApply) - for (unsigned ArgIdx = NumProtoArgs; ArgIdx < NumArgs; ++ArgIdx) { + for (unsigned ArgIdx = NumProtoArgs; ArgIdx < Args.size(); ++ArgIdx) { // Args[ArgIdx] can be null in malformed code. - if (Expr *Arg = Args[ArgIdx]) + if (const Expr *Arg = Args[ArgIdx]) variadicArgumentPODCheck(Arg, CallType); } for (specific_attr_iterator<NonNullAttr> I = FDecl->specific_attr_begin<NonNullAttr>(), E = FDecl->specific_attr_end<NonNullAttr>(); I != E; ++I) - CheckNonNullArguments(*I, Args, Loc); + CheckNonNullArguments(*I, Args.data(), Loc); // Type safety checking. for (specific_attr_iterator<ArgumentWithTypeTagAttr> i = FDecl->specific_attr_begin<ArgumentWithTypeTagAttr>(), e = FDecl->specific_attr_end<ArgumentWithTypeTagAttr>(); i != e; ++i) { - CheckArgumentWithTypeTag(*i, Args); + CheckArgumentWithTypeTag(*i, Args.data()); } } /// CheckConstructorCall - Check a constructor call for correctness and safety /// properties not enforced by the C type system. -void Sema::CheckConstructorCall(FunctionDecl *FDecl, Expr **Args, - unsigned NumArgs, +void Sema::CheckConstructorCall(FunctionDecl *FDecl, + ArrayRef<const Expr *> Args, const FunctionProtoType *Proto, SourceLocation Loc) { VariadicCallType CallType = Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; - checkCall(FDecl, Args, NumArgs, Proto->getNumArgs(), + checkCall(FDecl, Args, Proto->getNumArgs(), /*IsMemberFunction=*/true, Loc, SourceRange(), CallType); } @@ -561,7 +559,8 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, ++Args; --NumArgs; } - checkCall(FDecl, Args, NumArgs, NumProtoArgs, + checkCall(FDecl, llvm::makeArrayRef<const Expr *>(Args, NumArgs), + NumProtoArgs, IsMemberFunction, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); @@ -591,7 +590,8 @@ bool Sema::CheckObjCMethodCall(ObjCMethodDecl *Method, SourceLocation lbrac, VariadicCallType CallType = Method->isVariadic() ? VariadicMethod : VariadicDoesNotApply; - checkCall(Method, Args, NumArgs, Method->param_size(), + checkCall(Method, llvm::makeArrayRef<const Expr *>(Args, NumArgs), + Method->param_size(), /*IsMemberFunction=*/false, lbrac, Method->getSourceRange(), CallType); @@ -612,7 +612,9 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall, Proto && Proto->isVariadic() ? VariadicBlock : VariadicDoesNotApply ; unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; - checkCall(NDecl, TheCall->getArgs(), TheCall->getNumArgs(), + checkCall(NDecl, + llvm::makeArrayRef<const Expr *>(TheCall->getArgs(), + TheCall->getNumArgs()), NumProtoArgs, /*IsMemberFunction=*/false, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); @@ -1646,8 +1648,8 @@ bool Sema::SemaBuiltinLongjmp(CallExpr *TheCall) { // format string, we will usually need to emit a warning. // True string literals are then checked by CheckFormatString. Sema::StringLiteralCheckType -Sema::checkFormatStringExpr(const Expr *E, Expr **Args, - unsigned NumArgs, bool HasVAListArg, +Sema::checkFormatStringExpr(const Expr *E, ArrayRef<const Expr *> Args, + bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, VariadicCallType CallType, bool inFunctionCall) { @@ -1672,13 +1674,13 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, const AbstractConditionalOperator *C = cast<AbstractConditionalOperator>(E); StringLiteralCheckType Left = - checkFormatStringExpr(C->getTrueExpr(), Args, NumArgs, + checkFormatStringExpr(C->getTrueExpr(), Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, inFunctionCall); if (Left == SLCT_NotALiteral) return SLCT_NotALiteral; StringLiteralCheckType Right = - checkFormatStringExpr(C->getFalseExpr(), Args, NumArgs, + checkFormatStringExpr(C->getFalseExpr(), Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, inFunctionCall); return Left < Right ? Left : Right; @@ -1729,7 +1731,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, if (InitList->isStringLiteralInit()) Init = InitList->getInit(0)->IgnoreParenImpCasts(); } - return checkFormatStringExpr(Init, Args, NumArgs, + return checkFormatStringExpr(Init, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, /*inFunctionCall*/false); @@ -1787,7 +1789,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, --ArgIndex; const Expr *Arg = CE->getArg(ArgIndex - 1); - return checkFormatStringExpr(Arg, Args, NumArgs, + return checkFormatStringExpr(Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, inFunctionCall); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { @@ -1795,7 +1797,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString || BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString) { const Expr *Arg = CE->getArg(0); - return checkFormatStringExpr(Arg, Args, NumArgs, + return checkFormatStringExpr(Arg, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType, inFunctionCall); @@ -1815,7 +1817,7 @@ Sema::checkFormatStringExpr(const Expr *E, Expr **Args, StrE = cast<StringLiteral>(E); if (StrE) { - CheckFormatString(StrE, E, Args, NumArgs, HasVAListArg, format_idx, + CheckFormatString(StrE, E, Args, HasVAListArg, format_idx, firstDataArg, Type, inFunctionCall, CallType); return SLCT_CheckedLiteral; } @@ -1836,8 +1838,20 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull, e = NonNull->args_end(); i != e; ++i) { const Expr *ArgExpr = ExprArgs[*i]; - if (ArgExpr->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNotNull)) + + // As a special case, transparent unions initialized with zero are + // considered null for the purposes of the nonnull attribute. + if (const RecordType *UT = ArgExpr->getType()->getAsUnionType()) { + if (UT->getDecl()->hasAttr<TransparentUnionAttr>()) + if (const CompoundLiteralExpr *CLE = + dyn_cast<CompoundLiteralExpr>(ArgExpr)) + if (const InitListExpr *ILE = + dyn_cast<InitListExpr>(CLE->getInitializer())) + ArgExpr = ILE->getInit(0); + } + + bool Result; + if (ArgExpr->EvaluateAsBooleanCondition(Result, Context) && !Result) Diag(CallSiteLoc, diag::warn_null_arg) << ArgExpr->getSourceRange(); } } @@ -1856,25 +1870,26 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { /// CheckFormatArguments - Check calls to printf and scanf (and similar /// functions) for correct use of format strings. /// Returns true if a format string has been fully checked. -bool Sema::CheckFormatArguments(const FormatAttr *Format, Expr **Args, - unsigned NumArgs, bool IsCXXMember, +bool Sema::CheckFormatArguments(const FormatAttr *Format, + ArrayRef<const Expr *> Args, + bool IsCXXMember, VariadicCallType CallType, SourceLocation Loc, SourceRange Range) { FormatStringInfo FSI; if (getFormatStringInfo(Format, IsCXXMember, &FSI)) - return CheckFormatArguments(Args, NumArgs, FSI.HasVAListArg, FSI.FormatIdx, + return CheckFormatArguments(Args, FSI.HasVAListArg, FSI.FormatIdx, FSI.FirstDataArg, GetFormatStringType(Format), CallType, Loc, Range); return false; } -bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs, +bool Sema::CheckFormatArguments(ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, VariadicCallType CallType, SourceLocation Loc, SourceRange Range) { // CHECK: printf/scanf-like function is called with no format string. - if (format_idx >= NumArgs) { + if (format_idx >= Args.size()) { Diag(Loc, diag::warn_missing_format_string) << Range; return false; } @@ -1894,7 +1909,7 @@ bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs, // 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. StringLiteralCheckType CT = - checkFormatStringExpr(OrigFormatExpr, Args, NumArgs, HasVAListArg, + checkFormatStringExpr(OrigFormatExpr, Args, HasVAListArg, format_idx, firstDataArg, Type, CallType); if (CT != SLCT_NotALiteral) // Literal format string found, check done! @@ -1915,7 +1930,7 @@ bool Sema::CheckFormatArguments(Expr **Args, unsigned NumArgs, // If there are no arguments specified, warn with -Wformat-security, otherwise // warn only with -Wformat-nonliteral. - if (NumArgs == format_idx+1) + if (Args.size() == format_idx+1) Diag(Args[format_idx]->getLocStart(), diag::warn_format_nonliteral_noargs) << OrigFormatExpr->getSourceRange(); @@ -1936,8 +1951,7 @@ protected: const unsigned NumDataArgs; const char *Beg; // Start of format string. const bool HasVAListArg; - const Expr * const *Args; - const unsigned NumArgs; + ArrayRef<const Expr *> Args; unsigned FormatIdx; llvm::BitVector CoveredArgs; bool usesPositionalArgs; @@ -1948,13 +1962,13 @@ public: CheckFormatHandler(Sema &s, const StringLiteral *fexpr, const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, const char *beg, bool hasVAListArg, - Expr **args, unsigned numArgs, + ArrayRef<const Expr *> Args, unsigned formatIdx, bool inFunctionCall, Sema::VariadicCallType callType) : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), FirstDataArg(firstDataArg), NumDataArgs(numDataArgs), Beg(beg), HasVAListArg(hasVAListArg), - Args(args), NumArgs(numArgs), FormatIdx(formatIdx), + Args(Args), FormatIdx(formatIdx), usesPositionalArgs(false), atFirstArg(true), inFunctionCall(inFunctionCall), CallType(callType) { CoveredArgs.resize(numDataArgs); @@ -2066,7 +2080,7 @@ void CheckFormatHandler::HandleInvalidLengthModifier( CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength()); // See if we know how to fix this length modifier. - llvm::Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier(); + Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier(); if (FixedLM) { EmitFormatDiagnostic(S.PDiag(DiagID) << LM.toString() << CS.toString(), getLocationOfByte(LM.getStart()), @@ -2099,7 +2113,7 @@ void CheckFormatHandler::HandleNonStandardLengthModifier( CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength()); // See if we know how to fix this length modifier. - llvm::Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier(); + Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier(); if (FixedLM) { EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << LM.toString() << 0, @@ -2126,7 +2140,7 @@ void CheckFormatHandler::HandleNonStandardConversionSpecifier( using namespace analyze_format_string; // See if we know how to fix this conversion specifier. - llvm::Optional<ConversionSpecifier> FixedCS = CS.getStandardSpecifier(); + Optional<ConversionSpecifier> FixedCS = CS.getStandardSpecifier(); if (FixedCS) { EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << CS.toString() << /*conversion specifier*/1, @@ -2346,11 +2360,11 @@ public: const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, bool isObjC, const char *beg, bool hasVAListArg, - Expr **Args, unsigned NumArgs, + ArrayRef<const Expr *> Args, unsigned formatIdx, bool inFunctionCall, Sema::VariadicCallType CallType) : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, - numDataArgs, beg, hasVAListArg, Args, NumArgs, + numDataArgs, beg, hasVAListArg, Args, formatIdx, inFunctionCall, CallType), ObjCContext(isObjC) {} @@ -2690,12 +2704,24 @@ static bool requiresParensToAddCast(const Expr *E) { switch (Inside->getStmtClass()) { case Stmt::ArraySubscriptExprClass: case Stmt::CallExprClass: + case Stmt::CharacterLiteralClass: + case Stmt::CXXBoolLiteralExprClass: case Stmt::DeclRefExprClass: + case Stmt::FloatingLiteralClass: + case Stmt::IntegerLiteralClass: case Stmt::MemberExprClass: + case Stmt::ObjCArrayLiteralClass: + case Stmt::ObjCBoolLiteralExprClass: + case Stmt::ObjCBoxedExprClass: + case Stmt::ObjCDictionaryLiteralClass: + case Stmt::ObjCEncodeExprClass: case Stmt::ObjCIvarRefExprClass: case Stmt::ObjCMessageExprClass: case Stmt::ObjCPropertyRefExprClass: + case Stmt::ObjCStringLiteralClass: + case Stmt::ObjCSubscriptRefExprClass: case Stmt::ParenExprClass: + case Stmt::StringLiteralClass: case Stmt::UnaryOperatorClass: return false; default: @@ -2717,8 +2743,8 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, if (!AT.isValid()) return true; - QualType IntendedTy = E->getType(); - if (AT.matchesType(S.Context, IntendedTy)) + QualType ExprTy = E->getType(); + if (AT.matchesType(S.Context, ExprTy)) return true; // Look through argument promotions for our error message's reported type. @@ -2729,7 +2755,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, if (ICE->getCastKind() == CK_IntegralCast || ICE->getCastKind() == CK_FloatingCast) { E = ICE->getSubExpr(); - IntendedTy = E->getType(); + ExprTy = E->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 @@ -2737,22 +2763,63 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, if (ICE->getType() == S.Context.IntTy || ICE->getType() == S.Context.UnsignedIntTy) { // All further checking is done on the subexpression. - if (AT.matchesType(S.Context, IntendedTy)) + if (AT.matchesType(S.Context, ExprTy)) return true; } } + } else if (const CharacterLiteral *CL = dyn_cast<CharacterLiteral>(E)) { + // Special case for 'a', which has type 'int' in C. + // Note, however, that we do /not/ want to treat multibyte constants like + // 'MooV' as characters! This form is deprecated but still exists. + if (ExprTy == S.Context.IntTy) + if (llvm::isUIntN(S.Context.getCharWidth(), CL->getValue())) + ExprTy = S.Context.CharTy; + } + + // %C in an Objective-C context prints a unichar, not a wchar_t. + // If the argument is an integer of some kind, believe the %C and suggest + // a cast instead of changing the conversion specifier. + QualType IntendedTy = ExprTy; + if (ObjCContext && + FS.getConversionSpecifier().getKind() == ConversionSpecifier::CArg) { + if (ExprTy->isIntegralOrUnscopedEnumerationType() && + !ExprTy->isCharType()) { + // 'unichar' is defined as a typedef of unsigned short, but we should + // prefer using the typedef if it is visible. + IntendedTy = S.Context.UnsignedShortTy; + + LookupResult Result(S, &S.Context.Idents.get("unichar"), E->getLocStart(), + Sema::LookupOrdinaryName); + if (S.LookupName(Result, S.getCurScope())) { + NamedDecl *ND = Result.getFoundDecl(); + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND)) + if (TD->getUnderlyingType() == IntendedTy) + IntendedTy = S.Context.getTypedefType(TD); + } + } } + // Special-case some of Darwin's platform-independence types by suggesting + // casts to primitive types that are known to be large enough. + bool ShouldNotPrintDirectly = false; if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { - // Special-case some of Darwin's platform-independence types. - if (const TypedefType *UserTy = IntendedTy->getAs<TypedefType>()) { + // Use a 'while' to peel off layers of typedefs. + QualType TyTy = IntendedTy; + while (const TypedefType *UserTy = TyTy->getAs<TypedefType>()) { StringRef Name = UserTy->getDecl()->getName(); - IntendedTy = llvm::StringSwitch<QualType>(Name) + QualType CastTy = llvm::StringSwitch<QualType>(Name) .Case("NSInteger", S.Context.LongTy) .Case("NSUInteger", S.Context.UnsignedLongTy) .Case("SInt32", S.Context.IntTy) .Case("UInt32", S.Context.UnsignedIntTy) - .Default(IntendedTy); + .Default(QualType()); + + if (!CastTy.isNull()) { + ShouldNotPrintDirectly = true; + IntendedTy = CastTy; + break; + } + TyTy = UserTy->desugar(); } } @@ -2769,7 +2836,19 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen); - if (IntendedTy != E->getType()) { + if (IntendedTy == ExprTy) { + // In this case, the specifier is wrong and should be changed to match + // the argument. + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << IntendedTy + << E->getSourceRange(), + E->getLocStart(), + /*IsStringLocation*/false, + SpecRange, + FixItHint::CreateReplacement(SpecRange, os.str())); + + } else { // The canonical type for formatting this value is different from the // actual type of the expression. (This occurs, for example, with Darwin's // NSInteger on 32-bit platforms, where it is typedef'd as 'int', but @@ -2807,26 +2886,28 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, Hints.push_back(FixItHint::CreateInsertion(After, ")")); } - // We extract the name from the typedef because we don't want to show - // the underlying type in the diagnostic. - const TypedefType *UserTy = cast<TypedefType>(E->getType()); - StringRef Name = UserTy->getDecl()->getName(); - - // Finally, emit the diagnostic. - EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast) - << Name << IntendedTy - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation=*/false, - SpecRange, Hints); - } else { - EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << IntendedTy - << E->getSourceRange(), - E->getLocStart(), - /*IsStringLocation*/false, - SpecRange, - FixItHint::CreateReplacement(SpecRange, os.str())); + if (ShouldNotPrintDirectly) { + // The expression has a type that should not be printed directly. + // We extract the name from the typedef because we don't want to show + // the underlying type in the diagnostic. + StringRef Name = cast<TypedefType>(ExprTy)->getDecl()->getName(); + + EmitFormatDiagnostic(S.PDiag(diag::warn_format_argument_needs_cast) + << Name << IntendedTy + << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation=*/false, + SpecRange, Hints); + } else { + // In this case, the expression could be printed using a different + // specifier, but we've decided that the specifier is probably correct + // and we should cast instead. Just use the normal warning message. + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << ExprTy + << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation*/false, + SpecRange, Hints); + } } } else { const CharSourceRange &CSR = getSpecifierRange(StartSpecifier, @@ -2834,17 +2915,17 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // Since the warning for passing non-POD types to variadic functions // was deferred until now, we emit a warning for non-POD // arguments here. - if (S.isValidVarArgType(E->getType()) == Sema::VAK_Invalid) { + if (S.isValidVarArgType(ExprTy) == Sema::VAK_Invalid) { unsigned DiagKind; - if (E->getType()->isObjCObjectType()) + if (ExprTy->isObjCObjectType()) DiagKind = diag::err_cannot_pass_objc_interface_to_vararg_format; else DiagKind = diag::warn_non_pod_vararg_with_format_string; EmitFormatDiagnostic( S.PDiag(DiagKind) - << S.getLangOpts().CPlusPlus0x - << E->getType() + << S.getLangOpts().CPlusPlus11 + << ExprTy << CallType << AT.getRepresentativeTypeName(S.Context) << CSR @@ -2855,7 +2936,7 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, } else EmitFormatDiagnostic( S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << E->getType() + << AT.getRepresentativeTypeName(S.Context) << ExprTy << CSR << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/false, CSR); @@ -2872,12 +2953,12 @@ public: CheckScanfHandler(Sema &s, const StringLiteral *fexpr, const Expr *origFormatExpr, unsigned firstDataArg, unsigned numDataArgs, const char *beg, bool hasVAListArg, - Expr **Args, unsigned NumArgs, + ArrayRef<const Expr *> Args, unsigned formatIdx, bool inFunctionCall, Sema::VariadicCallType CallType) : CheckFormatHandler(s, fexpr, origFormatExpr, firstDataArg, numDataArgs, beg, hasVAListArg, - Args, NumArgs, formatIdx, inFunctionCall, CallType) + Args, formatIdx, inFunctionCall, CallType) {} bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, @@ -3029,7 +3110,7 @@ bool CheckScanfHandler::HandleScanfSpecifier( void Sema::CheckFormatString(const StringLiteral *FExpr, const Expr *OrigFormatExpr, - Expr **Args, unsigned NumArgs, + ArrayRef<const Expr *> Args, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, FormatStringType Type, bool inFunctionCall, VariadicCallType CallType) { @@ -3047,7 +3128,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, StringRef StrRef = FExpr->getString(); const char *Str = StrRef.data(); unsigned StrLen = StrRef.size(); - const unsigned numDataArgs = NumArgs - firstDataArg; + const unsigned numDataArgs = Args.size() - firstDataArg; // CHECK: empty format string? if (StrLen == 0 && numDataArgs > 0) { @@ -3061,7 +3142,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, if (Type == FST_Printf || Type == FST_NSString) { CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, (Type == FST_NSString), - Str, HasVAListArg, Args, NumArgs, format_idx, + Str, HasVAListArg, Args, format_idx, inFunctionCall, CallType); if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, @@ -3070,7 +3151,7 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, H.DoneProcessing(); } else if (Type == FST_Scanf) { CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, - Str, HasVAListArg, Args, NumArgs, format_idx, + Str, HasVAListArg, Args, format_idx, inFunctionCall, CallType); if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen, @@ -3177,7 +3258,8 @@ void Sema::CheckMemaccessArguments(const CallExpr *Call, if (const UnaryOperator *UnaryOp = dyn_cast<UnaryOperator>(Dest)) if (UnaryOp->getOpcode() == UO_AddrOf) ActionIdx = 1; // If its an address-of operator, just remove it. - if (Context.getTypeSize(PointeeTy) == Context.getCharWidth()) + if (!PointeeTy->isIncompleteType() && + (Context.getTypeSize(PointeeTy) == Context.getCharWidth())) ActionIdx = 2; // If the pointee's size is sizeof(char), // suggest an explicit length. @@ -3922,7 +4004,11 @@ struct IntRange { unsigned NumPositive = Enum->getNumPositiveBits(); unsigned NumNegative = Enum->getNumNegativeBits(); - return IntRange(std::max(NumPositive, NumNegative), NumNegative == 0); + if (NumNegative == 0) + return IntRange(NumPositive, true/*NonNegative*/); + else + return IntRange(std::max(NumPositive + 1, NumNegative), + false/*NonNegative*/); } const BuiltinType *BT = cast<BuiltinType>(T); @@ -4328,38 +4414,108 @@ static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, Expr *Constant, Expr *Other, llvm::APSInt Value, bool RhsConstant) { + // 0 values are handled later by CheckTrivialUnsignedComparison(). + if (Value == 0) + return; + BinaryOperatorKind op = E->getOpcode(); QualType OtherT = Other->getType(); QualType ConstantT = Constant->getType(); + QualType CommonT = E->getLHS()->getType(); if (S.Context.hasSameUnqualifiedType(OtherT, ConstantT)) return; assert((OtherT->isIntegerType() && ConstantT->isIntegerType()) && "comparison with non-integer type"); - // FIXME. handle cases for signedness to catch (signed char)N == 200 + + bool ConstantSigned = ConstantT->isSignedIntegerType(); + bool CommonSigned = CommonT->isSignedIntegerType(); + + bool EqualityOnly = false; + + // TODO: Investigate using GetExprRange() to get tighter bounds on + // on the bit ranges. IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); - IntRange LitRange = GetValueRange(S.Context, Value, Value.getBitWidth()); - if (OtherRange.Width >= LitRange.Width) - return; + unsigned OtherWidth = OtherRange.Width; + + if (CommonSigned) { + // The common type is signed, therefore no signed to unsigned conversion. + if (!OtherRange.NonNegative) { + // Check that the constant is representable in type OtherT. + if (ConstantSigned) { + if (OtherWidth >= Value.getMinSignedBits()) + return; + } else { // !ConstantSigned + if (OtherWidth >= Value.getActiveBits() + 1) + return; + } + } else { // !OtherSigned + // Check that the constant is representable in type OtherT. + // Negative values are out of range. + if (ConstantSigned) { + if (Value.isNonNegative() && OtherWidth >= Value.getActiveBits()) + return; + } else { // !ConstantSigned + if (OtherWidth >= Value.getActiveBits()) + return; + } + } + } else { // !CommonSigned + if (OtherRange.NonNegative) { + if (OtherWidth >= Value.getActiveBits()) + return; + } else if (!OtherRange.NonNegative && !ConstantSigned) { + // Check to see if the constant is representable in OtherT. + if (OtherWidth > Value.getActiveBits()) + return; + // Check to see if the constant is equivalent to a negative value + // cast to CommonT. + if (S.Context.getIntWidth(ConstantT) == S.Context.getIntWidth(CommonT) && + Value.isNegative() && Value.getMinSignedBits() <= OtherWidth) + return; + // The constant value rests between values that OtherT can represent after + // conversion. Relational comparison still works, but equality + // comparisons will be tautological. + EqualityOnly = true; + } else { // OtherSigned && ConstantSigned + assert(0 && "Two signed types converted to unsigned types."); + } + } + + bool PositiveConstant = !ConstantSigned || Value.isNonNegative(); + bool IsTrue = true; - if (op == BO_EQ) - IsTrue = false; - else if (op == BO_NE) - IsTrue = true; - else if (RhsConstant) { + if (op == BO_EQ || op == BO_NE) { + IsTrue = op == BO_NE; + } else if (EqualityOnly) { + return; + } else if (RhsConstant) { if (op == BO_GT || op == BO_GE) - IsTrue = !LitRange.NonNegative; + IsTrue = !PositiveConstant; else // op == BO_LT || op == BO_LE - IsTrue = LitRange.NonNegative; + IsTrue = PositiveConstant; } else { if (op == BO_LT || op == BO_LE) - IsTrue = !LitRange.NonNegative; + IsTrue = !PositiveConstant; else // op == BO_GT || op == BO_GE - IsTrue = LitRange.NonNegative; + IsTrue = PositiveConstant; } - SmallString<16> PrettySourceValue(Value.toString(10)); + + // If this is a comparison to an enum constant, include that + // constant in the diagnostic. + const EnumConstantDecl *ED = 0; + if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Constant)) + ED = dyn_cast<EnumConstantDecl>(DR->getDecl()); + + SmallString<64> PrettySourceValue; + llvm::raw_svector_ostream OS(PrettySourceValue); + if (ED) + OS << '\'' << *ED << "' (" << Value << ")"; + else + OS << Value; + S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare) - << PrettySourceValue << OtherT << IsTrue - << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); + << OS.str() << OtherT << IsTrue + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); } /// Analyze the operands of the given comparison. Implements the @@ -4800,7 +4956,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) == Expr::NPCK_GNUNull) && !Target->isAnyPointerType() && !Target->isBlockPointerType() && !Target->isMemberPointerType() - && Target->isScalarType()) { + && Target->isScalarType() && !Target->isNullPtrType()) { SourceLocation Loc = E->getSourceRange().getBegin(); if (Loc.isMacroID()) Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; @@ -4843,7 +4999,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, // People want to build with -Wshorten-64-to-32 and not -Wconversion. if (S.SourceMgr.isInSystemMacro(CC)) return; - + if (TargetRange.Width == 32 && S.Context.getIntWidth(E->getType()) == 64) return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_integer_64_32, /* pruneControlFlow */ true); @@ -4887,10 +5043,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, 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()) && + if (SourceEnum->getDecl()->hasNameForLinkage() && + TargetEnum->getDecl()->hasNameForLinkage() && SourceEnum != TargetEnum) { if (S.SourceMgr.isInSystemMacro(CC)) return; @@ -5046,6 +5200,462 @@ void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { AnalyzeImplicitConversions(*this, E, CC); } +/// Diagnose when expression is an integer constant expression and its evaluation +/// results in integer overflow +void Sema::CheckForIntOverflow (Expr *E) { + if (isa<BinaryOperator>(E->IgnoreParens())) { + llvm::SmallVector<PartialDiagnosticAt, 4> Diags; + E->EvaluateForOverflow(Context, &Diags); + } +} + +namespace { +/// \brief Visitor for expressions which looks for unsequenced operations on the +/// same object. +class SequenceChecker : public EvaluatedExprVisitor<SequenceChecker> { + /// \brief A tree of sequenced regions within an expression. Two regions are + /// unsequenced if one is an ancestor or a descendent of the other. When we + /// finish processing an expression with sequencing, such as a comma + /// expression, we fold its tree nodes into its parent, since they are + /// unsequenced with respect to nodes we will visit later. + class SequenceTree { + struct Value { + explicit Value(unsigned Parent) : Parent(Parent), Merged(false) {} + unsigned Parent : 31; + bool Merged : 1; + }; + llvm::SmallVector<Value, 8> Values; + + public: + /// \brief A region within an expression which may be sequenced with respect + /// to some other region. + class Seq { + explicit Seq(unsigned N) : Index(N) {} + unsigned Index; + friend class SequenceTree; + public: + Seq() : Index(0) {} + }; + + SequenceTree() { Values.push_back(Value(0)); } + Seq root() const { return Seq(0); } + + /// \brief Create a new sequence of operations, which is an unsequenced + /// subset of \p Parent. This sequence of operations is sequenced with + /// respect to other children of \p Parent. + Seq allocate(Seq Parent) { + Values.push_back(Value(Parent.Index)); + return Seq(Values.size() - 1); + } + + /// \brief Merge a sequence of operations into its parent. + void merge(Seq S) { + Values[S.Index].Merged = true; + } + + /// \brief Determine whether two operations are unsequenced. This operation + /// is asymmetric: \p Cur should be the more recent sequence, and \p Old + /// should have been merged into its parent as appropriate. + bool isUnsequenced(Seq Cur, Seq Old) { + unsigned C = representative(Cur.Index); + unsigned Target = representative(Old.Index); + while (C >= Target) { + if (C == Target) + return true; + C = Values[C].Parent; + } + return false; + } + + private: + /// \brief Pick a representative for a sequence. + unsigned representative(unsigned K) { + if (Values[K].Merged) + // Perform path compression as we go. + return Values[K].Parent = representative(Values[K].Parent); + return K; + } + }; + + /// An object for which we can track unsequenced uses. + typedef NamedDecl *Object; + + /// Different flavors of object usage which we track. We only track the + /// least-sequenced usage of each kind. + enum UsageKind { + /// A read of an object. Multiple unsequenced reads are OK. + UK_Use, + /// A modification of an object which is sequenced before the value + /// computation of the expression, such as ++n. + UK_ModAsValue, + /// A modification of an object which is not sequenced before the value + /// computation of the expression, such as n++. + UK_ModAsSideEffect, + + UK_Count = UK_ModAsSideEffect + 1 + }; + + struct Usage { + Usage() : Use(0), Seq() {} + Expr *Use; + SequenceTree::Seq Seq; + }; + + struct UsageInfo { + UsageInfo() : Diagnosed(false) {} + Usage Uses[UK_Count]; + /// Have we issued a diagnostic for this variable already? + bool Diagnosed; + }; + typedef llvm::SmallDenseMap<Object, UsageInfo, 16> UsageInfoMap; + + Sema &SemaRef; + /// Sequenced regions within the expression. + SequenceTree Tree; + /// Declaration modifications and references which we have seen. + UsageInfoMap UsageMap; + /// The region we are currently within. + SequenceTree::Seq Region; + /// Filled in with declarations which were modified as a side-effect + /// (that is, post-increment operations). + llvm::SmallVectorImpl<std::pair<Object, Usage> > *ModAsSideEffect; + /// Expressions to check later. We defer checking these to reduce + /// stack usage. + llvm::SmallVectorImpl<Expr*> &WorkList; + + /// RAII object wrapping the visitation of a sequenced subexpression of an + /// expression. At the end of this process, the side-effects of the evaluation + /// become sequenced with respect to the value computation of the result, so + /// we downgrade any UK_ModAsSideEffect within the evaluation to + /// UK_ModAsValue. + struct SequencedSubexpression { + SequencedSubexpression(SequenceChecker &Self) + : Self(Self), OldModAsSideEffect(Self.ModAsSideEffect) { + Self.ModAsSideEffect = &ModAsSideEffect; + } + ~SequencedSubexpression() { + for (unsigned I = 0, E = ModAsSideEffect.size(); I != E; ++I) { + UsageInfo &U = Self.UsageMap[ModAsSideEffect[I].first]; + U.Uses[UK_ModAsSideEffect] = ModAsSideEffect[I].second; + Self.addUsage(U, ModAsSideEffect[I].first, + ModAsSideEffect[I].second.Use, UK_ModAsValue); + } + Self.ModAsSideEffect = OldModAsSideEffect; + } + + SequenceChecker &Self; + llvm::SmallVector<std::pair<Object, Usage>, 4> ModAsSideEffect; + llvm::SmallVectorImpl<std::pair<Object, Usage> > *OldModAsSideEffect; + }; + + /// \brief Find the object which is produced by the specified expression, + /// if any. + Object getObject(Expr *E, bool Mod) const { + E = E->IgnoreParenCasts(); + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { + if (Mod && (UO->getOpcode() == UO_PreInc || UO->getOpcode() == UO_PreDec)) + return getObject(UO->getSubExpr(), Mod); + } else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) + return getObject(BO->getRHS(), Mod); + if (Mod && BO->isAssignmentOp()) + return getObject(BO->getLHS(), Mod); + } else if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + // FIXME: Check for more interesting cases, like "x.n = ++x.n". + if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenCasts())) + return ME->getMemberDecl(); + } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + // FIXME: If this is a reference, map through to its value. + return DRE->getDecl(); + return 0; + } + + /// \brief Note that an object was modified or used by an expression. + void addUsage(UsageInfo &UI, Object O, Expr *Ref, UsageKind UK) { + Usage &U = UI.Uses[UK]; + if (!U.Use || !Tree.isUnsequenced(Region, U.Seq)) { + if (UK == UK_ModAsSideEffect && ModAsSideEffect) + ModAsSideEffect->push_back(std::make_pair(O, U)); + U.Use = Ref; + U.Seq = Region; + } + } + /// \brief Check whether a modification or use conflicts with a prior usage. + void checkUsage(Object O, UsageInfo &UI, Expr *Ref, UsageKind OtherKind, + bool IsModMod) { + if (UI.Diagnosed) + return; + + const Usage &U = UI.Uses[OtherKind]; + if (!U.Use || !Tree.isUnsequenced(Region, U.Seq)) + return; + + Expr *Mod = U.Use; + Expr *ModOrUse = Ref; + if (OtherKind == UK_Use) + std::swap(Mod, ModOrUse); + + SemaRef.Diag(Mod->getExprLoc(), + IsModMod ? diag::warn_unsequenced_mod_mod + : diag::warn_unsequenced_mod_use) + << O << SourceRange(ModOrUse->getExprLoc()); + UI.Diagnosed = true; + } + + void notePreUse(Object O, Expr *Use) { + UsageInfo &U = UsageMap[O]; + // Uses conflict with other modifications. + checkUsage(O, U, Use, UK_ModAsValue, false); + } + void notePostUse(Object O, Expr *Use) { + UsageInfo &U = UsageMap[O]; + checkUsage(O, U, Use, UK_ModAsSideEffect, false); + addUsage(U, O, Use, UK_Use); + } + + void notePreMod(Object O, Expr *Mod) { + UsageInfo &U = UsageMap[O]; + // Modifications conflict with other modifications and with uses. + checkUsage(O, U, Mod, UK_ModAsValue, true); + checkUsage(O, U, Mod, UK_Use, false); + } + void notePostMod(Object O, Expr *Use, UsageKind UK) { + UsageInfo &U = UsageMap[O]; + checkUsage(O, U, Use, UK_ModAsSideEffect, true); + addUsage(U, O, Use, UK); + } + +public: + SequenceChecker(Sema &S, Expr *E, + llvm::SmallVectorImpl<Expr*> &WorkList) + : EvaluatedExprVisitor<SequenceChecker>(S.Context), SemaRef(S), + Region(Tree.root()), ModAsSideEffect(0), WorkList(WorkList) { + Visit(E); + } + + void VisitStmt(Stmt *S) { + // Skip all statements which aren't expressions for now. + } + + void VisitExpr(Expr *E) { + // By default, just recurse to evaluated subexpressions. + EvaluatedExprVisitor<SequenceChecker>::VisitStmt(E); + } + + void VisitCastExpr(CastExpr *E) { + Object O = Object(); + if (E->getCastKind() == CK_LValueToRValue) + O = getObject(E->getSubExpr(), false); + + if (O) + notePreUse(O, E); + VisitExpr(E); + if (O) + notePostUse(O, E); + } + + void VisitBinComma(BinaryOperator *BO) { + // C++11 [expr.comma]p1: + // Every value computation and side effect associated with the left + // expression is sequenced before every value computation and side + // effect associated with the right expression. + SequenceTree::Seq LHS = Tree.allocate(Region); + SequenceTree::Seq RHS = Tree.allocate(Region); + SequenceTree::Seq OldRegion = Region; + + { + SequencedSubexpression SeqLHS(*this); + Region = LHS; + Visit(BO->getLHS()); + } + + Region = RHS; + Visit(BO->getRHS()); + + Region = OldRegion; + + // Forget that LHS and RHS are sequenced. They are both unsequenced + // with respect to other stuff. + Tree.merge(LHS); + Tree.merge(RHS); + } + + void VisitBinAssign(BinaryOperator *BO) { + // The modification is sequenced after the value computation of the LHS + // and RHS, so check it before inspecting the operands and update the + // map afterwards. + Object O = getObject(BO->getLHS(), true); + if (!O) + return VisitExpr(BO); + + notePreMod(O, BO); + + // C++11 [expr.ass]p7: + // E1 op= E2 is equivalent to E1 = E1 op E2, except that E1 is evaluated + // only once. + // + // Therefore, for a compound assignment operator, O is considered used + // everywhere except within the evaluation of E1 itself. + if (isa<CompoundAssignOperator>(BO)) + notePreUse(O, BO); + + Visit(BO->getLHS()); + + if (isa<CompoundAssignOperator>(BO)) + notePostUse(O, BO); + + Visit(BO->getRHS()); + + notePostMod(O, BO, UK_ModAsValue); + } + void VisitCompoundAssignOperator(CompoundAssignOperator *CAO) { + VisitBinAssign(CAO); + } + + void VisitUnaryPreInc(UnaryOperator *UO) { VisitUnaryPreIncDec(UO); } + void VisitUnaryPreDec(UnaryOperator *UO) { VisitUnaryPreIncDec(UO); } + void VisitUnaryPreIncDec(UnaryOperator *UO) { + Object O = getObject(UO->getSubExpr(), true); + if (!O) + return VisitExpr(UO); + + notePreMod(O, UO); + Visit(UO->getSubExpr()); + notePostMod(O, UO, UK_ModAsValue); + } + + void VisitUnaryPostInc(UnaryOperator *UO) { VisitUnaryPostIncDec(UO); } + void VisitUnaryPostDec(UnaryOperator *UO) { VisitUnaryPostIncDec(UO); } + void VisitUnaryPostIncDec(UnaryOperator *UO) { + Object O = getObject(UO->getSubExpr(), true); + if (!O) + return VisitExpr(UO); + + notePreMod(O, UO); + Visit(UO->getSubExpr()); + notePostMod(O, UO, UK_ModAsSideEffect); + } + + /// Don't visit the RHS of '&&' or '||' if it might not be evaluated. + void VisitBinLOr(BinaryOperator *BO) { + // The side-effects of the LHS of an '&&' are sequenced before the + // value computation of the RHS, and hence before the value computation + // of the '&&' itself, unless the LHS evaluates to zero. We treat them + // as if they were unconditionally sequenced. + { + SequencedSubexpression Sequenced(*this); + Visit(BO->getLHS()); + } + + bool Result; + if (!BO->getLHS()->isValueDependent() && + BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) { + if (!Result) + Visit(BO->getRHS()); + } else { + // Check for unsequenced operations in the RHS, treating it as an + // entirely separate evaluation. + // + // FIXME: If there are operations in the RHS which are unsequenced + // with respect to operations outside the RHS, and those operations + // are unconditionally evaluated, diagnose them. + WorkList.push_back(BO->getRHS()); + } + } + void VisitBinLAnd(BinaryOperator *BO) { + { + SequencedSubexpression Sequenced(*this); + Visit(BO->getLHS()); + } + + bool Result; + if (!BO->getLHS()->isValueDependent() && + BO->getLHS()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) { + if (Result) + Visit(BO->getRHS()); + } else { + WorkList.push_back(BO->getRHS()); + } + } + + // Only visit the condition, unless we can be sure which subexpression will + // be chosen. + void VisitAbstractConditionalOperator(AbstractConditionalOperator *CO) { + SequencedSubexpression Sequenced(*this); + Visit(CO->getCond()); + + bool Result; + if (!CO->getCond()->isValueDependent() && + CO->getCond()->EvaluateAsBooleanCondition(Result, SemaRef.Context)) + Visit(Result ? CO->getTrueExpr() : CO->getFalseExpr()); + else { + WorkList.push_back(CO->getTrueExpr()); + WorkList.push_back(CO->getFalseExpr()); + } + } + + void VisitCXXConstructExpr(CXXConstructExpr *CCE) { + if (!CCE->isListInitialization()) + return VisitExpr(CCE); + + // In C++11, list initializations are sequenced. + llvm::SmallVector<SequenceTree::Seq, 32> Elts; + SequenceTree::Seq Parent = Region; + for (CXXConstructExpr::arg_iterator I = CCE->arg_begin(), + E = CCE->arg_end(); + I != E; ++I) { + Region = Tree.allocate(Parent); + Elts.push_back(Region); + Visit(*I); + } + + // Forget that the initializers are sequenced. + Region = Parent; + for (unsigned I = 0; I < Elts.size(); ++I) + Tree.merge(Elts[I]); + } + + void VisitInitListExpr(InitListExpr *ILE) { + if (!SemaRef.getLangOpts().CPlusPlus11) + return VisitExpr(ILE); + + // In C++11, list initializations are sequenced. + llvm::SmallVector<SequenceTree::Seq, 32> Elts; + SequenceTree::Seq Parent = Region; + for (unsigned I = 0; I < ILE->getNumInits(); ++I) { + Expr *E = ILE->getInit(I); + if (!E) continue; + Region = Tree.allocate(Parent); + Elts.push_back(Region); + Visit(E); + } + + // Forget that the initializers are sequenced. + Region = Parent; + for (unsigned I = 0; I < Elts.size(); ++I) + Tree.merge(Elts[I]); + } +}; +} + +void Sema::CheckUnsequencedOperations(Expr *E) { + llvm::SmallVector<Expr*, 8> WorkList; + WorkList.push_back(E); + while (!WorkList.empty()) { + Expr *Item = WorkList.back(); + WorkList.pop_back(); + SequenceChecker(*this, Item, WorkList); + } +} + +void Sema::CheckCompletedExpr(Expr *E, SourceLocation CheckLoc, + bool IsConstexpr) { + CheckImplicitConversions(E, CheckLoc); + CheckUnsequencedOperations(E); + if (!IsConstexpr && !E->isValueDependent()) + CheckForIntOverflow(E); +} + void Sema::CheckBitFieldInitialization(SourceLocation InitLoc, FieldDecl *BitField, Expr *Init) { @@ -5091,7 +5701,7 @@ bool Sema::CheckParmsForFunctionDef(ParmVarDecl **P, ParmVarDecl **PEnd, QualType PType = Param->getOriginalType(); if (const ArrayType *AT = Context.getAsArrayType(PType)) { if (AT->getSizeModifier() == ArrayType::Star) { - // FIXME: This diagnosic should point the '[*]' if source-location + // FIXME: This diagnostic should point the '[*]' if source-location // information is added for it. Diag(Param->getLocation(), diag::err_array_star_in_function_definition); } @@ -5174,16 +5784,16 @@ static bool IsTailPaddedMemberArray(Sema &S, llvm::APInt Size, while (TInfo) { TypeLoc TL = TInfo->getTypeLoc(); // Look through typedefs. - const TypedefTypeLoc *TTL = dyn_cast<TypedefTypeLoc>(&TL); - if (TTL) { - const TypedefNameDecl *TDL = TTL->getTypedefNameDecl(); + if (TypedefTypeLoc TTL = TL.getAs<TypedefTypeLoc>()) { + const TypedefNameDecl *TDL = TTL.getTypedefNameDecl(); TInfo = TDL->getTypeSourceInfo(); continue; } - ConstantArrayTypeLoc CTL = cast<ConstantArrayTypeLoc>(TL); - const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr()); - if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) - return false; + if (ConstantArrayTypeLoc CTL = TL.getAs<ConstantArrayTypeLoc>()) { + const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr()); + if (!SizeExpr || SizeExpr->getExprLoc().isMacroID()) + return false; + } break; } @@ -5574,7 +6184,7 @@ static bool isSetterLikeSelector(Selector sel) { return false; if (str.empty()) return true; - return !islower(str.front()); + return !isLowercase(str.front()); } /// Check a message send to see if it's likely to cause a retain cycle. @@ -5625,21 +6235,59 @@ void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) { diagnoseRetainCycle(*this, Capturer, Owner); } -bool Sema::checkUnsafeAssigns(SourceLocation Loc, - QualType LHS, Expr *RHS) { - Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime(); - if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone) +static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc, + Expr *RHS, bool isProperty) { + // Check if RHS is an Objective-C object literal, which also can get + // immediately zapped in a weak reference. Note that we explicitly + // allow ObjCStringLiterals, since those are designed to never really die. + RHS = RHS->IgnoreParenImpCasts(); + + // This enum needs to match with the 'select' in + // warn_objc_arc_literal_assign (off-by-1). + Sema::ObjCLiteralKind Kind = S.CheckLiteralKind(RHS); + if (Kind == Sema::LK_String || Kind == Sema::LK_None) return false; - // strip off any implicit cast added to get to the one arc-specific + + S.Diag(Loc, diag::warn_arc_literal_assign) + << (unsigned) Kind + << (isProperty ? 0 : 1) + << RHS->getSourceRange(); + + return true; +} + +static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc, + Qualifiers::ObjCLifetime LT, + Expr *RHS, bool isProperty) { + // Strip off any implicit cast added to get to the one ARC-specific. while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) { if (cast->getCastKind() == CK_ARCConsumeObject) { - Diag(Loc, diag::warn_arc_retained_assign) - << (LT == Qualifiers::OCL_ExplicitNone) << 1 + S.Diag(Loc, diag::warn_arc_retained_assign) + << (LT == Qualifiers::OCL_ExplicitNone) + << (isProperty ? 0 : 1) << RHS->getSourceRange(); return true; } RHS = cast->getSubExpr(); } + + if (LT == Qualifiers::OCL_Weak && + checkUnsafeAssignLiteral(S, Loc, RHS, isProperty)) + return true; + + return false; +} + +bool Sema::checkUnsafeAssigns(SourceLocation Loc, + QualType LHS, Expr *RHS) { + Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime(); + + if (LT != Qualifiers::OCL_Weak && LT != Qualifiers::OCL_ExplicitNone) + return false; + + if (checkUnsafeAssignObject(*this, Loc, LT, RHS, false)) + return true; + return false; } @@ -5702,14 +6350,8 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, } } else if (Attributes & ObjCPropertyDecl::OBJC_PR_weak) { - while (ImplicitCastExpr *cast = dyn_cast<ImplicitCastExpr>(RHS)) { - if (cast->getCastKind() == CK_ARCConsumeObject) { - Diag(Loc, diag::warn_arc_retained_assign) - << 0 << 0<< RHS->getSourceRange(); - return; - } - RHS = cast->getSubExpr(); - } + if (checkUnsafeAssignObject(*this, Loc, Qualifiers::OCL_Weak, RHS, true)) + return; } } } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index b1aead8..2db1e2a 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -11,18 +11,19 @@ // //===----------------------------------------------------------------------===// #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/Basic/CharInfo.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Overload.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -45,7 +46,7 @@ namespace { /// 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 bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; typedef CodeCompletionResult Result; @@ -56,9 +57,9 @@ namespace { /// \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; + llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound; - typedef std::pair<NamedDecl *, unsigned> DeclIndexPair; + typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; /// \brief An entry in the shadow map, which is optimized to store /// a single (declaration, index) mapping (the common case) but @@ -68,7 +69,7 @@ namespace { /// \brief Contains either the solitary NamedDecl * or a vector /// of (declaration, index) pairs. - llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector; + llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector; /// \brief When the entry contains a single declaration, this is /// the index associated with that entry. @@ -77,7 +78,7 @@ namespace { public: ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { } - void Add(NamedDecl *ND, unsigned Index) { + void Add(const NamedDecl *ND, unsigned Index) { if (DeclOrVector.isNull()) { // 0 - > 1 elements: just set the single element information. DeclOrVector = ND; @@ -85,7 +86,8 @@ namespace { return; } - if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) { + if (const NamedDecl *PrevND = + DeclOrVector.dyn_cast<const NamedDecl *>()) { // 1 -> 2 elements: create the vector of results and push in the // existing declaration. DeclIndexPairVector *Vec = new DeclIndexPairVector; @@ -161,7 +163,7 @@ namespace { /// \brief If we are in an instance method definition, the \@implementation /// object. ObjCImplementationDecl *ObjCImplementation; - + void AdjustResultPriorityForDecl(Result &R); void MaybeAddConstructorResults(Result R); @@ -195,7 +197,10 @@ namespace { break; } } - + + /// \brief Determine the priority for a reference to the given declaration. + unsigned getBasePriority(const NamedDecl *D); + /// \brief Whether we should include code patterns in the completion /// results. bool includeCodePatterns() const { @@ -265,7 +270,8 @@ namespace { /// /// \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; + bool isInterestingDecl(const NamedDecl *ND, + bool &AsNestedNameSpecifier) const; /// \brief Check whether the result is hidden by the Hiding declaration. /// @@ -274,7 +280,7 @@ namespace { /// modified to describe how the result can be found (e.g., via extra /// qualification). bool CheckHiddenResult(Result &R, DeclContext *CurContext, - NamedDecl *Hiding); + const 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 @@ -309,7 +315,7 @@ namespace { void ExitScope(); /// \brief Ignore this declaration, if it is seen again. - void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } + void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } /// \name Name lookup predicates /// @@ -317,29 +323,29 @@ namespace { /// 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 IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const; - bool IsObjCCollection(NamedDecl *ND) const; - bool IsImpossibleToSatisfy(NamedDecl *ND) const; + bool IsOrdinaryName(const NamedDecl *ND) const; + bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; + bool IsIntegralConstantValue(const NamedDecl *ND) const; + bool IsOrdinaryNonValueName(const NamedDecl *ND) const; + bool IsNestedNameSpecifier(const NamedDecl *ND) const; + bool IsEnum(const NamedDecl *ND) const; + bool IsClassOrStruct(const NamedDecl *ND) const; + bool IsUnion(const NamedDecl *ND) const; + bool IsNamespace(const NamedDecl *ND) const; + bool IsNamespaceOrAlias(const NamedDecl *ND) const; + bool IsType(const NamedDecl *ND) const; + bool IsMember(const NamedDecl *ND) const; + bool IsObjCIvar(const NamedDecl *ND) const; + bool IsObjCMessageReceiver(const NamedDecl *ND) const; + bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; + bool IsObjCCollection(const NamedDecl *ND) const; + bool IsImpossibleToSatisfy(const NamedDecl *ND) const; //@} }; } class ResultBuilder::ShadowMapEntry::iterator { - llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator; + llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator; unsigned SingleDeclIndex; public: @@ -361,14 +367,14 @@ public: iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { } - iterator(NamedDecl *SingleDecl, unsigned Index) + iterator(const NamedDecl *SingleDecl, unsigned Index) : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { } iterator(const DeclIndexPair *Iterator) : DeclOrIterator(Iterator), SingleDeclIndex(0) { } iterator &operator++() { - if (DeclOrIterator.is<NamedDecl *>()) { + if (DeclOrIterator.is<const NamedDecl *>()) { DeclOrIterator = (NamedDecl *)0; SingleDeclIndex = 0; return *this; @@ -387,7 +393,7 @@ public: }*/ reference operator*() const { - if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>()) + if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>()) return reference(ND, SingleDeclIndex); return *DeclOrIterator.get<const DeclIndexPair*>(); @@ -413,7 +419,7 @@ ResultBuilder::ShadowMapEntry::begin() const { if (DeclOrVector.isNull()) return iterator(); - if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>()) + if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>()) return iterator(ND, SingleDeclIndex); return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin()); @@ -421,7 +427,7 @@ ResultBuilder::ShadowMapEntry::begin() const { ResultBuilder::ShadowMapEntry::iterator ResultBuilder::ShadowMapEntry::end() const { - if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull()) + if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull()) return iterator(); return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end()); @@ -442,11 +448,11 @@ ResultBuilder::ShadowMapEntry::end() const { /// NULL if no qualification is needed. static NestedNameSpecifier * getRequiredQualification(ASTContext &Context, - DeclContext *CurContext, - DeclContext *TargetContext) { - SmallVector<DeclContext *, 4> TargetParents; + const DeclContext *CurContext, + const DeclContext *TargetContext) { + SmallVector<const DeclContext *, 4> TargetParents; - for (DeclContext *CommonAncestor = TargetContext; + for (const DeclContext *CommonAncestor = TargetContext; CommonAncestor && !CommonAncestor->Encloses(CurContext); CommonAncestor = CommonAncestor->getLookupParent()) { if (CommonAncestor->isTransparentContext() || @@ -458,16 +464,16 @@ getRequiredQualification(ASTContext &Context, NestedNameSpecifier *Result = 0; while (!TargetParents.empty()) { - DeclContext *Parent = TargetParents.back(); + const DeclContext *Parent = TargetParents.back(); TargetParents.pop_back(); - if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) { + if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) { if (!Namespace->getIdentifier()) continue; Result = NestedNameSpecifier::Create(Context, Result, Namespace); } - else if (TagDecl *TD = dyn_cast<TagDecl>(Parent)) + else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent)) Result = NestedNameSpecifier::Create(Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); @@ -475,7 +481,7 @@ getRequiredQualification(ASTContext &Context, return Result; } -bool ResultBuilder::isInterestingDecl(NamedDecl *ND, +bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, bool &AsNestedNameSpecifier) const { AsNestedNameSpecifier = false; @@ -547,14 +553,15 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND, } bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, - NamedDecl *Hiding) { + const 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.getLangOpts().CPlusPlus) return true; - DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext(); + const DeclContext *HiddenCtx = + R.Declaration->getDeclContext()->getRedeclContext(); // There is no way to qualify a name declared in a function or method. if (HiddenCtx->isFunctionOrMethod()) @@ -645,26 +652,27 @@ SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { /// \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) { +QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); - if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND)) return C.getTypeDeclType(Type); - if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) + if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) return C.getObjCInterfaceType(Iface); QualType T; - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) T = Function->getCallResultType(); - else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) T = Method->getSendResultType(); - else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) + else if (const FunctionTemplateDecl *FunTmpl = + dyn_cast<FunctionTemplateDecl>(ND)) T = FunTmpl->getTemplatedDecl()->getCallResultType(); - else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); - else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) T = Property->getType(); - else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) + else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) T = Value->getType(); else return QualType(); @@ -703,11 +711,48 @@ QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) { return T; } +unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { + if (!ND) + return CCP_Unlikely; + + // Context-based decisions. + const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); + if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) { + // _cmd is relatively rare + if (const 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; + + // Use CCP_Type for type declarations unless we're in a statement, Objective-C + // message receiver, or parenthesized expression context. There, it's as + // likely that the user will want to write a type as other declarations. + if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) && + !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement || + CompletionContext.getKind() + == CodeCompletionContext::CCC_ObjCMessageReceiver || + CompletionContext.getKind() + == CodeCompletionContext::CCC_ParenthesizedExpression)) + return CCP_Type; + + return CCP_Declaration; +} + 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 (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) if (PreferredSelector == Method->getSelector()) R.Priority += CCD_SelectorMatch; @@ -735,9 +780,9 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) { return; ASTContext &Context = SemaRef.Context; - NamedDecl *D = R.Declaration; - CXXRecordDecl *Record = 0; - if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) + const NamedDecl *D = R.Declaration; + const CXXRecordDecl *Record = 0; + if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) Record = ClassTemplate->getTemplatedDecl(); else if ((Record = dyn_cast<CXXRecordDecl>(D))) { // Skip specializations and partial specializations. @@ -757,9 +802,11 @@ void ResultBuilder::MaybeAddConstructorResults(Result R) { 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; + DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName); + for (DeclContext::lookup_const_iterator I = Ctors.begin(), + E = Ctors.end(); + I != E; ++I) { + R.Declaration = *I; R.CursorKind = getCursorKindForDecl(R.Declaration); Results.push_back(R); } @@ -775,12 +822,16 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { } // Look through using declarations. - if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { - MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext); + if (const UsingShadowDecl *Using = + dyn_cast<UsingShadowDecl>(R.Declaration)) { + MaybeAddResult(Result(Using->getTargetDecl(), + getBasePriority(Using->getTargetDecl()), + R.Qualifier), + CurContext); return; } - Decl *CanonDecl = R.Declaration->getCanonicalDecl(); + const Decl *CanonDecl = R.Declaration->getCanonicalDecl(); unsigned IDNS = CanonDecl->getIdentifierNamespace(); bool AsNestedNameSpecifier = false; @@ -800,7 +851,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { } for (; I != IEnd; ++I) { - NamedDecl *ND = I->first; + const NamedDecl *ND = I->first; unsigned Index = I->second; if (ND->getCanonicalDecl() == CanonDecl) { // This is a redeclaration. Always pick the newer declaration. @@ -859,10 +910,10 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { // 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)) + const DeclContext *Ctx = R.Declaration->getDeclContext(); + if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); - else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) + else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else @@ -887,8 +938,11 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, } // Look through using declarations. - if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { - AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding); + if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { + AddResult(Result(Using->getTargetDecl(), + getBasePriority(Using->getTargetDecl()), + R.Qualifier), + CurContext, Hiding); return; } @@ -921,10 +975,10 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, // 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)) + const DeclContext *Ctx = R.Declaration->getDeclContext(); + if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); - else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) + else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); else @@ -938,7 +992,7 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, AdjustResultPriorityForDecl(R); if (HasObjectTypeQualifiers) - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) + if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) if (Method->isInstance()) { Qualifiers MethodQuals = Qualifiers::fromCVRMask(Method->getTypeQualifiers()); @@ -982,7 +1036,7 @@ void ResultBuilder::ExitScope() { /// \brief Determines whether this given declaration will be found by /// ordinary name lookup. -bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { +bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); unsigned IDNS = Decl::IDNS_Ordinary; @@ -998,7 +1052,7 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { /// \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 { +bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) return false; @@ -1014,11 +1068,11 @@ bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const { return ND->getIdentifierNamespace() & IDNS; } -bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const { +bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { if (!IsOrdinaryNonTypeName(ND)) return 0; - if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) + if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) if (VD->getType()->isIntegralOrEnumerationType()) return true; @@ -1027,7 +1081,7 @@ bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const { /// \brief Determines whether this given declaration will be found by /// ordinary name lookup. -bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const { +bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { ND = cast<NamedDecl>(ND->getUnderlyingDecl()); unsigned IDNS = Decl::IDNS_Ordinary; @@ -1041,27 +1095,27 @@ bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const { /// \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 { +bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const 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 { +bool ResultBuilder::IsEnum(const NamedDecl *ND) const { return isa<EnumDecl>(ND); } /// \brief Determines whether the given declaration is a class or struct. -bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const { +bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); // For purposes of this check, interfaces match too. - if (RecordDecl *RD = dyn_cast<RecordDecl>(ND)) + if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct || RD->getTagKind() == TTK_Interface; @@ -1070,31 +1124,31 @@ bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const { } /// \brief Determines whether the given declaration is a union. -bool ResultBuilder::IsUnion(NamedDecl *ND) const { +bool ResultBuilder::IsUnion(const NamedDecl *ND) const { // Allow us to find class templates, too. - if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) + if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); - if (RecordDecl *RD = dyn_cast<RecordDecl>(ND)) + if (const 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 { +bool ResultBuilder::IsNamespace(const 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 { +bool ResultBuilder::IsNamespaceOrAlias(const 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)) +bool ResultBuilder::IsType(const NamedDecl *ND) const { + if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) ND = Using->getTargetDecl(); return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); @@ -1103,8 +1157,8 @@ bool ResultBuilder::IsType(NamedDecl *ND) const { /// \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)) +bool ResultBuilder::IsMember(const NamedDecl *ND) const { + if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) ND = Using->getTargetDecl(); return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) || @@ -1144,7 +1198,7 @@ static bool isObjCReceiverType(ASTContext &C, QualType T) { return T->isDependentType() || T->isRecordType(); } -bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const { +bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { QualType T = getDeclUsageType(SemaRef.Context, ND); if (T.isNull()) return false; @@ -1153,18 +1207,18 @@ bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const { return isObjCReceiverType(SemaRef.Context, T); } -bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const { +bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const { if (IsObjCMessageReceiver(ND)) return true; - VarDecl *Var = dyn_cast<VarDecl>(ND); + const VarDecl *Var = dyn_cast<VarDecl>(ND); if (!Var) return false; return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>(); } -bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const { +bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const { if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) || (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND))) return false; @@ -1179,13 +1233,13 @@ bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const { (SemaRef.getLangOpts().CPlusPlus && T->isRecordType()); } -bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const { +bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const { return false; } /// \brief Determines whether the given declaration is an Objective-C /// instance variable. -bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const { +bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const { return isa<ObjCIvarDecl>(ND); } @@ -1206,7 +1260,8 @@ namespace { if (Ctx) Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx); - ResultBuilder::Result Result(ND, 0, false, Accessible); + ResultBuilder::Result Result(ND, Results.getBasePriority(ND), 0, false, + Accessible); Results.AddResult(Result, CurContext, Hiding, InBaseClass); } }; @@ -1256,7 +1311,7 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Builder.AddPlaceholderChunk("name"); Results.AddResult(Result(Builder.TakeString())); - if (LangOpts.CPlusPlus0x) { + if (LangOpts.CPlusPlus11) { Results.AddResult(Result("auto", CCP_Type)); Results.AddResult(Result("char16_t", CCP_Type)); Results.AddResult(Result("char32_t", CCP_Type)); @@ -1421,7 +1476,7 @@ static const char *GetCompletionTypeString(QualType T, // Anonymous tag types are constant strings. if (const TagType *TagT = dyn_cast<TagType>(T)) if (TagDecl *Tag = TagT->getDecl()) - if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { + if (!Tag->hasNameForLinkage()) { switch (Tag->getTagKind()) { case TTK_Struct: return "struct <anonymous>"; case TTK_Interface: return "__interface <anonymous>"; @@ -1906,7 +1961,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, // FIXME: Rethrow? - if (SemaRef.getLangOpts().CPlusPlus0x) { + if (SemaRef.getLangOpts().CPlusPlus11) { // nullptr Builder.AddResultTypeChunk("std::nullptr_t"); Builder.AddTypedTextChunk("nullptr"); @@ -1997,7 +2052,7 @@ static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, /// type chunk. static void AddResultTypeChunk(ASTContext &Context, const PrintingPolicy &Policy, - NamedDecl *ND, + const NamedDecl *ND, CodeCompletionBuilder &Result) { if (!ND) return; @@ -2009,19 +2064,20 @@ static void AddResultTypeChunk(ASTContext &Context, // Determine the type of the declaration (if it has a type). QualType T; - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) T = Function->getResultType(); - else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) T = Method->getResultType(); - else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) + else if (const FunctionTemplateDecl *FunTmpl = + dyn_cast<FunctionTemplateDecl>(ND)) T = FunTmpl->getTemplatedDecl()->getResultType(); - else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + else if (const 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)) { + } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) { T = Value->getType(); - } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) T = Property->getType(); if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) @@ -2031,7 +2087,8 @@ static void AddResultTypeChunk(ASTContext &Context, Result.getAllocator())); } -static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod, +static void MaybeAddSentinel(ASTContext &Context, + const NamedDecl *FunctionOrMethod, CodeCompletionBuilder &Result) { if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) if (Sentinel->getSentinel() == 0) { @@ -2064,7 +2121,7 @@ static std::string formatObjCParamQualifiers(unsigned ObjCQuals) { static std::string FormatFunctionParameter(ASTContext &Context, const PrintingPolicy &Policy, - ParmVarDecl *Param, + const ParmVarDecl *Param, bool SuppressName = false, bool SuppressBlock = false) { bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); @@ -2090,36 +2147,35 @@ static std::string FormatFunctionParameter(ASTContext &Context, // The argument for a block pointer parameter is a block literal with // the appropriate type. - FunctionTypeLoc *Block = 0; - FunctionProtoTypeLoc *BlockProto = 0; + FunctionTypeLoc Block; + FunctionProtoTypeLoc BlockProto; TypeLoc TL; if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) { TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); while (true) { // Look through typedefs. if (!SuppressBlock) { - if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) { - if (TypeSourceInfo *InnerTSInfo - = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) { + if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) { + 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(); + if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { + 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); + if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) { + TL = BlockPtr.getPointeeLoc().IgnoreParens(); + Block = TL.getAs<FunctionTypeLoc>(); + BlockProto = TL.getAs<FunctionProtoTypeLoc>(); } break; } @@ -2147,27 +2203,27 @@ static std::string FormatFunctionParameter(ASTContext &Context, // 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(); + QualType ResultType = Block.getTypePtr()->getResultType(); if (!ResultType->isVoidType() || SuppressBlock) ResultType.getAsStringInternal(Result, Policy); // Format the parameter list. std::string Params; - if (!BlockProto || Block->getNumArgs() == 0) { - if (BlockProto && BlockProto->getTypePtr()->isVariadic()) + if (!BlockProto || Block.getNumArgs() == 0) { + if (BlockProto && BlockProto.getTypePtr()->isVariadic()) Params = "(...)"; else Params = "(void)"; } else { Params += "("; - for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) { + for (unsigned I = 0, N = Block.getNumArgs(); I != N; ++I) { if (I) Params += ", "; - Params += FormatFunctionParameter(Context, Policy, Block->getArg(I), + Params += FormatFunctionParameter(Context, Policy, Block.getArg(I), /*SuppressName=*/false, /*SuppressBlock=*/true); - if (I == N - 1 && BlockProto->getTypePtr()->isVariadic()) + if (I == N - 1 && BlockProto.getTypePtr()->isVariadic()) Params += ", ..."; } Params += ")"; @@ -2195,14 +2251,14 @@ static std::string FormatFunctionParameter(ASTContext &Context, /// \brief Add function parameter chunks to the given code completion string. static void AddFunctionParameterChunks(ASTContext &Context, const PrintingPolicy &Policy, - FunctionDecl *Function, + const FunctionDecl *Function, CodeCompletionBuilder &Result, unsigned Start = 0, bool InOptional = false) { bool FirstParameter = true; for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { - ParmVarDecl *Param = Function->getParamDecl(P); + const ParmVarDecl *Param = Function->getParamDecl(P); if (Param->hasDefaultArg() && !InOptional) { // When we see an optional default argument, put that argument and @@ -2248,7 +2304,7 @@ static void AddFunctionParameterChunks(ASTContext &Context, /// \brief Add template parameter chunks to the given code completion string. static void AddTemplateParameterChunks(ASTContext &Context, const PrintingPolicy &Policy, - TemplateDecl *Template, + const TemplateDecl *Template, CodeCompletionBuilder &Result, unsigned MaxParameters = 0, unsigned Start = 0, @@ -2346,7 +2402,7 @@ AddQualifierToCompletionString(CodeCompletionBuilder &Result, static void AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, - FunctionDecl *Function) { + const FunctionDecl *Function) { const FunctionProtoType *Proto = Function->getType()->getAs<FunctionProtoType>(); if (!Proto || !Proto->getTypeQuals()) @@ -2383,7 +2439,8 @@ AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, /// \brief Add the name of the given declaration static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, - NamedDecl *ND, CodeCompletionBuilder &Result) { + const NamedDecl *ND, + CodeCompletionBuilder &Result) { DeclarationName Name = ND->getDeclName(); if (!Name) return; @@ -2484,6 +2541,27 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (Declaration) { Result.addParentContext(Declaration->getDeclContext()); Pattern->ParentName = Result.getParentName(); + // Provide code completion comment for self.GetterName where + // GetterName is the getter method for a property with name + // different from the property name (declared via a property + // getter attribute. + const NamedDecl *ND = Declaration; + if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND)) + if (M->isPropertyAccessor()) + if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl()) + if (PDecl->getGetterName() == M->getSelector() && + PDecl->getIdentifier() != M->getIdentifier()) { + if (const RawComment *RC = + Ctx.getRawCommentForAnyRedecl(M)) { + Result.addBriefComment(RC->getBriefText(Ctx)); + Pattern->BriefComment = Result.getBriefComment(); + } + else if (const RawComment *RC = + Ctx.getRawCommentForAnyRedecl(PDecl)) { + Result.addBriefComment(RC->getBriefText(Ctx)); + Pattern->BriefComment = Result.getBriefComment(); + } + } } return Pattern; @@ -2495,8 +2573,9 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } if (Kind == RK_Macro) { - MacroInfo *MI = PP.getMacroInfoHistory(Macro); - assert(MI && "Not a macro?"); + const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro); + assert(MD && "Not a macro?"); + const MacroInfo *MI = MD->getMacroInfo(); Result.AddTypedTextChunk( Result.getAllocator().CopyString(Macro->getName())); @@ -2540,14 +2619,19 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } assert(Kind == RK_Declaration && "Missed a result kind?"); - NamedDecl *ND = Declaration; + const NamedDecl *ND = Declaration; Result.addParentContext(ND->getDeclContext()); if (IncludeBriefComments) { // Add documentation comment, if it exists. if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) { Result.addBriefComment(RC->getBriefText(Ctx)); - } + } + else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) + if (OMD->isPropertyAccessor()) + if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl()) + if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl)) + Result.addBriefComment(RC->getBriefText(Ctx)); } if (StartsNestedNameSpecifier) { @@ -2565,7 +2649,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, AddResultTypeChunk(Ctx, Policy, ND, Result); - if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); AddTypedNameChunk(Ctx, Policy, ND, Result); @@ -2576,7 +2660,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { + if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); FunctionDecl *Function = FunTmpl->getTemplatedDecl(); @@ -2630,7 +2714,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } - if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { + if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, Ctx, Policy); Result.AddTypedTextChunk( @@ -2641,7 +2725,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, return Result.TakeString(); } - if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { + if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { Selector Sel = Method->getSelector(); if (Sel.isUnarySelector()) { Result.AddTypedTextChunk(Result.getAllocator().CopyString( @@ -2662,8 +2746,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, Result.AddTypedTextChunk(""); } unsigned Idx = 0; - for (ObjCMethodDecl::param_iterator P = Method->param_begin(), - PEnd = Method->param_end(); + for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), + PEnd = Method->param_end(); P != PEnd; (void)++P, ++Idx) { if (Idx > 0) { std::string Keyword; @@ -2827,7 +2911,7 @@ unsigned clang::getMacroUsagePriority(StringRef MacroName, return Priority; } -CXCursorKind clang::getCursorKindForDecl(Decl *D) { +CXCursorKind clang::getCursorKindForDecl(const Decl *D) { if (!D) return CXCursor_UnexposedDecl; @@ -2887,7 +2971,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { return CXCursor_ModuleImportDecl; default: - if (TagDecl *TD = dyn_cast<TagDecl>(D)) { + if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { switch (TD->getTagKind()) { case TTK_Interface: // fall through case TTK_Struct: return CXCursor_StructDecl; @@ -2930,7 +3014,7 @@ static void AddPrettyFunctionResults(const LangOptions &LangOpts, Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant)); Results.AddResult(Result("__FUNCTION__", CCP_Constant)); - if (LangOpts.C99 || LangOpts.CPlusPlus0x) + if (LangOpts.C99 || LangOpts.CPlusPlus11) Results.AddResult(Result("__func__", CCP_Constant)); Results.ExitScope(); } @@ -3036,7 +3120,7 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, M != MEnd; ++M) { CodeCompletionBuilder Builder(Results.getAllocator(), Results.getCodeCompletionTUInfo()); - CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M); + const CXXMethodDecl *Overridden = *M; if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) continue; @@ -3092,7 +3176,7 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, typedef CodeCompletionResult Result; if (Path.empty()) { // Enumerate all top-level modules. - llvm::SmallVector<Module *, 8> Modules; + SmallVector<Module *, 8> Modules; PP.getHeaderSearchInfo().collectAllModules(Modules); for (unsigned I = 0, N = Modules.size(); I != N; ++I) { Builder.AddTypedTextChunk( @@ -3265,7 +3349,7 @@ void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, // the initial opening bracket '[' missing. Add appropriate completions. if (AllowNonIdentifiers && !AllowNestedNameSpecifiers && DS.getTypeSpecType() == DeclSpec::TST_typename && - DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified && + DS.getStorageClassSpec() == DeclSpec::SCS_unspecified && !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() && DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && @@ -3395,7 +3479,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container, P != PEnd; ++P) { if (AddedProperties.insert(P->getIdentifier())) - Results.MaybeAddResult(Result(*P, 0), CurContext); + Results.MaybeAddResult(Result(*P, Results.getBasePriority(*P), 0), + CurContext); } // Add nullary methods @@ -3432,9 +3517,11 @@ static void AddObjCProperties(ObjCContainerDecl *Container, } 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, + for (ObjCInterfaceDecl::known_categories_iterator + Cat = IFace->known_categories_begin(), + CatEnd = IFace->known_categories_end(); + Cat != CatEnd; ++Cat) + AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods, CurContext, AddedProperties, Results); } @@ -3642,6 +3729,9 @@ void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { if (getLangOpts().C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) Results.AddResult("restrict"); + if (getLangOpts().C11 && + !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic)) + Results.AddResult("_Atomic"); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), @@ -3724,8 +3814,7 @@ void Sema::CodeCompleteCase(Scope *S) { if (EnumeratorsSeen.count(*E)) continue; - CodeCompletionResult R(*E, Qualifier); - R.Priority = CCP_EnumInCase; + CodeCompletionResult R(*E, CCP_EnumInCase, Qualifier); Results.AddResult(R, CurContext, 0, false); } Results.ExitScope(); @@ -4094,7 +4183,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end(); NS != NSEnd; ++NS) - Results.AddResult(CodeCompletionResult(NS->second, 0), + Results.AddResult(CodeCompletionResult( + NS->second, Results.getBasePriority(NS->second), 0), CurContext, 0, false); Results.ExitScope(); } @@ -4308,7 +4398,8 @@ void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, continue; if (Known.insert(Var->getIdentifier())) - Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false); + Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration), + CurContext, 0, false); } } @@ -4410,6 +4501,14 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); Builder.AddPlaceholderChunk("class"); Results.AddResult(Result(Builder.TakeString())); + + if (Results.getSema().getLangOpts().Modules) { + // @import name + Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import")); + Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); + Builder.AddPlaceholderChunk("module"); + Results.AddResult(Result(Builder.TakeString())); + } } void Sema::CodeCompleteObjCAtDirective(Scope *S) { @@ -4757,10 +4856,15 @@ static void AddObjCMethods(ObjCContainerDecl *Container, bool InOriginalClass = true) { typedef CodeCompletionResult Result; Container = getContainerDef(Container); + ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); + bool isRootClass = IFace && !IFace->getSuperClass(); for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), MEnd = Container->meth_end(); M != MEnd; ++M) { - if (M->isInstanceMethod() == WantInstanceMethods) { + // The instance methods on the root class can be messaged via the + // metaclass. + if (M->isInstanceMethod() == WantInstanceMethods || + (isRootClass && !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, @@ -4770,7 +4874,7 @@ static void AddObjCMethods(ObjCContainerDecl *Container, if (!Selectors.insert(M->getSelector())) continue; - Result R = Result(*M, 0); + Result R = Result(*M, Results.getBasePriority(*M), 0); R.StartParameter = NumSelIdents; R.AllParametersAreInformative = (WantKind != MK_Any); if (!InOriginalClass) @@ -4793,7 +4897,6 @@ static void AddObjCMethods(ObjCContainerDecl *Container, } } - ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); if (!IFace || !IFace->hasDefinition()) return; @@ -4805,9 +4908,13 @@ static void AddObjCMethods(ObjCContainerDecl *Container, CurContext, Selectors, AllowSameLength, Results, false); // Add methods in categories. - for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl; - CatDecl = CatDecl->getNextClassCategory()) { - AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, + for (ObjCInterfaceDecl::known_categories_iterator + Cat = IFace->known_categories_begin(), + CatEnd = IFace->known_categories_end(); + Cat != CatEnd; ++Cat) { + ObjCCategoryDecl *CatDecl = *Cat; + + AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, CurContext, Selectors, AllowSameLength, Results, InOriginalClass); @@ -4946,6 +5053,11 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, Builder.AddTextChunk("sender"); Results.AddResult(CodeCompletionResult(Builder.TakeString())); } + + // If we're completing the return type, provide 'instancetype'. + if (!IsParameter) { + Results.AddResult(CodeCompletionResult("instancetype")); + } // Add various builtin type names and specifiers. AddOrdinaryNameResults(PCC_Type, S, *this, Results); @@ -5075,11 +5187,14 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, // Check in categories or class extensions. if (!SuperMethod) { - for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category; - Category = Category->getNextClassCategory()) - if ((SuperMethod = Category->getMethod(CurMethod->getSelector(), + for (ObjCInterfaceDecl::known_categories_iterator + Cat = Class->known_categories_begin(), + CatEnd = Class->known_categories_end(); + Cat != CatEnd; ++Cat) { + if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(), CurMethod->isInstanceMethod()))) break; + } } } @@ -5163,7 +5278,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_ObjCMessageReceiver, - getLangOpts().CPlusPlus0x + getLangOpts().CPlusPlus11 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture : &ResultBuilder::IsObjCMessageReceiver); @@ -5182,7 +5297,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results); } - if (getLangOpts().CPlusPlus0x) + if (getLangOpts().CPlusPlus11) addThisCompletion(*this, Results); Results.ExitScope(); @@ -5224,7 +5339,7 @@ void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, } else { // "super" may be the name of a type or variable. Figure out which // it is. - IdentifierInfo *Super = &Context.Idents.get("super"); + IdentifierInfo *Super = getSuperIdentifier(); NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName); if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) { @@ -5274,7 +5389,7 @@ static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, if (R.Kind == Result::RK_Declaration && isa<ObjCMethodDecl>(R.Declaration)) { if (R.Priority <= BestPriority) { - ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration); + const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration); if (NumSelIdents <= Method->param_size()) { QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1] ->getType(); @@ -5362,7 +5477,7 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, NumSelIdents)) continue; - Result R(MethList->Method, 0); + Result R(MethList->Method, Results.getBasePriority(MethList->Method),0); R.StartParameter = NumSelIdents; R.AllParametersAreInformative = false; Results.MaybeAddResult(R, SemaRef.CurContext); @@ -5538,7 +5653,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, if (!Selectors.insert(MethList->Method->getSelector())) continue; - Result R(MethList->Method, 0); + Result R(MethList->Method, Results.getBasePriority(MethList->Method),0); R.StartParameter = NumSelIdents; R.AllParametersAreInformative = false; Results.MaybeAddResult(R, CurContext); @@ -5656,7 +5771,8 @@ static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, // Record any protocols we find. if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D)) if (!OnlyForwardDeclarations || !Proto->hasDefinition()) - Results.AddResult(Result(Proto, 0), CurContext, 0, false); + Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0), + CurContext, 0, false); } } @@ -5724,7 +5840,8 @@ static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && (!OnlyUnimplemented || !Class->getImplementation())) - Results.AddResult(Result(Class, 0), CurContext, 0, false); + Results.AddResult(Result(Class, Results.getBasePriority(Class), 0), + CurContext, 0, false); } } @@ -5806,11 +5923,15 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, 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()); - + if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){ + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = Class->visible_categories_begin(), + CatEnd = Class->visible_categories_end(); + Cat != CatEnd; ++Cat) { + CategoryNames.insert(Cat->getIdentifier()); + } + } + // Add all of the categories we know about. Results.EnterNewScope(); TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); @@ -5819,7 +5940,8 @@ void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, D != DEnd; ++D) if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D)) if (CategoryNames.insert(Category->getIdentifier())) - Results.AddResult(Result(Category, 0), CurContext, 0, false); + Results.AddResult(Result(Category, Results.getBasePriority(Category),0), + CurContext, 0, false); Results.ExitScope(); HandleCodeCompleteResults(this, CodeCompleter, @@ -5852,11 +5974,15 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, 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); + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = Class->visible_categories_begin(), + CatEnd = Class->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if ((!IgnoreImplemented || !Cat->getImplementation()) && + CategoryNames.insert(Cat->getIdentifier())) + Results.AddResult(Result(*Cat, Results.getBasePriority(*Cat), 0), + CurContext, 0, false); + } Class = Class->getSuperClass(); IgnoreImplemented = false; @@ -5956,7 +6082,8 @@ void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, 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); + Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), 0), + CurContext, 0, false); // Determine whether we've seen an ivar with a name similar to the // property. @@ -6032,12 +6159,14 @@ static void FindImplementableMethods(ASTContext &Context, 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, + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IFace->visible_categories_begin(), + CatEnd = IFace->visible_categories_end(); + Cat != CatEnd; ++Cat) { + FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType, KnownMethods, false); - + } + // Visit the superclass. if (IFace->getSuperClass()) FindImplementableMethods(Context, IFace->getSuperClass(), @@ -6167,7 +6296,7 @@ static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, // The uppercased name of the property name. std::string UpperKey = PropName->getName(); if (!UpperKey.empty()) - UpperKey[0] = toupper(UpperKey[0]); + UpperKey[0] = toUppercase(UpperKey[0]); bool ReturnTypeMatchesProperty = ReturnType.isNull() || Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), @@ -6897,9 +7026,12 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, IFace = Category->getClassInterface(); if (IFace) { - for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category; - Category = Category->getNextClassCategory()) - Containers.push_back(Category); + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IFace->visible_categories_begin(), + CatEnd = IFace->visible_categories_end(); + Cat != CatEnd; ++Cat) { + Containers.push_back(*Cat); + } } for (unsigned I = 0, N = Containers.size(); I != N; ++I) { @@ -6975,7 +7107,7 @@ void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, continue; } - Result R(MethList->Method, 0); + Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0); R.StartParameter = NumSelIdents; R.AllParametersAreInformative = false; R.DeclaringEntity = true; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0092d5d..adf3505 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -12,15 +12,11 @@ //===----------------------------------------------------------------------===// #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/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/CommentDiagnostic.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -28,18 +24,21 @@ #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/Sema/DelayedDiagnostic.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 "clang/Lex/ModuleLoader.h" +#include "clang/Lex/HeaderSearch.h" // FIXME: Sema shouldn't depend on Lex +#include "clang/Lex/ModuleLoader.h" // FIXME: Sema shouldn't depend on Lex +#include "clang/Lex/Preprocessor.h" // FIXME: Sema shouldn't depend on Lex +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/DelayedDiagnostic.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Triple.h" #include <algorithm> @@ -677,9 +676,9 @@ Corrected: (isa<TypeDecl>(UnderlyingFirstDecl) || isa<ObjCInterfaceDecl>(UnderlyingFirstDecl) || isa<ObjCCompatibleAliasDecl>(UnderlyingFirstDecl))) { - UnqualifiedDiag = diag::err_unknown_typename_suggest; - QualifiedDiag = diag::err_unknown_nested_typename_suggest; - } + UnqualifiedDiag = diag::err_unknown_typename_suggest; + QualifiedDiag = diag::err_unknown_nested_typename_suggest; + } if (SS.isEmpty()) Diag(NameLoc, UnqualifiedDiag) @@ -1097,7 +1096,7 @@ void Sema::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { bool Sema::isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S, bool ExplicitInstantiationOrSpecialization) { - return IdResolver.isDeclInScope(D, Ctx, Context, S, + return IdResolver.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization); } @@ -1175,6 +1174,31 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { return false; } +// We need this to handle +// +// typedef struct { +// void *foo() { return 0; } +// } A; +// +// When we see foo we don't know if after the typedef we will get 'A' or '*A' +// for example. If 'A', foo will have external linkage. If we have '*A', +// foo will have no linkage. Since we can't know untill we get to the end +// of the typedef, this function finds out if D might have non external linkage. +// Callers should verify at the end of the TU if it D has external linkage or +// not. +bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) { + const DeclContext *DC = D->getDeclContext(); + while (!DC->isTranslationUnit()) { + if (const RecordDecl *RD = dyn_cast<RecordDecl>(DC)){ + if (!RD->hasNameForLinkage()) + return true; + } + DC = DC->getParent(); + } + + return !D->hasExternalLinkage(); +} + bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { assert(D); @@ -1224,10 +1248,7 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { } // Only warn for unused decls internal to the translation unit. - if (D->getLinkage() == ExternalLinkage) - return false; - - return true; + return mightHaveNonExternalLinkage(D); } void Sema::MarkUnusedFileScopedDecl(const DeclaratorDecl *D) { @@ -1368,7 +1389,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { if (!D->getDeclName()) continue; // Diagnose unused variables in this scope. - if (!S->hasErrorOccurred()) + if (!S->hasUnrecoverableErrorOccurred()) DiagnoseUnusedDecl(D); // If this was a forward reference to a label, verify it was defined. @@ -1465,6 +1486,24 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { return S; } +/// \brief Looks up the declaration of "struct objc_super" and +/// saves it for later use in building builtin declaration of +/// objc_msgSendSuper and objc_msgSendSuper_stret. If no such +/// pre-existing declaration exists no action takes place. +static void LookupPredefedObjCSuperType(Sema &ThisSema, Scope *S, + IdentifierInfo *II) { + if (!II->isStr("objc_msgSendSuper")) + return; + ASTContext &Context = ThisSema.Context; + + LookupResult Result(ThisSema, &Context.Idents.get("objc_super"), + SourceLocation(), Sema::LookupTagName); + ThisSema.LookupName(Result, S); + if (Result.getResultKind() == LookupResult::Found) + if (const TagDecl *TD = Result.getAsSingle<TagDecl>()) + Context.setObjCSuperType(Context.getTagDeclType(TD)); +} + /// 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 @@ -1472,6 +1511,8 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) { NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S, bool ForRedeclaration, SourceLocation Loc) { + LookupPredefedObjCSuperType(*this, S, II); + Builtin::ID BID = (Builtin::ID)bid; ASTContext::GetBuiltinTypeError Error; @@ -1516,7 +1557,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Context.getTranslationUnitDecl(), Loc, Loc, II, R, /*TInfo=*/0, SC_Extern, - SC_None, false, + false, /*hasPrototype=*/true); New->setImplicit(); @@ -1529,7 +1570,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, ParmVarDecl::Create(Context, New, SourceLocation(), SourceLocation(), 0, FT->getArgType(i), /*TInfo=*/0, - SC_None, SC_None, 0); + SC_None, 0); parm->setScopeInfo(0, i); Params.push_back(parm); } @@ -1549,6 +1590,49 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } +/// \brief Filter out any previous declarations that the given declaration +/// should not consider because they are not permitted to conflict, e.g., +/// because they come from hidden sub-modules and do not refer to the same +/// entity. +static void filterNonConflictingPreviousDecls(ASTContext &context, + NamedDecl *decl, + LookupResult &previous){ + // This is only interesting when modules are enabled. + if (!context.getLangOpts().Modules) + return; + + // Empty sets are uninteresting. + if (previous.empty()) + return; + + LookupResult::Filter filter = previous.makeFilter(); + while (filter.hasNext()) { + NamedDecl *old = filter.next(); + + // Non-hidden declarations are never ignored. + if (!old->isHidden()) + continue; + + // If either has no-external linkage, ignore the old declaration. + // If this declaration would have external linkage if it were the first + // declaration of this name, then it may in fact be a redeclaration of + // some hidden declaration, so include those too. We don't need to worry + // about some previous visible declaration giving this declaration external + // linkage, because in that case, we'll mark this declaration as a redecl + // of the visible decl, and that decl will already be a redecl of the + // hidden declaration if that's appropriate. + // + // Don't cache this linkage computation, because it's not yet correct: we + // may later give this declaration a previous declaration which changes + // its linkage. + if (old->getLinkage() != ExternalLinkage || + !decl->hasExternalLinkageUncached()) + filter.erase(); + } + + filter.done(); +} + bool Sema::isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New) { QualType OldType; if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(Old)) @@ -1769,26 +1853,164 @@ DeclHasAttr(const Decl *D, const Attr *A) { return false; } -bool Sema::mergeDeclAttribute(Decl *D, InheritableAttr *Attr) { +static bool isAttributeTargetADefinition(Decl *D) { + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + return VD->isThisDeclarationADefinition(); + if (TagDecl *TD = dyn_cast<TagDecl>(D)) + return TD->isCompleteDefinition() || TD->isBeingDefined(); + return true; +} + +/// Merge alignment attributes from \p Old to \p New, taking into account the +/// special semantics of C11's _Alignas specifier and C++11's alignas attribute. +/// +/// \return \c true if any attributes were added to \p New. +static bool mergeAlignedAttrs(Sema &S, NamedDecl *New, Decl *Old) { + // Look for alignas attributes on Old, and pick out whichever attribute + // specifies the strictest alignment requirement. + AlignedAttr *OldAlignasAttr = 0; + AlignedAttr *OldStrictestAlignAttr = 0; + unsigned OldAlign = 0; + for (specific_attr_iterator<AlignedAttr> + I = Old->specific_attr_begin<AlignedAttr>(), + E = Old->specific_attr_end<AlignedAttr>(); I != E; ++I) { + // FIXME: We have no way of representing inherited dependent alignments + // in a case like: + // template<int A, int B> struct alignas(A) X; + // template<int A, int B> struct alignas(B) X {}; + // For now, we just ignore any alignas attributes which are not on the + // definition in such a case. + if (I->isAlignmentDependent()) + return false; + + if (I->isAlignas()) + OldAlignasAttr = *I; + + unsigned Align = I->getAlignment(S.Context); + if (Align > OldAlign) { + OldAlign = Align; + OldStrictestAlignAttr = *I; + } + } + + // Look for alignas attributes on New. + AlignedAttr *NewAlignasAttr = 0; + unsigned NewAlign = 0; + for (specific_attr_iterator<AlignedAttr> + I = New->specific_attr_begin<AlignedAttr>(), + E = New->specific_attr_end<AlignedAttr>(); I != E; ++I) { + if (I->isAlignmentDependent()) + return false; + + if (I->isAlignas()) + NewAlignasAttr = *I; + + unsigned Align = I->getAlignment(S.Context); + if (Align > NewAlign) + NewAlign = Align; + } + + if (OldAlignasAttr && NewAlignasAttr && OldAlign != NewAlign) { + // Both declarations have 'alignas' attributes. We require them to match. + // C++11 [dcl.align]p6 and C11 6.7.5/7 both come close to saying this, but + // fall short. (If two declarations both have alignas, they must both match + // every definition, and so must match each other if there is a definition.) + + // If either declaration only contains 'alignas(0)' specifiers, then it + // specifies the natural alignment for the type. + if (OldAlign == 0 || NewAlign == 0) { + QualType Ty; + if (ValueDecl *VD = dyn_cast<ValueDecl>(New)) + Ty = VD->getType(); + else + Ty = S.Context.getTagDeclType(cast<TagDecl>(New)); + + if (OldAlign == 0) + OldAlign = S.Context.getTypeAlign(Ty); + if (NewAlign == 0) + NewAlign = S.Context.getTypeAlign(Ty); + } + + if (OldAlign != NewAlign) { + S.Diag(NewAlignasAttr->getLocation(), diag::err_alignas_mismatch) + << (unsigned)S.Context.toCharUnitsFromBits(OldAlign).getQuantity() + << (unsigned)S.Context.toCharUnitsFromBits(NewAlign).getQuantity(); + S.Diag(OldAlignasAttr->getLocation(), diag::note_previous_declaration); + } + } + + if (OldAlignasAttr && !NewAlignasAttr && isAttributeTargetADefinition(New)) { + // C++11 [dcl.align]p6: + // if any declaration of an entity has an alignment-specifier, + // every defining declaration of that entity shall specify an + // equivalent alignment. + // C11 6.7.5/7: + // If the definition of an object does not have an alignment + // specifier, any other declaration of that object shall also + // have no alignment specifier. + S.Diag(New->getLocation(), diag::err_alignas_missing_on_definition) + << OldAlignasAttr->isC11(); + S.Diag(OldAlignasAttr->getLocation(), diag::note_alignas_on_declaration) + << OldAlignasAttr->isC11(); + } + + bool AnyAdded = false; + + // Ensure we have an attribute representing the strictest alignment. + if (OldAlign > NewAlign) { + AlignedAttr *Clone = OldStrictestAlignAttr->clone(S.Context); + Clone->setInherited(true); + New->addAttr(Clone); + AnyAdded = true; + } + + // Ensure we have an alignas attribute if the old declaration had one. + if (OldAlignasAttr && !NewAlignasAttr && + !(AnyAdded && OldStrictestAlignAttr->isAlignas())) { + AlignedAttr *Clone = OldAlignasAttr->clone(S.Context); + Clone->setInherited(true); + New->addAttr(Clone); + AnyAdded = true; + } + + return AnyAdded; +} + +static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *Attr, + bool Override) { InheritableAttr *NewAttr = NULL; + unsigned AttrSpellingListIndex = Attr->getSpellingListIndex(); if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr)) - NewAttr = mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), - AA->getIntroduced(), AA->getDeprecated(), - AA->getObsoleted(), AA->getUnavailable(), - AA->getMessage()); + NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), + AA->getIntroduced(), AA->getDeprecated(), + AA->getObsoleted(), AA->getUnavailable(), + AA->getMessage(), Override, + AttrSpellingListIndex); else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr)) - NewAttr = mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility()); + NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(), + AttrSpellingListIndex); + else if (TypeVisibilityAttr *VA = dyn_cast<TypeVisibilityAttr>(Attr)) + NewAttr = S.mergeTypeVisibilityAttr(D, VA->getRange(), VA->getVisibility(), + AttrSpellingListIndex); else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr)) - NewAttr = mergeDLLImportAttr(D, ImportA->getRange()); + NewAttr = S.mergeDLLImportAttr(D, ImportA->getRange(), + AttrSpellingListIndex); else if (DLLExportAttr *ExportA = dyn_cast<DLLExportAttr>(Attr)) - NewAttr = mergeDLLExportAttr(D, ExportA->getRange()); + NewAttr = S.mergeDLLExportAttr(D, ExportA->getRange(), + AttrSpellingListIndex); else if (FormatAttr *FA = dyn_cast<FormatAttr>(Attr)) - NewAttr = mergeFormatAttr(D, FA->getRange(), FA->getType(), - FA->getFormatIdx(), FA->getFirstArg()); + NewAttr = S.mergeFormatAttr(D, FA->getRange(), FA->getType(), + FA->getFormatIdx(), FA->getFirstArg(), + AttrSpellingListIndex); else if (SectionAttr *SA = dyn_cast<SectionAttr>(Attr)) - NewAttr = mergeSectionAttr(D, SA->getRange(), SA->getName()); + NewAttr = S.mergeSectionAttr(D, SA->getRange(), SA->getName(), + AttrSpellingListIndex); + else if (isa<AlignedAttr>(Attr)) + // AlignedAttrs are handled separately, because we need to handle all + // such attributes on a declaration at the same time. + NewAttr = 0; else if (!DeclHasAttr(D, Attr)) - NewAttr = cast<InheritableAttr>(Attr->clone(Context)); + NewAttr = cast<InheritableAttr>(Attr->clone(S.Context)); if (NewAttr) { NewAttr->setInherited(true); @@ -1839,6 +2061,31 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { ++I; continue; // regular attr merging will take care of validating this. } + + if (isa<C11NoReturnAttr>(NewAttribute)) { + // C's _Noreturn is allowed to be added to a function after it is defined. + ++I; + continue; + } else if (const AlignedAttr *AA = dyn_cast<AlignedAttr>(NewAttribute)) { + if (AA->isAlignas()) { + // C++11 [dcl.align]p6: + // if any declaration of an entity has an alignment-specifier, + // every defining declaration of that entity shall specify an + // equivalent alignment. + // C11 6.7.5/7: + // If the definition of an object does not have an alignment + // specifier, any other declaration of that object shall also + // have no alignment specifier. + S.Diag(Def->getLocation(), diag::err_alignas_missing_on_definition) + << AA->isC11(); + S.Diag(NewAttribute->getLocation(), diag::note_alignas_on_declaration) + << AA->isC11(); + NewAttributes.erase(NewAttributes.begin() + I); + --E; + continue; + } + } + S.Diag(NewAttribute->getLocation(), diag::warn_attribute_precede_definition); S.Diag(Def->getLocation(), diag::note_previous_definition); @@ -1848,8 +2095,11 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { } /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. -void Sema::mergeDeclAttributes(Decl *New, Decl *Old, - bool MergeDeprecation) { +void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, + AvailabilityMergeKind AMK) { + if (!Old->hasAttrs() && !New->hasAttrs()) + return; + // attributes declared post-definition are currently ignored checkNewAttributesAfterDef(*this, New, Old); @@ -1866,17 +2116,31 @@ void Sema::mergeDeclAttributes(Decl *New, Decl *Old, i = Old->specific_attr_begin<InheritableAttr>(), e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) { + bool Override = false; // Ignore deprecated/unavailable/availability attributes if requested. - if (!MergeDeprecation && - (isa<DeprecatedAttr>(*i) || - isa<UnavailableAttr>(*i) || - isa<AvailabilityAttr>(*i))) - continue; + if (isa<DeprecatedAttr>(*i) || + isa<UnavailableAttr>(*i) || + isa<AvailabilityAttr>(*i)) { + switch (AMK) { + case AMK_None: + continue; - if (mergeDeclAttribute(New, *i)) + case AMK_Redeclaration: + break; + + case AMK_Override: + Override = true; + break; + } + } + + if (mergeDeclAttribute(*this, New, *i, Override)) foundAny = true; } + if (mergeAlignedAttrs(*this, New, Old)) + foundAny = true; + if (!foundAny) New->dropAttrs(); } @@ -1884,7 +2148,25 @@ void Sema::mergeDeclAttributes(Decl *New, Decl *Old, /// to the new one. static void mergeParamDeclAttributes(ParmVarDecl *newDecl, const ParmVarDecl *oldDecl, - ASTContext &C) { + Sema &S) { + // C++11 [dcl.attr.depend]p2: + // The first declaration of a function shall specify the + // carries_dependency attribute for its declarator-id if any declaration + // of the function specifies the carries_dependency attribute. + if (newDecl->hasAttr<CarriesDependencyAttr>() && + !oldDecl->hasAttr<CarriesDependencyAttr>()) { + S.Diag(newDecl->getAttr<CarriesDependencyAttr>()->getLocation(), + diag::err_carries_dependency_missing_on_first_decl) << 1/*Param*/; + // Find the first declaration of the parameter. + // FIXME: Should we build redeclaration chains for function parameters? + const FunctionDecl *FirstFD = + cast<FunctionDecl>(oldDecl->getDeclContext())->getFirstDeclaration(); + const ParmVarDecl *FirstVD = + FirstFD->getParamDecl(oldDecl->getFunctionScopeIndex()); + S.Diag(FirstVD->getLocation(), + diag::note_carries_dependency_missing_first_decl) << 1/*Param*/; + } + if (!oldDecl->hasAttrs()) return; @@ -1898,7 +2180,8 @@ static void mergeParamDeclAttributes(ParmVarDecl *newDecl, 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)); + InheritableAttr *newAttr = + cast<InheritableParamAttr>((*i)->clone(S.Context)); newAttr->setInherited(true); newDecl->addAttr(newAttr); foundAny = true; @@ -1966,6 +2249,22 @@ static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) { return ABIDefaultCC == CC; } +template <typename T> +static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { + const DeclContext *DC = Old->getDeclContext(); + if (DC->isRecord()) + return false; + + LanguageLinkage OldLinkage = Old->getLanguageLinkage(); + if (OldLinkage == CXXLanguageLinkage && + New->getDeclContext()->isExternCContext()) + return true; + if (OldLinkage == CLanguageLinkage && + New->getDeclContext()->isExternCXXContext()) + return true; + return false; +} + /// 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, @@ -1987,6 +2286,15 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { Old = dyn_cast<FunctionDecl>(OldD); if (!Old) { if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) { + if (New->getFriendObjectKind()) { + Diag(New->getLocation(), diag::err_using_decl_friend); + 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_using_decl_conflict_reverse); Diag(Shadow->getTargetDecl()->getLocation(), diag::note_using_decl_target); @@ -2016,9 +2324,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // Don't complain about this if we're in GNU89 mode and the old function // is an extern inline function. + // Don't complain about specializations. They are not supposed to have + // storage classes. if (!isa<CXXMethodDecl>(New) && !isa<CXXMethodDecl>(Old) && New->getStorageClass() == SC_Static && - Old->getStorageClass() != SC_Static && + isExternalLinkage(Old->getLinkage()) && + !New->getTemplateSpecializationInfo() && !canRedefineFunction(Old, getLangOpts())) { if (getLangOpts().MicrosoftExt) { Diag(New->getLocation(), diag::warn_static_non_static) << New; @@ -2060,9 +2371,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { RequiresAdjustment = true; // Don't complain about mismatches when the default CC is - // effectively the same as the explict one. + // effectively the same as the explict one. Only Old decl contains correct + // information about storage class of CXXMethod. } else if (OldTypeInfo.getCC() == CC_Default && - isABIDefaultCC(*this, NewTypeInfo.getCC(), New)) { + isABIDefaultCC(*this, NewTypeInfo.getCC(), Old)) { NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); RequiresAdjustment = true; @@ -2116,6 +2428,23 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { New->setType(QualType(NewType, 0)); NewQType = Context.getCanonicalType(New->getType()); } + + // If this redeclaration makes the function inline, we may need to add it to + // UndefinedButUsed. + if (!Old->isInlined() && New->isInlined() && + !New->hasAttr<GNUInlineAttr>() && + (getLangOpts().CPlusPlus || !getLangOpts().GNUInline) && + Old->isUsed(false) && + !Old->isDefined() && !New->isThisDeclarationADefinition()) + UndefinedButUsed.insert(std::make_pair(Old->getCanonicalDecl(), + SourceLocation())); + + // If this redeclaration makes it newly gnu_inline, we don't want to warn + // about it. + if (New->hasAttr<GNUInlineAttr>() && + Old->isInlined() && !Old->hasAttr<GNUInlineAttr>()) { + UndefinedButUsed.erase(Old->getCanonicalDecl()); + } if (getLangOpts().CPlusPlus) { // (C++98 13.1p2): @@ -2211,6 +2540,30 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { } } + // C++11 [dcl.attr.noreturn]p1: + // The first declaration of a function shall specify the noreturn + // attribute if any declaration of that function specifies the noreturn + // attribute. + if (New->hasAttr<CXX11NoReturnAttr>() && + !Old->hasAttr<CXX11NoReturnAttr>()) { + Diag(New->getAttr<CXX11NoReturnAttr>()->getLocation(), + diag::err_noreturn_missing_on_first_decl); + Diag(Old->getFirstDeclaration()->getLocation(), + diag::note_noreturn_missing_first_decl); + } + + // C++11 [dcl.attr.depend]p2: + // The first declaration of a function shall specify the + // carries_dependency attribute for its declarator-id if any declaration + // of the function specifies the carries_dependency attribute. + if (New->hasAttr<CarriesDependencyAttr>() && + !Old->hasAttr<CarriesDependencyAttr>()) { + Diag(New->getAttr<CarriesDependencyAttr>()->getLocation(), + diag::err_carries_dependency_missing_on_first_decl) << 0/*Function*/; + Diag(Old->getFirstDeclaration()->getLocation(), + diag::note_carries_dependency_missing_first_decl) << 0/*Function*/; + } + // (C++98 8.3.5p3): // All declarations for a function shall agree exactly in both the // return type and the parameter-type-list. @@ -2226,6 +2579,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { assert(OldQTypeForComparison.isCanonical()); } + if (haveIncompatibleLanguageLinkages(Old, New)) { + Diag(New->getLocation(), diag::err_different_language_linkage) << New; + Diag(Old->getLocation(), PrevDiag); + return true; + } + if (OldQTypeForComparison == NewQType) return MergeCompatibleFunctionDecls(New, Old, S); @@ -2247,7 +2606,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { SmallVector<QualType, 16> ParamTypes(OldProto->arg_type_begin(), OldProto->arg_type_end()); NewQType = Context.getFunctionType(NewFuncType->getResultType(), - ParamTypes.data(), ParamTypes.size(), + ParamTypes, OldProto->getExtProtoInfo()); New->setType(NewQType); New->setHasInheritedPrototype(); @@ -2262,7 +2621,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { SourceLocation(), SourceLocation(), 0, *ParamType, /*TInfo=*/0, - SC_None, SC_None, + SC_None, 0); Param->setScopeInfo(0, Params.size()); Param->setImplicit(); @@ -2330,8 +2689,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { diag::note_previous_declaration); } - New->setType(Context.getFunctionType(MergedReturn, &ArgTypes[0], - ArgTypes.size(), + New->setType(Context.getFunctionType(MergedReturn, ArgTypes, OldProto->getExtProtoInfo())); return MergeCompatibleFunctionDecls(New, Old, S); } @@ -2379,25 +2737,30 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, // Merge the attributes mergeDeclAttributes(New, Old); - // 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 "used" flag. + if (Old->isUsed(false)) + New->setUsed(); + // 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); + *this); if (getLangOpts().CPlusPlus) return MergeCXXFunctionDecl(New, Old, S); + // Merge the function types so the we get the composite types for the return + // and argument types. + QualType Merged = Context.mergeTypes(Old->getType(), New->getType()); + if (!Merged.isNull()) + New->setType(Merged); + return false; } @@ -2406,7 +2769,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, ObjCMethodDecl *oldMethod) { // Merge the attributes, including deprecated/unavailable - mergeDeclAttributes(newMethod, oldMethod, /* mergeDeprecation */true); + mergeDeclAttributes(newMethod, oldMethod, AMK_Override); // Merge attributes from the parameters. ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(), @@ -2414,9 +2777,9 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, for (ObjCMethodDecl::param_iterator ni = newMethod->param_begin(), ne = newMethod->param_end(); ni != ne && oi != oe; ++ni, ++oi) - mergeParamDeclAttributes(*ni, *oi, Context); + mergeParamDeclAttributes(*ni, *oi, *this); - CheckObjCMethodOverride(newMethod, oldMethod, true); + CheckObjCMethodOverride(newMethod, oldMethod); } /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and @@ -2426,7 +2789,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back /// to here in AddInitializerToDecl. We can't check them before the initializer /// is attached. -void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { +void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool OldWasHidden) { if (New->isInvalidDecl() || Old->isInvalidDecl()) return; @@ -2447,19 +2810,17 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { // 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()) + const ArrayType *OldArray = Context.getAsArrayType(Old->getType()); + const ArrayType *NewArray = Context.getAsArrayType(New->getType()); + if (Context.hasSameType(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()) + const ArrayType *OldArray = Context.getAsArrayType(Old->getType()); + const ArrayType *NewArray = Context.getAsArrayType(New->getType()); + if (Context.hasSameType(OldArray->getElementType(), + NewArray->getElementType())) MergedT = Old->getType(); } else if (New->getType()->isObjCObjectPointerType() && Old->getType()->isObjCObjectPointerType()) { @@ -2475,7 +2836,11 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); } - New->setType(MergedT); + + // Don't actually update the type on the new declaration if the old + // declaration was a extern declaration in a different scope. + if (!OldWasHidden) + New->setType(MergedT); } /// MergeVarDecl - We just parsed a variable 'New' which has the same name @@ -2486,7 +2851,8 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative /// definitions here, since the initializer hasn't been attached. /// -void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { +void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous, + bool PreviousWasHidden) { // If the new decl is already invalid, don't do any other checking. if (New->isInvalidDecl()) return; @@ -2526,13 +2892,14 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { } // Merge the types. - MergeVarDeclTypes(New, Old); + MergeVarDeclTypes(New, Old, PreviousWasHidden); if (New->isInvalidDecl()) return; - // C99 6.2.2p4: Check if we have a static decl followed by a non-static. + // [dcl.stc]p8: Check if we have a non-static decl followed by a static. if (New->getStorageClass() == SC_Static && - (Old->getStorageClass() == SC_None || Old->hasExternalStorage())) { + !New->isStaticDataMember() && + isExternalLinkage(Old->getLinkage())) { Diag(New->getLocation(), diag::err_static_non_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -2548,8 +2915,9 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // identifier has external linkage. if (New->hasExternalStorage() && Old->hasLinkage()) /* Okay */; - else if (New->getStorageClass() != SC_Static && - Old->getStorageClass() == SC_Static) { + else if (New->getCanonicalDecl()->getStorageClass() != SC_Static && + !New->isStaticDataMember() && + Old->getCanonicalDecl()->getStorageClass() == SC_Static) { Diag(New->getLocation(), diag::err_non_static_static) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -2562,8 +2930,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); } - if (Old->hasExternalStorage() && - !New->hasLinkage() && New->isLocalVarDecl()) { + if (Old->hasLinkage() && New->isLocalVarDecl() && + !New->hasExternalStorage()) { Diag(New->getLocation(), diag::err_non_extern_extern) << New->getDeclName(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -2601,17 +2969,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { 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()); + + if (haveIncompatibleLanguageLinkages(Old, New)) { + Diag(New->getLocation(), diag::err_different_language_linkage) << New; + Diag(Old->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return; + } + + // Merge "used" flag. + if (Old->isUsed(false)) + New->setUsed(); // Keep a chain of previous declarations. New->setPreviousDeclaration(Old); @@ -2628,11 +2996,12 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with -/// no declarator (e.g. "struct foo;") is parsed. It also accopts template +/// no declarator (e.g. "struct foo;") is parsed. It also accepts template /// parameters to cope with template friend declarations. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, - MultiTemplateParamsArg TemplateParams) { + MultiTemplateParamsArg TemplateParams, + bool IsExplicitInstantiation) { Decl *TagD = 0; TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || @@ -2655,6 +3024,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } if (Tag) { + getASTContext().addUnnamedTag(Tag); Tag->setFreeStanding(); if (Tag->isInvalidDecl()) return Tag; @@ -2684,6 +3054,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return TagD; } + DiagnoseFunctionSpecifiers(DS); + if (DS.isFriendSpecified()) { // If we're dealing with a decl but not a TagDecl, assume that // whatever routines created it handled the friendship aspect. @@ -2692,10 +3064,28 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return ActOnFriendTypeDecl(S, DS, TemplateParams); } - // Track whether we warned about the fact that there aren't any - // declarators. - bool emittedWarning = false; - + CXXScopeSpec &SS = DS.getTypeSpecScope(); + bool IsExplicitSpecialization = + !TemplateParams.empty() && TemplateParams.back()->size() == 0; + if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() && + !IsExplicitInstantiation && !IsExplicitSpecialization) { + // Per C++ [dcl.type.elab]p1, a class declaration cannot have a + // nested-name-specifier unless it is an explicit instantiation + // or an explicit specialization. + // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either. + Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier) + << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 : + DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 : + DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 : + DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4) + << SS.getRange(); + return 0; + } + + // Track whether this decl-specifier declares anything. + bool DeclaresAnything = true; + + // Handle anonymous struct definitions. if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { if (!Record->getDeclName() && Record->isCompleteDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { @@ -2703,13 +3093,11 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Record->getDeclContext()->isRecord()) return BuildAnonymousStructOrUnion(S, DS, AS, Record); - Diag(DS.getLocStart(), diag::ext_no_declarators) - << DS.getSourceRange(); - emittedWarning = true; + DeclaresAnything = false; } } - // Check for Microsoft C extension: anonymous struct. + // Check for Microsoft C extension: anonymous struct member. if (getLangOpts().MicrosoftExt && !getLangOpts().CPlusPlus && CurContext->isRecord() && DS.getStorageClassSpec() == DeclSpec::SCS_unspecified) { @@ -2726,70 +3114,82 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return BuildMicrosoftCAnonymousStruct(S, DS, Record); } } - - if (getLangOpts().CPlusPlus && + + // Skip all the checks below if we have a type error. + if (DS.getTypeSpecType() == DeclSpec::TST_error || + (TagD && TagD->isInvalidDecl())) + return TagD; + + if (getLangOpts().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; - } + !Enum->getIdentifier() && !Enum->isInvalidDecl()) + DeclaresAnything = false; - // 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)) { + // Customize diagnostic for a typedef missing a name. + if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) Diag(DS.getLocStart(), diag::ext_typedef_without_a_name) << DS.getSourceRange(); - return Tag; - } - - Diag(DS.getLocStart(), diag::ext_no_declarators) - << DS.getSourceRange(); - emittedWarning = true; + else + DeclaresAnything = false; } - // 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())) + if (DS.isModulePrivateSpecified() && + Tag && Tag->getDeclContext()->isFunctionOrMethod()) + Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) + << Tag->getTagKind() + << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); + + ActOnDocumentableDecl(TagD); + + // C 6.7/2: + // A declaration [...] shall declare at least a declarator [...], a tag, + // or the members of an enumeration. + // C++ [dcl.dcl]p3: + // [If there are no declarators], and except for the declaration of an + // unnamed bit-field, the decl-specifier-seq shall introduce one or more + // names into the program, or shall redeclare a name introduced by a + // previous declaration. + if (!DeclaresAnything) { + // In C, we allow this as a (popular) extension / bug. Don't bother + // producing further diagnostics for redundant qualifiers after this. + Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange(); return TagD; + } + + // C++ [dcl.stc]p1: + // If a storage-class-specifier appears in a decl-specifier-seq, [...] the + // init-declarator-list of the declaration shall not be empty. + // C++ [dcl.fct.spec]p1: + // If a cv-qualifier appears in a decl-specifier-seq, the + // init-declarator-list of the declaration shall not be empty. + // + // Spurious qualifiers here appear to be valid in C. + unsigned DiagID = diag::warn_standalone_specifier; + if (getLangOpts().CPlusPlus) + DiagID = diag::ext_standalone_specifier; // 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 (DeclSpec::SCS SCS = DS.getStorageClassSpec()) + if (!DS.isExternInLinkageSpec() && SCS != DeclSpec::SCS_typedef) + Diag(DS.getStorageClassSpecLoc(), DiagID) + << DeclSpec::getSpecifierName(SCS); if (DS.isThreadSpecified()) - Diag(DS.getThreadSpecLoc(), diag::warn_standalone_specifier) << "__thread"; + Diag(DS.getThreadSpecLoc(), DiagID) << "__thread"; if (DS.getTypeQualifiers()) { if (DS.getTypeQualifiers() & DeclSpec::TQ_const) - Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "const"; + Diag(DS.getConstSpecLoc(), DiagID) << "const"; if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) - Diag(DS.getConstSpecLoc(), diag::warn_standalone_specifier) << "volatile"; + Diag(DS.getConstSpecLoc(), DiagID) << "volatile"; // Restrict is covered above. + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) + Diag(DS.getAtomicSpecLoc(), DiagID) << "_Atomic"; } - 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"; - - if (DS.isModulePrivateSpecified() && - Tag && Tag->getDeclContext()->isFunctionOrMethod()) - Diag(DS.getModulePrivateSpecLoc(), diag::err_module_private_local_class) - << Tag->getTagKind() - << FixItHint::CreateRemoval(DS.getModulePrivateSpecLoc()); // Warn about ignored type attributes, for example: // __attribute__((aligned)) struct A; @@ -2814,8 +3214,6 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, } } - ActOnDocumentableDecl(TagD); - return TagD; } @@ -2950,25 +3348,6 @@ StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) { 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 C11 feature; anonymous structures @@ -3027,18 +3406,23 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (DS.getTypeQualifiers()) { if (DS.getTypeQualifiers() & DeclSpec::TQ_const) Diag(DS.getConstSpecLoc(), diag::ext_anonymous_struct_union_qualified) - << Record->isUnion() << 0 + << Record->isUnion() << "const" << FixItHint::CreateRemoval(DS.getConstSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile) - Diag(DS.getVolatileSpecLoc(), + Diag(DS.getVolatileSpecLoc(), diag::ext_anonymous_struct_union_qualified) - << Record->isUnion() << 1 + << Record->isUnion() << "volatile" << FixItHint::CreateRemoval(DS.getVolatileSpecLoc()); if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) - Diag(DS.getRestrictSpecLoc(), + Diag(DS.getRestrictSpecLoc(), diag::ext_anonymous_struct_union_qualified) - << Record->isUnion() << 2 + << Record->isUnion() << "restrict" << FixItHint::CreateRemoval(DS.getRestrictSpecLoc()); + if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) + Diag(DS.getAtomicSpecLoc(), + diag::ext_anonymous_struct_union_qualified) + << Record->isUnion() << "_Atomic" + << FixItHint::CreateRemoval(DS.getAtomicSpecLoc()); DS.ClearTypeQualifiers(); } @@ -3088,6 +3472,13 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, << (int)Record->isUnion(); Invalid = true; } + } else { + // This is an anonymous type definition within another anonymous type. + // This is a popular extension, provided by Plan9, MSVC and GCC, but + // not part of standard C++. + Diag(MemRecord->getLocation(), + diag::ext_anonymous_record_with_anonymous_type) + << (int)Record->isUnion(); } } else if (isa<AccessSpecDecl>(*Mem)) { // Any access specifier is fine. @@ -3153,15 +3544,12 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, Invalid = true; SC = SC_None; } - SCSpec = DS.getStorageClassSpecAsWritten(); - VarDecl::StorageClass SCAsWritten - = StorageClassSpecToVarDeclStorageClass(SCSpec); Anon = VarDecl::Create(Context, Owner, DS.getLocStart(), Record->getLocation(), /*IdentifierInfo=*/0, Context.getTypeDeclType(Record), - TInfo, SC, SCAsWritten); + TInfo, SC); // Default-initialize the implicit variable. This initialization will be // trivial in almost all cases, except if a union member has an in-class @@ -3383,7 +3771,7 @@ static QualType getCoreType(QualType Ty) { static bool hasSimilarParameters(ASTContext &Context, FunctionDecl *Declaration, FunctionDecl *Definition, - llvm::SmallVectorImpl<unsigned> &Params) { + SmallVectorImpl<unsigned> &Params) { Params.clear(); if (Declaration->param_size() != Definition->param_size()) return false; @@ -3609,8 +3997,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, return false; } -Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParamLists) { +NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists) { // TODO: consider using NameInfo for diagnostic. DeclarationNameInfo NameInfo = GetNameForDeclarator(D); DeclarationName Name = NameInfo.getName(); @@ -3690,8 +4078,6 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) return 0; - NamedDecl *New; - TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType R = TInfo->getType(); @@ -3776,6 +4162,13 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef) Previous.clear(); + // Check that there are no default arguments other than in the parameters + // of a function declaration (C++ only). + if (getLangOpts().CPlusPlus) + CheckExtraCXXDefaultArguments(D); + + NamedDecl *New; + bool AddToScope = true; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { if (TemplateParamLists.size()) { @@ -3877,29 +4270,29 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, static void FixInvalidVariablyModifiedTypeLoc(TypeLoc SrcTL, TypeLoc DstTL) { - if (PointerTypeLoc* SrcPTL = dyn_cast<PointerTypeLoc>(&SrcTL)) { - PointerTypeLoc* DstPTL = cast<PointerTypeLoc>(&DstTL); - FixInvalidVariablyModifiedTypeLoc(SrcPTL->getPointeeLoc(), - DstPTL->getPointeeLoc()); - DstPTL->setStarLoc(SrcPTL->getStarLoc()); + if (PointerTypeLoc SrcPTL = SrcTL.getAs<PointerTypeLoc>()) { + PointerTypeLoc DstPTL = DstTL.castAs<PointerTypeLoc>(); + FixInvalidVariablyModifiedTypeLoc(SrcPTL.getPointeeLoc(), + DstPTL.getPointeeLoc()); + DstPTL.setStarLoc(SrcPTL.getStarLoc()); return; } - if (ParenTypeLoc* SrcPTL = dyn_cast<ParenTypeLoc>(&SrcTL)) { - ParenTypeLoc* DstPTL = cast<ParenTypeLoc>(&DstTL); - FixInvalidVariablyModifiedTypeLoc(SrcPTL->getInnerLoc(), - DstPTL->getInnerLoc()); - DstPTL->setLParenLoc(SrcPTL->getLParenLoc()); - DstPTL->setRParenLoc(SrcPTL->getRParenLoc()); + if (ParenTypeLoc SrcPTL = SrcTL.getAs<ParenTypeLoc>()) { + ParenTypeLoc DstPTL = DstTL.castAs<ParenTypeLoc>(); + FixInvalidVariablyModifiedTypeLoc(SrcPTL.getInnerLoc(), + DstPTL.getInnerLoc()); + DstPTL.setLParenLoc(SrcPTL.getLParenLoc()); + DstPTL.setRParenLoc(SrcPTL.getRParenLoc()); return; } - ArrayTypeLoc* SrcATL = cast<ArrayTypeLoc>(&SrcTL); - ArrayTypeLoc* DstATL = cast<ArrayTypeLoc>(&DstTL); - TypeLoc SrcElemTL = SrcATL->getElementLoc(); - TypeLoc DstElemTL = DstATL->getElementLoc(); + ArrayTypeLoc SrcATL = SrcTL.castAs<ArrayTypeLoc>(); + ArrayTypeLoc DstATL = DstTL.castAs<ArrayTypeLoc>(); + TypeLoc SrcElemTL = SrcATL.getElementLoc(); + TypeLoc DstElemTL = DstATL.getElementLoc(); DstElemTL.initializeFullCopy(SrcElemTL); - DstATL->setLBracketLoc(SrcATL->getLBracketLoc()); - DstATL->setSizeExpr(SrcATL->getSizeExpr()); - DstATL->setRBracketLoc(SrcATL->getRBracketLoc()); + DstATL.setLBracketLoc(SrcATL.getLBracketLoc()); + DstATL.setSizeExpr(SrcATL.getSizeExpr()); + DstATL.setRBracketLoc(SrcATL.getRBracketLoc()); } /// Helper method to turn variable array types into constant array @@ -3921,7 +4314,7 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, return FixedTInfo; } -/// \brief Register the given locally-scoped external C declaration so +/// \brief Register the given locally-scoped extern "C" declaration so /// that it can be found later for redeclarations void Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, @@ -3930,15 +4323,15 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, 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; + LocallyScopedExternCDecls[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 + // If there was a previous declaration of this entity, 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 @@ -3962,38 +4355,42 @@ Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, } llvm::DenseMap<DeclarationName, NamedDecl *>::iterator -Sema::findLocallyScopedExternalDecl(DeclarationName Name) { +Sema::findLocallyScopedExternCDecl(DeclarationName Name) { if (ExternalSource) { // Load locally-scoped external decls from the external source. SmallVector<NamedDecl *, 4> Decls; - ExternalSource->ReadLocallyScopedExternalDecls(Decls); + ExternalSource->ReadLocallyScopedExternCDecls(Decls); for (unsigned I = 0, N = Decls.size(); I != N; ++I) { llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = LocallyScopedExternalDecls.find(Decls[I]->getDeclName()); - if (Pos == LocallyScopedExternalDecls.end()) - LocallyScopedExternalDecls[Decls[I]->getDeclName()] = Decls[I]; + = LocallyScopedExternCDecls.find(Decls[I]->getDeclName()); + if (Pos == LocallyScopedExternCDecls.end()) + LocallyScopedExternCDecls[Decls[I]->getDeclName()] = Decls[I]; } } - return LocallyScopedExternalDecls.find(Name); + return LocallyScopedExternCDecls.find(Name); } /// \brief Diagnose function specifiers on a declaration of an identifier that /// does not identify a function. -void Sema::DiagnoseFunctionSpecifiers(Declarator& D) { +void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) { // 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(), + if (DS.isInlineSpecified()) + Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function); - if (D.getDeclSpec().isVirtualSpecified()) - Diag(D.getDeclSpec().getVirtualSpecLoc(), + if (DS.isVirtualSpecified()) + Diag(DS.getVirtualSpecLoc(), diag::err_virtual_non_function); - if (D.getDeclSpec().isExplicitSpecified()) - Diag(D.getDeclSpec().getExplicitSpecLoc(), + if (DS.isExplicitSpecified()) + Diag(DS.getExplicitSpecLoc(), diag::err_explicit_non_function); + + if (DS.isNoreturnSpecified()) + Diag(DS.getNoreturnSpecLoc(), + diag::err_noreturn_non_function); } NamedDecl* @@ -4009,12 +4406,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, Previous.clear(); } - if (getLangOpts().CPlusPlus) { - // Check that there are no default arguments (C++ only). - CheckExtraCXXDefaultArguments(D); - } - - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); @@ -4090,6 +4482,7 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, // in an outer scope, it isn't the same thing. FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false, /*ExplicitInstantiationOrSpecialization=*/false); + filterNonConflictingPreviousDecls(Context, NewTD, Previous); if (!Previous.empty()) { Redeclaration = true; MergeTypedefNameDecl(NewTD, Previous); @@ -4220,6 +4613,74 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) { return false; } +static void checkAttributesAfterMerging(Sema &S, NamedDecl &ND) { + // 'weak' only applies to declarations with external linkage. + if (WeakAttr *Attr = ND.getAttr<WeakAttr>()) { + if (ND.getLinkage() != ExternalLinkage) { + S.Diag(Attr->getLocation(), diag::err_attribute_weak_static); + ND.dropAttr<WeakAttr>(); + } + } + if (WeakRefAttr *Attr = ND.getAttr<WeakRefAttr>()) { + if (ND.hasExternalLinkage()) { + S.Diag(Attr->getLocation(), diag::err_attribute_weakref_not_static); + ND.dropAttr<WeakRefAttr>(); + } + } +} + +/// Given that we are within the definition of the given function, +/// will that definition behave like C99's 'inline', where the +/// definition is discarded except for optimization purposes? +static bool isFunctionDefinitionDiscarded(Sema &S, FunctionDecl *FD) { + // Try to avoid calling GetGVALinkageForFunction. + + // All cases of this require the 'inline' keyword. + if (!FD->isInlined()) return false; + + // This is only possible in C++ with the gnu_inline attribute. + if (S.getLangOpts().CPlusPlus && !FD->hasAttr<GNUInlineAttr>()) + return false; + + // Okay, go ahead and call the relatively-more-expensive function. + +#ifndef NDEBUG + // AST quite reasonably asserts that it's working on a function + // definition. We don't really have a way to tell it that we're + // currently defining the function, so just lie to it in +Asserts + // builds. This is an awful hack. + FD->setLazyBody(1); +#endif + + bool isC99Inline = (S.Context.GetGVALinkageForFunction(FD) == GVA_C99Inline); + +#ifndef NDEBUG + FD->setLazyBody(0); +#endif + + return isC99Inline; +} + +static bool shouldConsiderLinkage(const VarDecl *VD) { + const DeclContext *DC = VD->getDeclContext()->getRedeclContext(); + if (DC->isFunctionOrMethod()) + return VD->hasExternalStorage(); + if (DC->isFileContext()) + return true; + if (DC->isRecord()) + return false; + llvm_unreachable("Unexpected context"); +} + +static bool shouldConsiderLinkage(const FunctionDecl *FD) { + const DeclContext *DC = FD->getDeclContext()->getRedeclContext(); + if (DC->isFileContext() || DC->isFunctionOrMethod()) + return true; + if (DC->isRecord()) + return false; + llvm_unreachable("Unexpected context"); +} + NamedDecl* Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -4227,14 +4688,21 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, QualType R = TInfo->getType(); DeclarationName Name = GetNameForDeclarator(D).getName(); - // Check that there are no default arguments (C++ only). - if (getLangOpts().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 (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16) + { + // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and + // half array type (unless the cl_khr_fp16 extension is enabled). + if (Context.getBaseElementType(R)->isHalfType()) { + Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R; + D.setInvalidType(); + } + } + if (SCSpec == DeclSpec::SCS_mutable) { // mutable can only appear on non-static class members, so it's always // an error here @@ -4242,9 +4710,6 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, D.setInvalidType(); SC = SC_None; } - SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); - VarDecl::StorageClass SCAsWritten - = StorageClassSpecToVarDeclStorageClass(SCSpec); IdentifierInfo *II = Name.getAsIdentifierInfo(); if (!II) { @@ -4253,7 +4718,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, return 0; } - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (!DC->isRecord() && S->getFnParent() == 0) { // C99 6.9p2: The storage-class specifiers auto and register shall not @@ -4273,8 +4738,33 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (getLangOpts().OpenCL) { // Set up the special work-group-local storage class for variables in the // OpenCL __local address space. - if (R.getAddressSpace() == LangAS::opencl_local) + if (R.getAddressSpace() == LangAS::opencl_local) { SC = SC_OpenCLWorkGroupLocal; + } + + // OpenCL v1.2 s6.9.b p4: + // The sampler type cannot be used with the __local and __global address + // space qualifiers. + if (R->isSamplerT() && (R.getAddressSpace() == LangAS::opencl_local || + R.getAddressSpace() == LangAS::opencl_global)) { + Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace); + } + + // OpenCL 1.2 spec, p6.9 r: + // The event type cannot be used to declare a program scope variable. + // The event type cannot be used with the __local, __constant and __global + // address space qualifiers. + if (R->isEventT()) { + if (S->getParent() == 0) { + Diag(D.getLocStart(), diag::err_event_t_global_var); + D.setInvalidType(); + } + + if (R.getAddressSpace()) { + Diag(D.getLocStart(), diag::err_event_t_addr_space_qual); + D.setInvalidType(); + } + } } bool isExplicitSpecialization = false; @@ -4282,7 +4772,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (!getLangOpts().CPlusPlus) { NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, - R, TInfo, SC, SCAsWritten); + R, TInfo, SC); if (D.isInvalidType()) NewVD->setInvalidDecl(); @@ -4293,8 +4783,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, 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 && CurContext->isRecord()) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) { @@ -4307,7 +4796,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // the program is ill-formed. C++11 drops this restriction. if (RD->isUnion()) Diag(D.getIdentifierLoc(), - getLangOpts().CPlusPlus0x + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_static_data_member_in_union : diag::ext_static_data_member_in_union) << Name; // We conservatively disallow static data members in anonymous structs. @@ -4352,7 +4841,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD = VarDecl::Create(Context, DC, D.getLocStart(), D.getIdentifierLoc(), II, - R, TInfo, SC, SCAsWritten); + R, TInfo, SC); // 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. @@ -4388,6 +4877,25 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->setThreadSpecified(true); } + // C99 6.7.4p3 + // An inline definition of a function with external linkage shall + // not contain a definition of a modifiable object with static or + // thread storage duration... + // We only apply this when the function is required to be defined + // elsewhere, i.e. when the function is not 'extern inline'. Note + // that a local variable with thread storage duration still has to + // be marked 'static'. Also note that it's possible to get these + // semantics in C++ using __attribute__((gnu_inline)). + if (SC == SC_Static && S->getFnParent() != 0 && + !NewVD->getType().isConstQualified()) { + FunctionDecl *CurFD = getCurFunctionDecl(); + if (CurFD && isFunctionDefinitionDiscarded(*this, CurFD)) { + Diag(D.getDeclSpec().getStorageClassSpecLoc(), + diag::warn_static_local_in_extern_inline); + MaybeSuggestAddingStaticToDecl(CurFD); + } + } + if (D.getDeclSpec().isModulePrivateSpecified()) { if (isExplicitSpecialization) Diag(NewVD->getLocation(), diag::err_module_private_specialization) @@ -4405,12 +4913,17 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); + if (NewVD->hasAttrs()) + CheckAlignasUnderalignment(NewVD); + if (getLangOpts().CUDA) { // CUDA B.2.5: "__shared__ and __constant__ variables have implied static // storage [duration]." if (SC == SC_None && S->getFnParent() != 0 && - (NewVD->hasAttr<CUDASharedAttr>() || NewVD->hasAttr<CUDAConstantAttr>())) + (NewVD->hasAttr<CUDASharedAttr>() || + NewVD->hasAttr<CUDAConstantAttr>())) { NewVD->setStorageClass(SC_Static); + } } // In auto-retain/release, infer strong retension for variables of @@ -4459,7 +4972,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // 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(), + FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewVD), isExplicitSpecialization); if (!getLangOpts().CPlusPlus) { @@ -4493,19 +5006,15 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewVD->setInvalidDecl(); } + ProcessPragmaWeak(S, NewVD); + checkAttributesAfterMerging(*this, *NewVD); + // 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; } @@ -4604,6 +5113,32 @@ void Sema::CheckShadow(Scope *S, VarDecl *D) { CheckShadow(S, D, R); } +template<typename T> +static bool mayConflictWithNonVisibleExternC(const T *ND) { + const DeclContext *DC = ND->getDeclContext(); + if (DC->getRedeclContext()->isTranslationUnit()) + return true; + + // We know that is the first decl we see, other than function local + // extern C ones. If this is C++ and the decl is not in a extern C context + // it cannot have C language linkage. Avoid calling isExternC in that case. + // We need to this because of code like + // + // namespace { struct bar {}; } + // auto foo = bar(); + // + // This code runs before the init of foo is set, and therefore before + // the type of foo is known. Not knowing the type we cannot know its linkage + // unless it is in an extern C block. + if (!DC->isExternCContext()) { + const ASTContext &Context = ND->getASTContext(); + if (Context.getLangOpts().CPlusPlus) + return false; + } + + return ND->isExternC(); +} + /// \brief Perform semantic checking on a newly-created variable /// declaration. /// @@ -4706,16 +5241,44 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, NewVD->setTypeSourceInfo(FixedTInfo); } - 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. + // If we did not find anything by this name, look for a non-visible + // extern "C" declaration with the same name. + // + // Clang has a lot of problems with extern local declarations. + // The actual standards text here is: + // + // C++11 [basic.link]p6: + // The name of a function declared in block scope and the name + // of a variable declared by a block scope extern declaration + // have linkage. 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. + // + // C11 6.2.7p4: + // For an identifier with internal or external linkage declared + // in a scope in which a prior declaration of that identifier is + // visible, if the prior declaration specifies internal or + // external linkage, the type of the identifier at the later + // declaration becomes the composite type. + // + // The most important point here is that we're not allowed to + // update our understanding of the type according to declarations + // not in scope. + bool PreviousWasHidden = false; + if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) { llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = findLocallyScopedExternalDecl(NewVD->getDeclName()); - if (Pos != LocallyScopedExternalDecls.end()) + = findLocallyScopedExternCDecl(NewVD->getDeclName()); + if (Pos != LocallyScopedExternCDecls.end()) { Previous.addDecl(Pos->second); + PreviousWasHidden = true; + } } + // Filter out any non-conflicting previous declarations. + filterNonConflictingPreviousDecls(Context, NewVD, Previous); + if (T->isVoidType() && !NewVD->hasExternalStorage()) { Diag(NewVD->getLocation(), diag::err_typecheck_decl_incomplete_type) << T; @@ -4743,7 +5306,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, } if (!Previous.empty()) { - MergeVarDecl(NewVD, Previous); + MergeVarDecl(NewVD, Previous, PreviousWasHidden); return true; } return false; @@ -4778,9 +5341,9 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, } for (Path.Decls = BaseRecord->lookup(Name); - Path.Decls.first != Path.Decls.second; - ++Path.Decls.first) { - NamedDecl *D = *Path.Decls.first; + !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + NamedDecl *D = Path.Decls.front(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false)) return true; @@ -4832,6 +5395,7 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) { MD->addOverriddenMethod(OldMD->getCanonicalDecl()); if (!CheckOverridingFunctionReturnType(MD, OldMD) && + !CheckOverridingFunctionAttributes(MD, OldMD) && !CheckOverridingFunctionExceptionSpec(MD, OldMD) && !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { hasDeletedOverridenMethods |= OldMD->isDeleted(); @@ -4878,7 +5442,7 @@ class DifferentNameValidatorCCC : public CorrectionCandidateCallback { if (candidate.getEditDistance() == 0) return false; - llvm::SmallVector<unsigned, 1> MismatchedParams; + SmallVector<unsigned, 1> MismatchedParams; for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(), CDeclEnd = candidate.end(); CDecl != CDeclEnd; ++CDecl) { @@ -4924,8 +5488,8 @@ static NamedDecl* DiagnoseInvalidRedeclaration( DeclContext *NewDC = NewFD->getDeclContext(); LookupResult Prev(SemaRef, Name, NewFD->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration); - llvm::SmallVector<unsigned, 1> MismatchedParams; - llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1> NearMatches; + SmallVector<unsigned, 1> MismatchedParams; + SmallVector<std::pair<FunctionDecl *, unsigned>, 1> NearMatches; TypoCorrection Correction; bool isFriendDecl = (SemaRef.getLangOpts().CPlusPlus && ExtraArgs.D.getDeclSpec().isFriendSpecified()); @@ -5029,7 +5593,7 @@ static NamedDecl* DiagnoseInvalidRedeclaration( if (CXXMethodDecl *NewMD = dyn_cast<CXXMethodDecl>(NewFD)) NewFDisConst = NewMD->isConst(); - for (llvm::SmallVector<std::pair<FunctionDecl*, unsigned>, 1>::iterator + for (SmallVector<std::pair<FunctionDecl *, unsigned>, 1>::iterator NearMatch = NearMatches.begin(), NearMatchEnd = NearMatches.end(); NearMatch != NearMatchEnd; ++NearMatch) { FunctionDecl *FD = NearMatch->first; @@ -5098,9 +5662,6 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, FunctionDecl *NewFD = 0; bool isInline = D.getDeclSpec().isInlineSpecified(); - DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten(); - FunctionDecl::StorageClass SCAsWritten - = StorageClassSpecToFunctionDeclStorageClass(SCSpec); if (!SemaRef.getLangOpts().CPlusPlus) { // Determine whether the function was written with a @@ -5114,8 +5675,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), NameInfo, R, - TInfo, SC, SCAsWritten, isInline, - HasPrototype); + TInfo, SC, isInline, + HasPrototype, false); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -5164,7 +5725,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // 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 (SemaRef.getLangOpts().CPlusPlus0x && !Record->isDependentType() && + if (SemaRef.getLangOpts().CPlusPlus11 && !Record->isDependentType() && Record->getDefinition() && !Record->isBeingDefined() && R->getAs<FunctionProtoType>()->getExceptionSpecType() == EST_None) { SemaRef.AdjustDestructorExceptionSpec(Record, NewDD); @@ -5182,7 +5743,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), D.getIdentifierLoc(), Name, R, TInfo, - SC, SCAsWritten, isInline, + SC, isInline, /*hasPrototype=*/true, isConstexpr); } @@ -5213,36 +5774,21 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, 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; - - IsVirtualOkay = !isStatic; - // This is a C++ method declaration. - return CXXMethodDecl::Create(SemaRef.Context, cast<CXXRecordDecl>(DC), - D.getLocStart(), NameInfo, R, - TInfo, isStatic, SCAsWritten, isInline, - isConstexpr, SourceLocation()); - + CXXMethodDecl *Ret = CXXMethodDecl::Create(SemaRef.Context, + cast<CXXRecordDecl>(DC), + D.getLocStart(), NameInfo, R, + TInfo, SC, isInline, + isConstexpr, SourceLocation()); + IsVirtualOkay = !Ret->isStatic(); + return Ret; } else { // Determine whether the function was written with a // prototype. This true when: // - we're in C++ (where every function has a prototype), return FunctionDecl::Create(SemaRef.Context, DC, D.getLocStart(), - NameInfo, R, TInfo, SC, SCAsWritten, isInline, + NameInfo, R, TInfo, SC, isInline, true/*HasPrototype*/, isConstexpr); } } @@ -5291,8 +5837,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, T = Context.getObjCObjectPointerType(T); if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(R)) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - R = Context.getFunctionType(T, FPT->arg_type_begin(), - FPT->getNumArgs(), EPI); + R = Context.getFunctionType(T, + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI); } else if (isa<FunctionNoProtoType>(R)) R = Context.getFunctionNoProtoType(T); @@ -5504,11 +6052,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } if (isConstexpr) { - // C++0x [dcl.constexpr]p2: constexpr functions and constexpr constructors + // C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors // are implicitly inline. NewFD->setImplicitlyInline(); - // C++0x [dcl.constexpr]p3: functions declared constexpr are required to + // C++11 [dcl.constexpr]p3: functions declared constexpr are required to // be either constructors or to return a literal type. Therefore, // destructors cannot be declared constexpr. if (isa<CXXDestructorDecl>(NewFD)) @@ -5583,17 +6131,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, const FunctionProtoType *FPT = R->getAs<FunctionProtoType>(); if ((Name.getCXXOverloadedOperator() == OO_Delete || Name.getCXXOverloadedOperator() == OO_Array_Delete) && - getLangOpts().CPlusPlus0x && FPT && !FPT->hasExceptionSpec()) { + getLangOpts().CPlusPlus11 && FPT && !FPT->hasExceptionSpec()) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExceptionSpecType = EST_BasicNoexcept; NewFD->setType(Context.getFunctionType(FPT->getResultType(), - FPT->arg_type_begin(), - FPT->getNumArgs(), EPI)); + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI)); } } // Filter out previous declarations that don't match the scope. - FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(), + FilterLookupForScope(Previous, DC, S, shouldConsiderLinkage(NewFD), isExplicitSpecialization || isFunctionTemplateSpecialization); @@ -5675,6 +6224,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setDeclsInPrototypeScope(DeclsInPrototypeScope); DeclsInPrototypeScope.clear(); + if (D.getDeclSpec().isNoreturnSpecified()) + NewFD->addAttr( + ::new(Context) C11NoReturnAttr(D.getDeclSpec().getNoreturnSpecLoc(), + Context)); + // Process the non-inheritable attributes on this declaration. ProcessDeclAttributes(S, NewFD, D, /*NonInheritable=*/true, /*Inheritable=*/false); @@ -5691,6 +6245,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, ProcessDeclAttributes(S, NewFD, D, /*NonInheritable=*/false, /*Inheritable=*/true); + QualType RetType = NewFD->getResultType(); + const CXXRecordDecl *Ret = RetType->isRecordType() ? + RetType->getAsCXXRecordDecl() : RetType->getPointeeCXXRecordDecl(); + if (!NewFD->isInvalidDecl() && !NewFD->hasAttr<WarnUnusedResultAttr>() && + Ret && Ret->hasAttr<WarnUnusedResultAttr>()) { + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); + if (!(MD && MD->getCorrespondingMethodInClass(Ret, true))) { + NewFD->addAttr(new (Context) WarnUnusedResultAttr(SourceRange(), + Context)); + } + } + if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. bool isExplicitSpecialization=false; @@ -5788,7 +6354,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // A storage-class-specifier shall not be specified in an explicit // specialization (14.7.3) if (SC != SC_None) { - if (SC != NewFD->getStorageClass()) + if (SC != NewFD->getTemplateSpecializationInfo()->getTemplate()->getTemplatedDecl()->getStorageClass()) Diag(NewFD->getLocation(), diag::err_explicit_specialization_inconsistent_storage_class) << SC @@ -5938,6 +6504,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + ProcessPragmaWeak(S, NewFD); + checkAttributesAfterMerging(*this, *NewFD); + AddKnownFunctionAttributes(NewFD); if (NewFD->hasAttr<OverloadableAttr>() && @@ -5952,13 +6521,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, EPI.Variadic = true; EPI.ExtInfo = FT->getExtInfo(); - QualType R = Context.getFunctionType(FT->getResultType(), 0, 0, EPI); + QualType R = Context.getFunctionType(FT->getResultType(), + ArrayRef<QualType>(), + 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()) + if (!DC->isRecord() && NewFD->hasExternalLinkage()) AddPushedVisibilityAttribute(NewFD); // If there's a #pragma clang arc_cf_code_audited in scope, consider @@ -5982,12 +6553,42 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - // OpenCL v1.2 s6.8 static is invalid for kernel functions. - if ((getLangOpts().OpenCLVersion >= 120) - && NewFD->hasAttr<OpenCLKernelAttr>() - && (SC == SC_Static)) { - Diag(D.getIdentifierLoc(), diag::err_static_kernel); - D.setInvalidType(); + if (NewFD->hasAttr<OpenCLKernelAttr>()) { + // OpenCL v1.2 s6.8 static is invalid for kernel functions. + if ((getLangOpts().OpenCLVersion >= 120) + && (SC == SC_Static)) { + Diag(D.getIdentifierLoc(), diag::err_static_kernel); + D.setInvalidType(); + } + + // OpenCL v1.2, s6.9 -- Kernels can only have return type void. + if (!NewFD->getResultType()->isVoidType()) { + Diag(D.getIdentifierLoc(), + diag::err_expected_kernel_void_return_type); + D.setInvalidType(); + } + + for (FunctionDecl::param_iterator PI = NewFD->param_begin(), + PE = NewFD->param_end(); PI != PE; ++PI) { + ParmVarDecl *Param = *PI; + QualType PT = Param->getType(); + + // OpenCL v1.2 s6.9.a: + // A kernel function argument cannot be declared as a + // pointer to a pointer type. + if (PT->isPointerType() && PT->getPointeeType()->isPointerType()) { + Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_arg); + D.setInvalidType(); + } + + // OpenCL v1.2 s6.8 n: + // A kernel function argument cannot be declared + // of event_t type. + if (PT->isEventT()) { + Diag(Param->getLocation(), diag::err_event_t_kernel_arg); + D.setInvalidType(); + } + } } MarkUnusedFileScopedDecl(NewFD); @@ -6043,17 +6644,20 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, && "Variably modified return types are not handled here"); // 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. + if (Previous.empty() && mayConflictWithNonVisibleExternC(NewFD)) { + // Since we did not find anything by this name, look for a non-visible + // extern "C" declaration with the same name. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = findLocallyScopedExternalDecl(NewFD->getDeclName()); - if (Pos != LocallyScopedExternalDecls.end()) + = findLocallyScopedExternCDecl(NewFD->getDeclName()); + if (Pos != LocallyScopedExternCDecls.end()) Previous.addDecl(Pos->second); } + // Filter out any non-conflicting previous declarations. + filterNonConflictingPreviousDecls(Context, NewFD, Previous); + bool Redeclaration = false; + NamedDecl *OldDecl = 0; // Merge or overload the declaration with an existing declaration of // the same name, if appropriate. @@ -6062,8 +6666,6 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // 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(); @@ -6100,42 +6702,90 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Context)); } } + } - if (Redeclaration) { - // NewFD and OldDecl represent declarations that need to be - // merged. - if (MergeFunctionDecl(NewFD, OldDecl, S)) { - NewFD->setInvalidDecl(); - return Redeclaration; - } + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // + // This needs to be delayed until we know whether this is an out-of-line + // definition of a static member function. + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); + if (MD && MD->isConstexpr() && !MD->isStatic() && + !isa<CXXConstructorDecl>(MD) && + (MD->getTypeQualifiers() & Qualifiers::Const) == 0) { + CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl); + if (FunctionTemplateDecl *OldTD = + dyn_cast_or_null<FunctionTemplateDecl>(OldDecl)) + OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl()); + if (!OldMD || !OldMD->isStatic()) { + const FunctionProtoType *FPT = + MD->getType()->castAs<FunctionProtoType>(); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.TypeQuals |= Qualifiers::Const; + MD->setType(Context.getFunctionType(FPT->getResultType(), + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI)); + } + } - 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()); + if (Redeclaration) { + // NewFD and OldDecl represent declarations that need to be + // merged. + if (MergeFunctionDecl(NewFD, OldDecl, S)) { + NewFD->setInvalidDecl(); + return Redeclaration; + } + + 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 { + // This needs to happen first so that 'inline' propagates. + NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); + + if (isa<CXXMethodDecl>(NewFD)) { + // A valid redeclaration of a C++ method must be out-of-line, + // but (unfortunately) it's not necessarily a definition + // because of templates, which means that the previous + // declaration is not necessarily from the class definition. + + // For just setting the access, that doesn't matter. + CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl); + NewFD->setAccess(oldMethod->getAccess()); + + // Update the key-function state if necessary for this ABI. + if (NewFD->isInlined() && + !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { + // setNonKeyFunction needs to work with the original + // declaration from the class definition, and isVirtual() is + // just faster in that case, so map back to that now. + oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDeclaration()); + if (oldMethod->isVirtual()) { + Context.setNonKeyFunction(oldMethod); + } } - - } else { - if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions - NewFD->setAccess(OldDecl->getAccess()); - NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl)); } } } @@ -6208,6 +6858,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // declaration against the expected type for the builtin. if (unsigned BuiltinID = NewFD->getBuiltinID()) { ASTContext::GetBuiltinTypeError Error; + LookupPredefedObjCSuperType(*this, S, NewFD->getIdentifier()); 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, @@ -6219,7 +6870,8 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // If this function is declared as being extern "C", then check to see if // the function returns a UDT (class, struct, or union type) that is not C // compatible, and if it does, warn the user. - if (NewFD->isExternC()) { + // But, issue any diagnostic on the first declaration only. + if (NewFD->isExternC() && Previous.empty()) { QualType R = NewFD->getResultType(); if (R->isIncompleteType() && !R->isVoidType()) Diag(NewFD->getLocation(), diag::warn_return_value_udt_incomplete) @@ -6232,12 +6884,30 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, return Redeclaration; } +static SourceRange getResultSourceRange(const FunctionDecl *FD) { + const TypeSourceInfo *TSI = FD->getTypeSourceInfo(); + if (!TSI) + return SourceRange(); + + TypeLoc TL = TSI->getTypeLoc(); + FunctionTypeLoc FunctionTL = TL.getAs<FunctionTypeLoc>(); + if (!FunctionTL) + return SourceRange(); + + TypeLoc ResultTL = FunctionTL.getResultLoc(); + if (ResultTL.getUnqualifiedLoc().getAs<BuiltinTypeLoc>()) + return ResultTL.getSourceRange(); + + return SourceRange(); +} + void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { // C++11 [basic.start.main]p3: A program that declares main to be inline, // static or constexpr is ill-formed. - // C99 6.7.4p4: In a hosted environment, the inline function specifier - // shall not appear in a declaration of main. + // C11 6.7.4p4: In a hosted environment, no function specifier(s) shall + // appear in a declaration of main. // static main is not an error under C99, but we should warn about it. + // We accept _Noreturn main as an extension. if (FD->getStorageClass() == SC_Static) Diag(DS.getStorageClassSpecLoc(), getLangOpts().CPlusPlus ? diag::err_static_main : diag::warn_static_main) @@ -6245,6 +6915,14 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { if (FD->isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_main) << FixItHint::CreateRemoval(DS.getInlineSpecLoc()); + if (DS.isNoreturnSpecified()) { + SourceLocation NoreturnLoc = DS.getNoreturnSpecLoc(); + SourceRange NoreturnRange(NoreturnLoc, + PP.getLocForEndOfToken(NoreturnLoc)); + Diag(NoreturnLoc, diag::ext_noreturn_main); + Diag(NoreturnLoc, diag::note_main_remove_noreturn) + << FixItHint::CreateRemoval(NoreturnRange); + } if (FD->isConstexpr()) { Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main) << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); @@ -6268,9 +6946,20 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { } else if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) { Diag(FD->getTypeSpecStartLoc(), diag::ext_main_returns_nonint); + SourceRange ResultRange = getResultSourceRange(FD); + if (ResultRange.isValid()) + Diag(ResultRange.getBegin(), diag::note_main_change_return_type) + << FixItHint::CreateReplacement(ResultRange, "int"); + // Otherwise, this is just a flat-out error. } else { - Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint); + SourceRange ResultRange = getResultSourceRange(FD); + if (ResultRange.isValid()) + Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint) + << FixItHint::CreateReplacement(ResultRange, "int"); + else + Diag(FD->getTypeSpecStartLoc(), diag::err_main_returns_nonint); + FD->setInvalidDecl(true); } @@ -6319,7 +7008,8 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { 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)) { + Context.hasSameType(QualType(qs.strip(PT->getPointeeType()), 0), + Context.CharTy)) { qs.removeConst(); mismatch = !qs.empty(); } @@ -6457,6 +7147,14 @@ namespace { Visit(Base); } + void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { + if (E->getNumArgs() > 0) + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getArg(0))) + HandleDeclRefExpr(DRE); + + Inherited::VisitCXXOperatorCallExpr(E); + } + void VisitUnaryOperator(UnaryOperator *E) { // For POD record types, addresses of its own members are well-defined. if (E->getOpcode() == UO_AddrOf && isRecordType && @@ -6471,11 +7169,17 @@ namespace { void VisitObjCMessageExpr(ObjCMessageExpr *E) { return; } void HandleDeclRefExpr(DeclRefExpr *DRE) { - Decl* ReferenceDecl = DRE->getDecl(); + Decl* ReferenceDecl = DRE->getDecl(); if (OrigDecl != ReferenceDecl) return; - unsigned diag = isReferenceType - ? diag::warn_uninit_self_reference_in_reference_init - : diag::warn_uninit_self_reference_in_init; + unsigned diag; + if (isReferenceType) { + diag = diag::warn_uninit_self_reference_in_reference_init; + } else if (cast<VarDecl>(OrigDecl)->isStaticLocal()) { + diag = diag::warn_static_self_reference_in_init; + } else { + diag = diag::warn_uninit_self_reference_in_init; + } + S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, S.PDiag(diag) << DRE->getNameInfo().getName() @@ -6572,6 +7276,20 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, DeduceInit = CXXDirectInit->getExpr(0); } } + + // Expressions default to 'id' when we're in a debugger. + bool DefaultedToAuto = false; + if (getLangOpts().DebuggerCastResultToId && + Init->getType() == Context.UnknownAnyTy) { + ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + Init = Result.take(); + DefaultedToAuto = true; + } + TypeSourceInfo *DeducedType = 0; if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) == DAR_Failed) @@ -6582,8 +7300,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } VDecl->setTypeSourceInfo(DeducedType); VDecl->setType(DeducedType->getType()); - VDecl->ClearLinkageCache(); - + assert(VDecl->isLinkageValid()); + // In ARC, infer lifetime. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) VDecl->setInvalidDecl(); @@ -6592,7 +7310,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // 'id' instead of a specific object type prevents most of our usual checks. // We only want to warn outside of template instantiations, though: // inside a template, the 'id' could have come from a parameter. - if (ActiveTemplateInstantiations.empty() && + if (ActiveTemplateInstantiations.empty() && !DefaultedToAuto && DeducedType->getType()->isObjCIdType()) { SourceLocation Loc = DeducedType->getTypeLoc().getBeginLoc(); Diag(Loc, diag::warn_auto_var_is_id) @@ -6602,7 +7320,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // If this is a redeclaration, check that the type we just deduced matches // the previously declared type. if (VarDecl *Old = VDecl->getPreviousDecl()) - MergeVarDeclTypes(VDecl, Old); + MergeVarDeclTypes(VDecl, Old, /*OldWasHidden*/ false); } if (VDecl->isLocalVarDecl() && VDecl->hasExternalStorage()) { @@ -6683,17 +7401,17 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // CheckInitializerTypes may change it. QualType DclT = VDecl->getType(), SavT = DclT; - // Top-level message sends default to 'id' when we're in a debugger - // and we are assigning it to a variable of 'id' type. - if (getLangOpts().DebuggerCastResultToId && DclT->isObjCIdType()) - if (Init->getType() == Context.UnknownAnyTy && isa<ObjCMessageExpr>(Init)) { - ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); - if (Result.isInvalid()) { - VDecl->setInvalidDecl(); - return; - } - Init = Result.take(); + // Expressions default to 'id' when we're in a debugger + // and we are assigning it to a variable of Objective-C pointer type. + if (getLangOpts().DebuggerCastResultToId && DclT->isObjCObjectPointerType() && + Init->getType() == Context.UnknownAnyTy) { + ExprResult Result = forceUnknownAnyToType(Init, Context.getObjCIdType()); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; } + Init = Result.take(); + } // Perform the initialization. if (!VDecl->isInvalidDecl()) { @@ -6740,9 +7458,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (!VDecl->isInvalidDecl() && (DclT != SavT)) VDecl->setType(DclT); - // Check any implicit conversions within the expression. - CheckImplicitConversions(Init, VDecl->getLocation()); - if (!VDecl->isInvalidDecl()) { checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); @@ -6765,7 +7480,26 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } } - Init = MaybeCreateExprWithCleanups(Init); + // The initialization is usually a full-expression. + // + // FIXME: If this is a braced initialization of an aggregate, it is not + // an expression, and each individual field initializer is a separate + // full-expression. For instance, in: + // + // struct Temp { ~Temp(); }; + // struct S { S(Temp); }; + // struct T { S a, b; } t = { Temp(), Temp() } + // + // we should destroy the first Temp before constructing the second. + ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(), + false, + VDecl->isConstexpr()); + if (Result.isInvalid()) { + VDecl->setInvalidDecl(); + return; + } + Init = Result.take(); + // Attach the initializer to the decl. VDecl->setInit(Init); @@ -6817,7 +7551,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } else if (DclT->isIntegralOrEnumerationType()) { // Check whether the expression is a constant expression. SourceLocation Loc; - if (getLangOpts().CPlusPlus0x && DclT.isVolatileQualified()) + if (getLangOpts().CPlusPlus11 && DclT.isVolatileQualified()) // In C++11, a non-constexpr const static data member with an // in-class initializer cannot be volatile. Diag(VDecl->getLocation(), diag::err_in_class_initializer_volatile); @@ -6840,21 +7574,28 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // We allow foldable floating-point constants as an extension. } else if (DclT->isFloatingType()) { // also permits complex, which is ok - Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) - << DclT << Init->getSourceRange(); - if (getLangOpts().CPlusPlus0x) + // In C++98, this is a GNU extension. In C++11, it is not, but we support + // it anyway and provide a fixit to add the 'constexpr'. + if (getLangOpts().CPlusPlus11) { Diag(VDecl->getLocation(), - diag::note_in_class_initializer_float_type_constexpr) - << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + diag::ext_in_class_initializer_float_type_cxx11) + << DclT << Init->getSourceRange(); + Diag(VDecl->getLocStart(), + diag::note_in_class_initializer_float_type_cxx11) + << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); + } else { + Diag(VDecl->getLocation(), diag::ext_in_class_initializer_float_type) + << DclT << Init->getSourceRange(); - if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) { - Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) - << Init->getSourceRange(); - VDecl->setInvalidDecl(); + if (!Init->isValueDependent() && !Init->isEvaluatable(Context)) { + Diag(Init->getExprLoc(), diag::err_in_class_initializer_non_constant) + << Init->getSourceRange(); + VDecl->setInvalidDecl(); + } } // Suggest adding 'constexpr' in C++11 for literal types. - } else if (getLangOpts().CPlusPlus0x && DclT->isLiteralType()) { + } else if (getLangOpts().CPlusPlus11 && DclT->isLiteralType()) { Diag(VDecl->getLocation(), diag::err_in_class_initializer_literal_type) << DclT << Init->getSourceRange() << FixItHint::CreateInsertion(VDecl->getLocStart(), "constexpr "); @@ -6866,9 +7607,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, VDecl->setInvalidDecl(); } } else if (VDecl->isFileVarDecl()) { - if (VDecl->getStorageClassAsWritten() == SC_Extern && + if (VDecl->getStorageClass() == SC_Extern && (!getLangOpts().CPlusPlus || - !Context.getBaseElementType(VDecl->getType()).isConstQualified())) + !(Context.getBaseElementType(VDecl->getType()).isConstQualified() || + VDecl->isExternC()))) Diag(VDecl->getLocation(), diag::warn_extern_init); // C99 6.7.8p4. All file scoped initializers need to be constant. @@ -7155,7 +7897,7 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) { // for-range-declaration cannot be given a storage class specifier. int Error = -1; - switch (VD->getStorageClassAsWritten()) { + switch (VD->getStorageClass()) { case SC_None: break; case SC_Extern: @@ -7206,7 +7948,10 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } if (var->isThisDeclarationADefinition() && - var->getLinkage() == ExternalLinkage) { + var->hasExternalLinkage() && + getDiagnostics().getDiagnosticLevel( + diag::warn_missing_variable_declarations, + var->getLocation())) { // Find a previous declaration that's not a definition. VarDecl *prev = var->getPreviousDecl(); while (prev && prev->isThisDeclarationADefinition()) @@ -7230,12 +7975,13 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // Regardless, we don't want to ignore array nesting when // constructing this copy. if (type->isStructureOrClassType()) { + EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated); SourceLocation poi = var->getLocation(); Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi); - ExprResult result = - PerformCopyInitialization( - InitializedEntity::InitializeBlock(poi, type, false), - poi, Owned(varRef)); + ExprResult result + = PerformMoveOrCopyInitialization( + InitializedEntity::InitializeBlock(poi, type, false), + var, var->getType(), varRef, /*AllowNRVO=*/true); if (!result.isInvalid()) { result = MaybeCreateExprWithCleanups(result); Expr *init = result.takeAs<Expr>(); @@ -7259,7 +8005,7 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { << Init->getSourceRange(); if (var->isConstexpr()) { - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; if (!var->evaluateValue(Notes) || !var->isInitICE()) { SourceLocation DiagLoc = var->getLocation(); // If the note doesn't add any useful information other than a source @@ -7294,40 +8040,52 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) { // Note that we are no longer parsing the initializer for this declaration. ParsingInitForAutoVars.erase(ThisDecl); + VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDecl); + if (!VD) + return; + + const DeclContext *DC = VD->getDeclContext(); + // If there's a #pragma GCC visibility in scope, and this isn't a class + // member, set the visibility of this variable. + if (!DC->isRecord() && VD->hasExternalLinkage()) + AddPushedVisibilityAttribute(VD); + + if (VD->isFileVarDecl()) + MarkUnusedFileScopedDecl(VD); + // Now we have parsed the initializer and can update the table of magic // tag values. - if (ThisDecl && ThisDecl->hasAttr<TypeTagForDatatypeAttr>()) { - const VarDecl *VD = dyn_cast<VarDecl>(ThisDecl); - if (VD && VD->getType()->isIntegralOrEnumerationType()) { - for (specific_attr_iterator<TypeTagForDatatypeAttr> - I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(), - E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>(); - I != E; ++I) { - const Expr *MagicValueExpr = VD->getInit(); - if (!MagicValueExpr) { - continue; - } - llvm::APSInt MagicValueInt; - if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) { - Diag(I->getRange().getBegin(), - diag::err_type_tag_for_datatype_not_ice) - << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); - continue; - } - if (MagicValueInt.getActiveBits() > 64) { - Diag(I->getRange().getBegin(), - diag::err_type_tag_for_datatype_too_large) - << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); - continue; - } - uint64_t MagicValue = MagicValueInt.getZExtValue(); - RegisterTypeTagForDatatype(I->getArgumentKind(), - MagicValue, - I->getMatchingCType(), - I->getLayoutCompatible(), - I->getMustBeNull()); - } + if (!VD->hasAttr<TypeTagForDatatypeAttr>() || + !VD->getType()->isIntegralOrEnumerationType()) + return; + + for (specific_attr_iterator<TypeTagForDatatypeAttr> + I = ThisDecl->specific_attr_begin<TypeTagForDatatypeAttr>(), + E = ThisDecl->specific_attr_end<TypeTagForDatatypeAttr>(); + I != E; ++I) { + const Expr *MagicValueExpr = VD->getInit(); + if (!MagicValueExpr) { + continue; + } + llvm::APSInt MagicValueInt; + if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) { + Diag(I->getRange().getBegin(), + diag::err_type_tag_for_datatype_not_ice) + << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); + continue; + } + if (MagicValueInt.getActiveBits() > 64) { + Diag(I->getRange().getBegin(), + diag::err_type_tag_for_datatype_too_large) + << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); + continue; } + uint64_t MagicValue = MagicValueInt.getZExtValue(); + RegisterTypeTagForDatatype(I->getArgumentKind(), + MagicValue, + I->getMatchingCType(), + I->getLayoutCompatible(), + I->getMustBeNull()); } } @@ -7343,6 +8101,10 @@ Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (Decl *D = Group[i]) Decls.push_back(D); + if (DeclSpec::isDeclRep(DS.getTypeSpecType())) + if (const TagDecl *Tag = dyn_cast_or_null<TagDecl>(DS.getRepAsDecl())) + getASTContext().addUnnamedTag(Tag); + return BuildDeclaratorGroup(Decls.data(), Decls.size(), DS.getTypeSpecType() == DeclSpec::TST_auto); } @@ -7449,14 +8211,11 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'. // C++03 [dcl.stc]p2 also permits 'auto'. VarDecl::StorageClass StorageClass = SC_None; - VarDecl::StorageClass StorageClassAsWritten = SC_None; if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { StorageClass = SC_Register; - StorageClassAsWritten = SC_Register; } else if (getLangOpts().CPlusPlus && DS.getStorageClassSpec() == DeclSpec::SCS_auto) { StorageClass = SC_Auto; - StorageClassAsWritten = SC_Auto; } else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified) { Diag(DS.getStorageClassSpecLoc(), diag::err_invalid_storage_class_in_func_decl); @@ -7469,7 +8228,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) << 0; - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); QualType parmDeclType = TInfo->getType(); @@ -7529,7 +8288,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { D.getLocStart(), D.getIdentifierLoc(), II, parmDeclType, TInfo, - StorageClass, StorageClassAsWritten); + StorageClass); if (D.isInvalidType()) New->setInvalidDecl(); @@ -7568,7 +8327,7 @@ ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, 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); + SC_None, 0); Param->setImplicit(); return Param; } @@ -7621,8 +8380,7 @@ void Sema::DiagnoseSizeOfParametersAndReturnValue(ParmVarDecl * const *Param, ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, SourceLocation NameLoc, IdentifierInfo *Name, QualType T, TypeSourceInfo *TSInfo, - VarDecl::StorageClass StorageClass, - VarDecl::StorageClass StorageClassAsWritten) { + VarDecl::StorageClass StorageClass) { // In ARC, infer a lifetime qualifier for appropriate parameter types. if (getLangOpts().ObjCAutoRefCount && T.getObjCLifetime() == Qualifiers::OCL_None && @@ -7649,8 +8407,7 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc, ParmVarDecl *New = ParmVarDecl::Create(Context, DC, StartLoc, NameLoc, Name, Context.getAdjustedParameterType(T), TSInfo, - StorageClass, StorageClassAsWritten, - 0); + StorageClass, 0); // Parameters can not be abstract class types. // For record types, this is done by the AbstractClassUsageDiagnoser once @@ -7730,7 +8487,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { return ActOnStartOfFunctionDef(FnBodyScope, DP); } -static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { +static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD, + const FunctionDecl*& PossibleZeroParamPrototype) { // Don't warn about invalid declarations. if (FD->isInvalidDecl()) return false; @@ -7772,6 +8530,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD) { continue; MissingPrototype = !Prev->getType()->isFunctionProtoType(); + if (FD->getNumParams() == 0) + PossibleZeroParamPrototype = Prev; break; } @@ -7837,8 +8597,22 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // 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)) + const FunctionDecl *PossibleZeroParamPrototype = 0; + if (ShouldWarnAboutMissingPrototype(FD, PossibleZeroParamPrototype)) { Diag(FD->getLocation(), diag::warn_missing_prototype) << FD; + + if (PossibleZeroParamPrototype) { + // We found a declaration that is not a prototype, + // but that could be a zero-parameter prototype + TypeSourceInfo* TI = PossibleZeroParamPrototype->getTypeSourceInfo(); + TypeLoc TL = TI->getTypeLoc(); + if (FunctionNoProtoTypeLoc FTL = TL.getAs<FunctionNoProtoTypeLoc>()) + Diag(PossibleZeroParamPrototype->getLocation(), + diag::note_declaration_not_a_prototype) + << PossibleZeroParamPrototype + << FixItHint::CreateInsertion(FTL.getRParenLoc(), "void"); + } + } if (FnBodyScope) PushDeclContext(FnBodyScope, FD); @@ -7913,7 +8687,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; FD->setInvalidDecl(); - return FD; + return D; } // Visual C++ appears to not think this is an issue, so only issue @@ -7930,7 +8704,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // We want to attach documentation to original Decl (which might be // a function template). ActOnDocumentableDecl(D); - return FD; + return D; } /// \brief Given the set of return statements within a function body, @@ -7967,6 +8741,33 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { const_cast<VarDecl*>(NRVOCandidate)->setNRVOVariable(true); } +bool Sema::canSkipFunctionBody(Decl *D) { + if (!Consumer.shouldSkipFunctionBody(D)) + return false; + + if (isa<ObjCMethodDecl>(D)) + return true; + + FunctionDecl *FD = 0; + if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) + FD = FTD->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(D); + + // We cannot skip the body of a function (or function template) which is + // constexpr, since we may need to evaluate its body in order to parse the + // rest of the file. + return !FD->isConstexpr(); +} + +Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) { + if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(Decl)) + FD->setHasSkippedBody(); + else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(Decl)) + MD->setHasSkippedBody(); + return ActOnFinishFunctionBody(Decl, 0); +} + Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { return ActOnFinishFunctionBody(D, BodyArg, false); } @@ -7986,6 +8787,18 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (FD) { FD->setBody(Body); + // The only way to be included in UndefinedButUsed is if there is an + // ODR use before the definition. Avoid the expensive map lookup if this + // is the first declaration. + if (FD->getPreviousDecl() != 0 && FD->getPreviousDecl()->isUsed()) { + if (FD->getLinkage() != ExternalLinkage) + UndefinedButUsed.erase(FD); + else if (FD->isInlined() && + (LangOpts.CPlusPlus || !LangOpts.GNUInline) && + (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>())) + UndefinedButUsed.erase(FD); + } + // If the function implicitly returns zero (like 'main') or is naked, // don't complain about missing return statements. if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>()) @@ -8068,7 +8881,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (PP.getDiagnostics().hasErrorOccurred() || PP.getDiagnostics().getSuppressAllDiagnostics()) { DiscardCleanupsInEvaluationContext(); - } else if (!isa<FunctionTemplateDecl>(dcl)) { + } + if (!PP.getDiagnostics().hasUncompilableErrorOccurred() && + !isa<FunctionTemplateDecl>(dcl)) { // Since the body is valid, issue any analysis-based warnings that are // enabled. ActivePolicy = &WP; @@ -8125,8 +8940,8 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, // this name as a function or variable. If so, use that // (non-visible) declaration, and complain about it. llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos - = findLocallyScopedExternalDecl(&II); - if (Pos != LocallyScopedExternalDecls.end()) { + = findLocallyScopedExternCDecl(&II); + if (Pos != LocallyScopedExternCDecls.end()) { Diag(Loc, diag::warn_use_out_of_scope_declaration) << Pos->second; Diag(Pos->second->getLocation(), diag::note_previous_declaration); return Pos->second; @@ -8202,7 +9017,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, DeclContext *PrevDC = CurContext; CurContext = Context.getTranslationUnitDecl(); - FunctionDecl *FD = dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D)); + FunctionDecl *FD = cast<FunctionDecl>(ActOnDeclarator(TUScope, D)); FD->setImplicit(); CurContext = PrevDC; @@ -8376,9 +9191,13 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); QualType T = TI->getType(); - if (T->isDependentType() || T->isIntegralType(Context)) + if (T->isDependentType()) return false; + if (const BuiltinType *BT = T->getAs<BuiltinType>()) + if (BT->isInteger()) + return false; + Diag(UnderlyingLoc, diag::err_enum_invalid_underlying) << T; return true; } @@ -8575,6 +9394,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, TUK == TUK_Friend, isExplicitSpecialization, Invalid)) { + if (Kind == TTK_Enum) { + Diag(KWLoc, diag::err_enum_template); + return 0; + } + if (TemplateParams->size() > 0) { // This is a declaration or definition of a class template (which may // be a member of another template). @@ -8703,6 +9527,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // shouldn't be diagnosing. LookupName(Previous, S); + // When declaring or defining a tag, ignore ambiguities introduced + // by types using'ed into this scope. if (Previous.isAmbiguous() && (TUK == TUK_Definition || TUK == TUK_Declaration)) { LookupResult::Filter F = Previous.makeFilter(); @@ -8713,6 +9539,27 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } F.done(); } + + // C++11 [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. + // + // Does it matter that this should be by scope instead of by + // semantic context? + if (!Previous.empty() && TUK == TUK_Friend) { + DeclContext *EnclosingNS = SearchDC->getEnclosingNamespaceContext(); + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *ND = F.next(); + DeclContext *DC = ND->getDeclContext()->getRedeclContext(); + if (DC->isFileContext() && !EnclosingNS->Encloses(ND->getDeclContext())) + F.erase(); + } + F.done(); + } // Note: there used to be some attempt at recovery here. if (Previous.isAmbiguous()) @@ -9070,7 +9917,8 @@ CreateNewDecl: // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; - if (getLangOpts().CPlusPlus0x && cast<EnumDecl>(New)->isFixed()) { + if ((getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && + cast<EnumDecl>(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. } @@ -9250,7 +10098,9 @@ CreateNewDecl: AddPushedVisibilityAttribute(New); OwnedDecl = true; - return New; + // In C++, don't return an invalid declaration. We can't recover well from + // the cases where we make the type anonymous. + return (Invalid && getLangOpts().CPlusPlus) ? 0 : New; } void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) { @@ -9330,7 +10180,11 @@ void Sema::ActOnTagFinishDefinition(Scope *S, Decl *TagD, // Exit this scope of this tag's definition. PopDeclContext(); - + + if (getCurLexicalContext()->isObjCContainer() && + Tag->getDeclContext()->isFileContext()) + Tag->setTopLevelDeclInObjCContainer(); + // Notify the consumer that we've defined a tag. Consumer.HandleTagDeclDefinition(Tag); } @@ -9479,14 +10333,24 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, } } - DiagnoseFunctionSpecifiers(D); + // TR 18037 does not allow fields to be declared with address spaces. + if (T.getQualifiers().hasAddressSpace()) { + Diag(Loc, diag::err_field_with_address_space); + D.setInvalidType(); + } + + // OpenCL 1.2 spec, s6.9 r: + // The event type cannot be used to declare a structure or union field. + if (LangOpts.OpenCL && T->isEventT()) { + Diag(Loc, diag::err_event_t_struct_field); + D.setInvalidType(); + } + + DiagnoseFunctionSpecifiers(D.getDeclSpec()); if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); - if (D.getDeclSpec().isConstexprSpecified()) - Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) - << 2; - + // Check to see if this name was declared as a member previously NamedDecl *PrevDecl = 0; LookupResult Previous(*this, II, Loc, LookupMemberName, ForRedeclaration); @@ -9587,6 +10451,12 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, } } + // OpenCL v1.2 s6.9.c: bitfields are not supported. + if (BitWidth && getLangOpts().OpenCL) { + Diag(Loc, diag::err_opencl_bitfields); + 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()) { @@ -9686,10 +10556,14 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // FIXME: We need to pass in the attributes given an AST // representation, not a parser representation. - if (D) + if (D) { // FIXME: What to pass instead of TUScope? ProcessDeclAttributes(TUScope, NewFD, *D); + if (NewFD->hasAttrs()) + CheckAlignasUnderalignment(NewFD); + } + // In auto-retain/release, infer strong retension for fields of // retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewFD)) @@ -9711,24 +10585,29 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { QualType EltTy = Context.getBaseElementType(FD->getType()); if (const RecordType *RT = EltTy->getAs<RecordType>()) { - CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); + 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()) + // We're required to check for any non-trivial constructors. Since the + // implicit default constructor is suppressed if there are any + // user-declared constructors, we just need to check that there is a + // trivial default constructor and a trivial copy constructor. (We don't + // worry about move constructors here, since this is a C++98 check.) + if (RDecl->hasNonTrivialCopyConstructor()) member = CXXCopyConstructor; else if (!RDecl->hasTrivialDefaultConstructor()) member = CXXDefaultConstructor; - else if (!RDecl->hasTrivialCopyAssignment()) + else if (RDecl->hasNonTrivialCopyAssignment()) member = CXXCopyAssignment; - else if (!RDecl->hasTrivialDestructor()) + else if (RDecl->hasNonTrivialDestructor()) member = CXXDestructor; if (member != CXXInvalid) { - if (!getLangOpts().CPlusPlus0x && + if (!getLangOpts().CPlusPlus11 && getLangOpts().ObjCAutoRefCount && RDecl->hasObjectMember()) { // Objective-C++ ARC: it is an error to have a non-trivial field of // a union. However, system headers in Objective-C programs @@ -9744,192 +10623,17 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { } } - Diag(FD->getLocation(), getLangOpts().CPlusPlus0x ? + Diag(FD->getLocation(), getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_nontrivial_union_or_anon_struct_member : diag::err_illegal_union_or_anon_struct_member) << (int)FD->getParent()->isUnion() << FD->getDeclName() << member; - DiagnoseNontrivial(RT, member); - return !getLangOpts().CPlusPlus0x; - } - } - } - - return false; -} - -/// If the given constructor is user-declared, produce a diagnostic explaining -/// that it makes the class non-trivial. -static bool diagnoseNonTrivialUserDeclaredCtor(Sema &S, QualType QT, - CXXConstructorDecl *CD, - Sema::CXXSpecialMember CSM) { - if (CD->isImplicit()) - return false; - - SourceLocation CtorLoc = CD->getLocation(); - S.Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << CSM; - return true; -} - -/// 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) - if (diagnoseNonTrivialUserDeclaredCtor(*this, QT, *CI, member)) - return; - - // No user-delcared constructors; look for constructor templates. - typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> - tmpl_iter; - for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); - TI != TE; ++TI) { - CXXConstructorDecl *CD = - dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl()); - if (CD && diagnoseNonTrivialUserDeclaredCtor(*this, QT, CD, member)) - 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()) { - SourceLocation AssignLoc = - RD->getCopyAssignmentOperator(0)->getLocation(); - Diag(AssignLoc, 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->getLocStart(); - 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->getLocStart(); - 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: - llvm_unreachable("unexpected special member"); - } - - // 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->getLocStart(); - 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; - } - } - - if (EltTy->isObjCLifetimeType()) { - switch (EltTy.getObjCLifetime()) { - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - break; - - case Qualifiers::OCL_Autoreleasing: - case Qualifiers::OCL_Weak: - case Qualifiers::OCL_Strong: - Diag(fi->getLocation(), diag::note_nontrivial_objc_ownership) - << QT << EltTy.getObjCLifetime(); - return; + DiagnoseNontrivial(RDecl, member); + return !getLangOpts().CPlusPlus11; } } } - llvm_unreachable("found no explanation for non-trivial member"); + return false; } /// TranslateIvarVisibility - Translate visibility from a token ID to an @@ -10058,8 +10762,8 @@ Decl *Sema::ActOnIvar(Scope *S, } /// 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, +/// 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, SmallVectorImpl<Decl *> &AllIvarDecls) { @@ -10259,52 +10963,54 @@ void Sema::ActOnFields(Scope* S, } if (Record && FDTTy->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); + if (Record && FDTTy->getDecl()->hasVolatileMember()) + Record->setHasVolatileMember(true); } else if (FDTy->isObjCObjectType()) { /// A field cannot be an Objective-c object Diag(FD->getLocation(), diag::err_statically_allocated_object) << FixItHint::CreateInsertion(FD->getLocation(), "*"); QualType T = Context.getObjCObjectPointerType(FD->getType()); FD->setType(T); - } else if (!getLangOpts().CPlusPlus) { - if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported) { - // It's an error in ARC if a field has lifetime. - // We don't want to report this in a system header, though, - // so we just make the field unavailable. - // FIXME: that's really not sufficient; we need to make the type - // itself invalid to, say, initialize or copy. - QualType T = FD->getType(); - Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); - if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { - SourceLocation loc = FD->getLocation(); - if (getSourceManager().isInSystemHeader(loc)) { - if (!FD->hasAttr<UnavailableAttr>()) { - FD->addAttr(new (Context) UnavailableAttr(loc, Context, - "this system field has retaining ownership")); - } - } else { - Diag(FD->getLocation(), diag::err_arc_objc_object_in_struct) - << T->isBlockPointerType(); + } else if (getLangOpts().ObjCAutoRefCount && Record && !ARCErrReported && + (!getLangOpts().CPlusPlus || Record->isUnion())) { + // It's an error in ARC if a field has lifetime. + // We don't want to report this in a system header, though, + // so we just make the field unavailable. + // FIXME: that's really not sufficient; we need to make the type + // itself invalid to, say, initialize or copy. + QualType T = FD->getType(); + Qualifiers::ObjCLifetime lifetime = T.getObjCLifetime(); + if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone) { + SourceLocation loc = FD->getLocation(); + if (getSourceManager().isInSystemHeader(loc)) { + if (!FD->hasAttr<UnavailableAttr>()) { + FD->addAttr(new (Context) UnavailableAttr(loc, Context, + "this system field has retaining ownership")); } - ARCErrReported = true; + } else { + Diag(FD->getLocation(), diag::err_arc_objc_object_in_tag) + << T->isBlockPointerType() << Record->getTagKind(); } + ARCErrReported = true; } - else if (getLangOpts().ObjC1 && + } else if (getLangOpts().ObjC1 && getLangOpts().getGC() != LangOptions::NonGC && Record && !Record->hasObjectMember()) { - if (FD->getType()->isObjCObjectPointerType() || - FD->getType().isObjCGCStrong()) + if (FD->getType()->isObjCObjectPointerType() || + FD->getType().isObjCGCStrong()) + Record->setHasObjectMember(true); + else if (Context.getAsArrayType(FD->getType())) { + QualType BaseType = Context.getBaseElementType(FD->getType()); + if (BaseType->isRecordType() && + BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); - else if (Context.getAsArrayType(FD->getType())) { - QualType BaseType = Context.getBaseElementType(FD->getType()); - if (BaseType->isRecordType() && - BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()) - Record->setHasObjectMember(true); - else if (BaseType->isObjCObjectPointerType() || - BaseType.isObjCGCStrong()) - Record->setHasObjectMember(true); - } + else if (BaseType->isObjCObjectPointerType() || + BaseType.isObjCGCStrong()) + Record->setHasObjectMember(true); } } + if (Record && FD->getType().isVolatileQualified()) + Record->setHasVolatileMember(true); // Keep track of the number of named members. if (FD->getIdentifier()) ++NumNamedMembers; @@ -10316,14 +11022,14 @@ void Sema::ActOnFields(Scope* S, 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()); + for (CXXRecordDecl::conversion_iterator + I = CXXRecord->conversion_begin(), + E = CXXRecord->conversion_end(); I != E; ++I) + I.setAccess((*I)->getAccess()); if (!CXXRecord->isDependentType()) { // Adjust user-defined destructor exception spec. - if (getLangOpts().CPlusPlus0x && + if (getLangOpts().CPlusPlus11 && CXXRecord->hasUserDeclaredDestructor()) AdjustDestructorExceptionSpec(CXXRecord,CXXRecord->getDestructor()); @@ -10376,6 +11082,8 @@ void Sema::ActOnFields(Scope* S, if (!Completed) Record->completeDefinition(); + if (Record->hasAttrs()) + CheckAlignasUnderalignment(Record); } else { ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(RecFields.data()); @@ -10418,11 +11126,12 @@ void Sema::ActOnFields(Scope* S, Diag(ClsIvar->getLocation(), diag::note_previous_definition); continue; } - for (const ObjCCategoryDecl *ClsExtDecl = - IDecl->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { - if (const ObjCIvarDecl *ClsExtIvar = - ClsExtDecl->getIvarDecl(ClsFields[i]->getIdentifier())) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = IDecl->known_extensions_begin(), + ExtEnd = IDecl->known_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (const ObjCIvarDecl *ClsExtIvar + = Ext->getIvarDecl(ClsFields[i]->getIdentifier())) { Diag(ClsFields[i]->getLocation(), diag::err_duplicate_ivar_declaration); Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); @@ -10503,7 +11212,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EltTy = Context.DependentTy; else { SourceLocation ExpLoc; - if (getLangOpts().CPlusPlus0x && Enum->isFixed() && + if (getLangOpts().CPlusPlus11 && Enum->isFixed() && !getLangOpts().MicrosoftMode) { // C++11 [dcl.enum]p5: If the underlying type is fixed, [...] the // constant-expression in the enumerator-definition shall be a converted @@ -10722,6 +11431,182 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, return New; } +// Returns true when the enum initial expression does not trigger the +// duplicate enum warning. A few common cases are exempted as follows: +// Element2 = Element1 +// Element2 = Element1 + 1 +// Element2 = Element1 - 1 +// Where Element2 and Element1 are from the same enum. +static bool ValidDuplicateEnum(EnumConstantDecl *ECD, EnumDecl *Enum) { + Expr *InitExpr = ECD->getInitExpr(); + if (!InitExpr) + return true; + InitExpr = InitExpr->IgnoreImpCasts(); + + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) { + if (!BO->isAdditiveOp()) + return true; + IntegerLiteral *IL = dyn_cast<IntegerLiteral>(BO->getRHS()); + if (!IL) + return true; + if (IL->getValue() != 1) + return true; + + InitExpr = BO->getLHS(); + } + + // This checks if the elements are from the same enum. + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InitExpr); + if (!DRE) + return true; + + EnumConstantDecl *EnumConstant = dyn_cast<EnumConstantDecl>(DRE->getDecl()); + if (!EnumConstant) + return true; + + if (cast<EnumDecl>(TagDecl::castFromDeclContext(ECD->getDeclContext())) != + Enum) + return true; + + return false; +} + +struct DupKey { + int64_t val; + bool isTombstoneOrEmptyKey; + DupKey(int64_t val, bool isTombstoneOrEmptyKey) + : val(val), isTombstoneOrEmptyKey(isTombstoneOrEmptyKey) {} +}; + +static DupKey GetDupKey(const llvm::APSInt& Val) { + return DupKey(Val.isSigned() ? Val.getSExtValue() : Val.getZExtValue(), + false); +} + +struct DenseMapInfoDupKey { + static DupKey getEmptyKey() { return DupKey(0, true); } + static DupKey getTombstoneKey() { return DupKey(1, true); } + static unsigned getHashValue(const DupKey Key) { + return (unsigned)(Key.val * 37); + } + static bool isEqual(const DupKey& LHS, const DupKey& RHS) { + return LHS.isTombstoneOrEmptyKey == RHS.isTombstoneOrEmptyKey && + LHS.val == RHS.val; + } +}; + +// Emits a warning when an element is implicitly set a value that +// a previous element has already been set to. +static void CheckForDuplicateEnumValues(Sema &S, Decl **Elements, + unsigned NumElements, EnumDecl *Enum, + QualType EnumType) { + if (S.Diags.getDiagnosticLevel(diag::warn_duplicate_enum_values, + Enum->getLocation()) == + DiagnosticsEngine::Ignored) + return; + // Avoid anonymous enums + if (!Enum->getIdentifier()) + return; + + // Only check for small enums. + if (Enum->getNumPositiveBits() > 63 || Enum->getNumNegativeBits() > 64) + return; + + typedef SmallVector<EnumConstantDecl *, 3> ECDVector; + typedef SmallVector<ECDVector *, 3> DuplicatesVector; + + typedef llvm::PointerUnion<EnumConstantDecl*, ECDVector*> DeclOrVector; + typedef llvm::DenseMap<DupKey, DeclOrVector, DenseMapInfoDupKey> + ValueToVectorMap; + + DuplicatesVector DupVector; + ValueToVectorMap EnumMap; + + // Populate the EnumMap with all values represented by enum constants without + // an initialier. + for (unsigned i = 0; i < NumElements; ++i) { + EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]); + + // Null EnumConstantDecl means a previous diagnostic has been emitted for + // this constant. Skip this enum since it may be ill-formed. + if (!ECD) { + return; + } + + if (ECD->getInitExpr()) + continue; + + DupKey Key = GetDupKey(ECD->getInitVal()); + DeclOrVector &Entry = EnumMap[Key]; + + // First time encountering this value. + if (Entry.isNull()) + Entry = ECD; + } + + // Create vectors for any values that has duplicates. + for (unsigned i = 0; i < NumElements; ++i) { + EnumConstantDecl *ECD = cast<EnumConstantDecl>(Elements[i]); + if (!ValidDuplicateEnum(ECD, Enum)) + continue; + + DupKey Key = GetDupKey(ECD->getInitVal()); + + DeclOrVector& Entry = EnumMap[Key]; + if (Entry.isNull()) + continue; + + if (EnumConstantDecl *D = Entry.dyn_cast<EnumConstantDecl*>()) { + // Ensure constants are different. + if (D == ECD) + continue; + + // Create new vector and push values onto it. + ECDVector *Vec = new ECDVector(); + Vec->push_back(D); + Vec->push_back(ECD); + + // Update entry to point to the duplicates vector. + Entry = Vec; + + // Store the vector somewhere we can consult later for quick emission of + // diagnostics. + DupVector.push_back(Vec); + continue; + } + + ECDVector *Vec = Entry.get<ECDVector*>(); + // Make sure constants are not added more than once. + if (*Vec->begin() == ECD) + continue; + + Vec->push_back(ECD); + } + + // Emit diagnostics. + for (DuplicatesVector::iterator DupVectorIter = DupVector.begin(), + DupVectorEnd = DupVector.end(); + DupVectorIter != DupVectorEnd; ++DupVectorIter) { + ECDVector *Vec = *DupVectorIter; + assert(Vec->size() > 1 && "ECDVector should have at least 2 elements."); + + // Emit warning for one enum constant. + ECDVector::iterator I = Vec->begin(); + S.Diag((*I)->getLocation(), diag::warn_duplicate_enum_values) + << (*I)->getName() << (*I)->getInitVal().toString(10) + << (*I)->getSourceRange(); + ++I; + + // Emit one note for each of the remaining enum constants with + // the same value. + for (ECDVector::iterator E = Vec->end(); I != E; ++I) + S.Diag((*I)->getLocation(), diag::note_duplicate_element) + << (*I)->getName() << (*I)->getInitVal().toString(10) + << (*I)->getSourceRange(); + delete Vec; + } +} + void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, SourceLocation RBraceLoc, Decl *EnumDeclX, Decl **Elements, unsigned NumElements, @@ -10944,6 +11829,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // it needs to go into the function scope. if (InFunctionDeclarator) DeclsInPrototypeScope.push_back(Enum); + + CheckForDuplicateEnumValues(*this, Elements, NumElements, Enum, EnumType); + + // Now that the enum type is defined, ensure it's not been underaligned. + if (Enum->hasAttrs()) + CheckAlignasUnderalignment(Enum); } Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, @@ -10967,7 +11858,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, if (!Mod) return true; - llvm::SmallVector<SourceLocation, 2> IdentifierLocs; + SmallVector<SourceLocation, 2> IdentifierLocs; Module *ModCheck = Mod; for (unsigned I = 0, N = Path.size(); I != N; ++I) { // If we've run out of module parents, just drop the remaining identifiers. @@ -10987,6 +11878,19 @@ DeclResult Sema::ActOnModuleImport(SourceLocation AtLoc, return Import; } +void Sema::createImplicitModuleImport(SourceLocation Loc, Module *Mod) { + // Create the implicit import declaration. + TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl(); + ImportDecl *ImportD = ImportDecl::CreateImplicit(getASTContext(), TU, + Loc, Mod, Loc); + TU->addDecl(ImportD); + Consumer.HandleImplicitImportDecl(ImportD); + + // Make the module visible. + PP.getModuleLoader().makeModuleVisible(Mod, Module::AllVisible, Loc, + /*Complain=*/false); +} + void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, IdentifierInfo* AliasName, SourceLocation PragmaLoc, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index e326a20..982e7a5 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -16,14 +16,17 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/Mangle.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" #include "llvm/ADT/StringExtras.h" using namespace clang; using namespace sema; @@ -37,6 +40,7 @@ enum AttributeDeclKind { ExpectedFunctionOrMethod, ExpectedParameter, ExpectedFunctionMethodOrBlock, + ExpectedFunctionMethodOrClass, ExpectedFunctionMethodOrParameter, ExpectedClass, ExpectedVariable, @@ -44,7 +48,11 @@ enum AttributeDeclKind { ExpectedVariableFunctionOrLabel, ExpectedFieldOrGlobalVar, ExpectedStruct, - ExpectedTLSVar + ExpectedVariableFunctionOrTag, + ExpectedTLSVar, + ExpectedVariableOrField, + ExpectedVariableFieldOrTag, + ExpectedTypeOrNamespace }; //===----------------------------------------------------------------------===// @@ -293,12 +301,12 @@ static bool isIntOrBool(Expr *Exp) { static bool threadSafetyCheckIsSmartPointer(Sema &S, const RecordType* RT) { DeclContextLookupConstResult Res1 = RT->getDecl()->lookup( S.Context.DeclarationNames.getCXXOperatorName(OO_Star)); - if (Res1.first == Res1.second) + if (Res1.empty()) return false; DeclContextLookupConstResult Res2 = RT->getDecl()->lookup( S.Context.DeclarationNames.getCXXOperatorName(OO_Arrow)); - if (Res2.first == Res2.second) + if (Res2.empty()) return false; return true; @@ -503,18 +511,22 @@ static void handleGuardedVarAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkGuardedVarAttrCommon(S, D, Attr)) return; - D->addAttr(::new (S.Context) GuardedVarAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + GuardedVarAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handlePtGuardedVarAttr(Sema &S, Decl *D, - const AttributeList &Attr) { + const AttributeList &Attr) { if (!checkGuardedVarAttrCommon(S, D, Attr)) return; if (!threadSafetyCheckIsPointer(S, D, Attr)) return; - D->addAttr(::new (S.Context) PtGuardedVarAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PtGuardedVarAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static bool checkGuardedByAttrCommon(Sema &S, Decl *D, @@ -594,11 +606,13 @@ static void handleScopedLockableAttr(Sema &S, Decl *D, if (!checkLockableAttrCommon(S, D, Attr)) return; - D->addAttr(::new (S.Context) ScopedLockableAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ScopedLockableAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } -static void handleNoThreadSafetyAttr(Sema &S, Decl *D, - const AttributeList &Attr) { +static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D, + const AttributeList &Attr) { assert(!Attr.isInvalid()); if (!checkAttributeNumArgs(S, Attr, 0)) @@ -614,7 +628,7 @@ static void handleNoThreadSafetyAttr(Sema &S, Decl *D, S.Context)); } -static void handleNoAddressSafetyAttr(Sema &S, Decl *D, +static void handleNoSanitizeAddressAttr(Sema &S, Decl *D, const AttributeList &Attr) { assert(!Attr.isInvalid()); @@ -622,13 +636,48 @@ static void handleNoAddressSafetyAttr(Sema &S, Decl *D, return; if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) + NoSanitizeAddressAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +static void handleNoSanitizeMemory(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(), + S.Context)); +} + +static void handleNoSanitizeThread(Sema &S, Decl *D, + const AttributeList &Attr) { + assert(!Attr.isInvalid()); + + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionOrMethod; return; } - D->addAttr(::new (S.Context) NoAddressSafetyAnalysisAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(), + S.Context)); } static bool checkAcquireOrderAttrCommon(Sema &S, Decl *D, @@ -673,8 +722,10 @@ static void handleAcquiredAfterAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) AcquiredAfterAttr(Attr.getRange(), S.Context, - StartArg, Args.size())); + D->addAttr(::new (S.Context) + AcquiredAfterAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static void handleAcquiredBeforeAttr(Sema &S, Decl *D, @@ -684,8 +735,10 @@ static void handleAcquiredBeforeAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) AcquiredBeforeAttr(Attr.getRange(), S.Context, - StartArg, Args.size())); + D->addAttr(::new (S.Context) + AcquiredBeforeAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static bool checkLockFunAttrCommon(Sema &S, Decl *D, @@ -716,9 +769,9 @@ static void handleSharedLockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) SharedLockFunctionAttr(Attr.getRange(), - S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + SharedLockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, @@ -729,9 +782,10 @@ static void handleExclusiveLockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) ExclusiveLockFunctionAttr(Attr.getRange(), - S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + ExclusiveLockFunctionAttr(Attr.getRange(), S.Context, + StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static bool checkTryLockFunAttrCommon(Sema &S, Decl *D, @@ -768,10 +822,10 @@ static void handleSharedTrylockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) SharedTrylockFunctionAttr(Attr.getRange(), - S.Context, - Attr.getArg(0), - StartArg, Size)); + D->addAttr(::new (S.Context) + SharedTrylockFunctionAttr(Attr.getRange(), S.Context, + Attr.getArg(0), StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, @@ -782,10 +836,10 @@ static void handleExclusiveTrylockFunctionAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) ExclusiveTrylockFunctionAttr(Attr.getRange(), - S.Context, - Attr.getArg(0), - StartArg, Size)); + D->addAttr(::new (S.Context) + ExclusiveTrylockFunctionAttr(Attr.getRange(), S.Context, + Attr.getArg(0), StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static bool checkLocksRequiredCommon(Sema &S, Decl *D, @@ -817,10 +871,10 @@ static void handleExclusiveLocksRequiredAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) ExclusiveLocksRequiredAttr(Attr.getRange(), - S.Context, - StartArg, - Args.size())); + D->addAttr(::new (S.Context) + ExclusiveLocksRequiredAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static void handleSharedLocksRequiredAttr(Sema &S, Decl *D, @@ -830,10 +884,10 @@ static void handleSharedLocksRequiredAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) SharedLocksRequiredAttr(Attr.getRange(), - S.Context, - StartArg, - Args.size())); + D->addAttr(::new (S.Context) + SharedLocksRequiredAttr(Attr.getRange(), S.Context, + StartArg, Args.size(), + Attr.getAttributeSpellingListIndex())); } static void handleUnlockFunAttr(Sema &S, Decl *D, @@ -854,8 +908,9 @@ static void handleUnlockFunAttr(Sema &S, Decl *D, unsigned Size = Args.size(); Expr **StartArg = Size == 0 ? 0 : &Args[0]; - D->addAttr(::new (S.Context) UnlockFunctionAttr(Attr.getRange(), S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + UnlockFunctionAttr(Attr.getRange(), S.Context, StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleLockReturnedAttr(Sema &S, Decl *D, @@ -878,8 +933,9 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, if (Size == 0) return; - D->addAttr(::new (S.Context) LockReturnedAttr(Attr.getRange(), S.Context, - Args[0])); + D->addAttr(::new (S.Context) + LockReturnedAttr(Attr.getRange(), S.Context, Args[0], + Attr.getAttributeSpellingListIndex())); } static void handleLocksExcludedAttr(Sema &S, Decl *D, @@ -903,54 +959,24 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D, return; Expr **StartArg = &Args[0]; - D->addAttr(::new (S.Context) LocksExcludedAttr(Attr.getRange(), S.Context, - StartArg, Size)); + D->addAttr(::new (S.Context) + LocksExcludedAttr(Attr.getRange(), S.Context, StartArg, Size, + Attr.getAttributeSpellingListIndex())); } static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { - TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(D); - if (tDecl == 0) { + TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D); + if (TD == 0) { + // __attribute__((ext_vector_type(N))) can only be applied to typedefs + // and type-ids. 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; - SourceLocation TemplateKWLoc; - UnqualifiedId id; - id.setIdentifier(Attr.getParameterName(), Attr.getLoc()); - - ExprResult Size = S.ActOnIdExpression(scope, SS, TemplateKWLoc, id, - false, false); - if (Size.isInvalid()) - return; - - sizeExpr = Size.get(); - } else { - // check the attribute arguments. - if (!checkAttributeNumArgs(S, Attr, 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); - } + // Remember this typedef decl, we will need it later for diagnostics. + S.ExtVectorDecls.push_back(TD); } static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -969,14 +995,18 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << Attr.getName() << FD->getType(); else - FD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context)); + FD->addAttr(::new (S.Context) + PackedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) - RD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context)); + RD->addAttr(::new (S.Context) + MsStructAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -989,7 +1019,9 @@ static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) { // 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.getRange(), S.Context)); + D->addAttr(::new (S.Context) + IBActionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; } @@ -1030,7 +1062,9 @@ static void handleIBOutlet(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkIBOutletCommon(S, D, Attr)) return; - D->addAttr(::new (S.Context) IBOutletAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + IBOutletAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleIBOutletCollection(Sema &S, Decl *D, @@ -1064,8 +1098,10 @@ static void handleIBOutletCollection(Sema &S, Decl *D, S.Diag(Attr.getLoc(), diag::err_iboutletcollection_type) << II; return; } - D->addAttr(::new (S.Context) IBOutletCollectionAttr(Attr.getRange(),S.Context, - QT, Attr.getParameterLoc())); + D->addAttr(::new (S.Context) + IBOutletCollectionAttr(Attr.getRange(),S.Context, + QT, Attr.getParameterLoc(), + Attr.getAttributeSpellingListIndex())); } static void possibleTransparentUnionPointerType(QualType &T) { @@ -1096,7 +1132,11 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { // 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 NumArgs; + if (hasFunctionProto(D)) + NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; + else + NumArgs = 0; SmallVector<unsigned, 8> SizeArgs; @@ -1148,8 +1188,10 @@ static void handleAllocSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { << "alloc_size" << 0 /*function*/<< 1 /*pointer*/ << D->getSourceRange(); } - D->addAttr(::new (S.Context) AllocSizeAttr(Attr.getRange(), S.Context, - SizeArgs.data(), SizeArgs.size())); + D->addAttr(::new (S.Context) + AllocSizeAttr(Attr.getRange(), S.Context, + SizeArgs.data(), SizeArgs.size(), + Attr.getAttributeSpellingListIndex())); } static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1164,15 +1206,13 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { // 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 NumArgs = getFunctionOrMethodNumArgs(D) + HasImplicitThisParam; // The nonnull attribute only applies to pointers. SmallVector<unsigned, 10> NonNullArgs; - for (AttributeList::arg_iterator I=Attr.arg_begin(), - E=Attr.arg_end(); I!=E; ++I) { - - + 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); @@ -1219,11 +1259,11 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { // 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(); + for (unsigned i = 0, e = getFunctionOrMethodNumArgs(D); i != e; ++i) { + QualType T = getFunctionOrMethodArgType(D, i).getNonReferenceType(); possibleTransparentUnionPointerType(T); if (T->isAnyPointerType() || T->isBlockPointerType()) - NonNullArgs.push_back(I); + NonNullArgs.push_back(i); } // No pointer arguments? @@ -1236,11 +1276,12 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { } } - unsigned* start = &NonNullArgs[0]; + unsigned *start = &NonNullArgs[0]; unsigned size = NonNullArgs.size(); llvm::array_pod_sort(start, start + size); - D->addAttr(::new (S.Context) NonNullAttr(Attr.getRange(), S.Context, start, - size)); + D->addAttr(::new (S.Context) + NonNullAttr(Attr.getRange(), S.Context, start, size, + Attr.getAttributeSpellingListIndex())); } static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { @@ -1395,27 +1436,9 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { 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!"); + D->addAttr(::new (S.Context) + OwnershipAttr(AL.getLoc(), S.Context, K, Module, start, size, + AL.getAttributeSpellingListIndex())); } static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1468,11 +1491,6 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { // 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? @@ -1493,7 +1511,9 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) { Str->getString())); } - D->addAttr(::new (S.Context) WeakRefAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + WeakRefAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1521,7 +1541,8 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { // FIXME: check if target symbol exists in current file D->addAttr(::new (S.Context) AliasAttr(Attr.getRange(), S.Context, - Str->getString())); + Str->getString(), + Attr.getAttributeSpellingListIndex())); } static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1535,7 +1556,9 @@ static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) MinSizeAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + MinSizeAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1555,7 +1578,8 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) ColdAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1575,7 +1599,8 @@ static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) HotAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1589,7 +1614,9 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) NakedAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NakedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleAlwaysInlineAttr(Sema &S, Decl *D, @@ -1606,7 +1633,9 @@ static void handleAlwaysInlineAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) AlwaysInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + AlwaysInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleTLSModelAttr(Sema &S, Decl *D, @@ -1641,8 +1670,9 @@ static void handleTLSModelAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) TLSModelAttr(Attr.getRange(), S.Context, - Model)); + D->addAttr(::new (S.Context) + TLSModelAttr(Attr.getRange(), S.Context, Model, + Attr.getAttributeSpellingListIndex())); } static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1655,7 +1685,9 @@ static void handleMallocAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { QualType RetTy = FD->getResultType(); if (RetTy->isAnyPointerType() || RetTy->isBlockPointerType()) { - D->addAttr(::new (S.Context) MallocAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + MallocAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; } } @@ -1668,13 +1700,17 @@ static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 0)) return; - D->addAttr(::new (S.Context) MayAliasAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + MayAliasAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { assert(!Attr.isInvalid()); if (isa<VarDecl>(D)) - D->addAttr(::new (S.Context) NoCommonAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoCommonAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; @@ -1683,7 +1719,9 @@ static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) { assert(!Attr.isInvalid()); if (isa<VarDecl>(D)) - D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CommonAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedVariable; @@ -1700,7 +1738,9 @@ static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) { return; } - D->addAttr(::new (S.Context) NoReturnAttr(attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoReturnAttr(attr.getRange(), S.Context, + attr.getAttributeSpellingListIndex())); } bool Sema::CheckNoReturnAttr(const AttributeList &attr) { @@ -1727,14 +1767,33 @@ static void handleAnalyzerNoReturnAttr(Sema &S, Decl *D, if (VD == 0 || (!VD->getType()->isBlockPointerType() && !VD->getType()->isFunctionPointerType())) { S.Diag(Attr.getLoc(), - Attr.isCXX0XAttribute() ? diag::err_attribute_wrong_decl_type + Attr.isCXX11Attribute() ? diag::err_attribute_wrong_decl_type : diag::warn_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } } - D->addAttr(::new (S.Context) AnalyzerNoReturnAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + AnalyzerNoReturnAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +static void handleCXX11NoReturnAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + // C++11 [dcl.attr.noreturn]p1: + // The attribute may be applied to the declarator-id in a function + // declaration. + FunctionDecl *FD = dyn_cast<FunctionDecl>(D); + if (!FD) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) + CXX11NoReturnAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } // PS3 PPU-specific. @@ -1795,16 +1854,30 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) { count++; } - D->addAttr(::new (S.Context) VecReturnAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + VecReturnAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } -static void handleDependencyAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (!isFunctionOrMethod(D) && !isa<ParmVarDecl>(D)) { +static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D, + const AttributeList &Attr) { + if (isa<ParmVarDecl>(D)) { + // [[carries_dependency]] can only be applied to a parameter if it is a + // parameter of a function declaration or lambda. + if (!(Scope->getFlags() & clang::Scope::FunctionDeclarationScope)) { + S.Diag(Attr.getLoc(), + diag::err_carries_dependency_param_not_function_decl); + return; + } + } else if (!isa<FunctionDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr.getName() << ExpectedFunctionMethodOrParameter; return; } - // FIXME: Actually store the attribute on the declaration + + D->addAttr(::new (S.Context) CarriesDependencyAttr( + Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1821,7 +1894,9 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) UnusedAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + UnusedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleReturnsTwiceAttr(Sema &S, Decl *D, @@ -1838,7 +1913,9 @@ static void handleReturnsTwiceAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ReturnsTwiceAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ReturnsTwiceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1859,7 +1936,9 @@ static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) UsedAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + UsedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1888,8 +1967,9 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) ConstructorAttr(Attr.getRange(), S.Context, - priority)); + D->addAttr(::new (S.Context) + ConstructorAttr(Attr.getRange(), S.Context, priority, + Attr.getAttributeSpellingListIndex())); } static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1918,8 +1998,9 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) DestructorAttr(Attr.getRange(), S.Context, - priority)); + D->addAttr(::new (S.Context) + DestructorAttr(Attr.getRange(), S.Context, priority, + Attr.getAttributeSpellingListIndex())); } template <typename AttrTy> @@ -1943,7 +2024,8 @@ static void handleAttrWithMessage(Sema &S, Decl *D, const AttributeList &Attr, Str = SE->getString(); } - D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str)); + D->addAttr(::new (S.Context) AttrTy(Attr.getRange(), S.Context, Str, + Attr.getAttributeSpellingListIndex())); } static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, @@ -1954,8 +2036,9 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ArcWeakrefUnavailableAttr( - Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleObjCRootClassAttr(Sema &S, Decl *D, @@ -1971,11 +2054,13 @@ static void handleObjCRootClassAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ObjCRootClassAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCRootClassAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } -static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, - const AttributeList &Attr) { +static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, + const AttributeList &Attr) { if (!isa<ObjCInterfaceDecl>(D)) { S.Diag(Attr.getLoc(), diag::err_suppress_autosynthesis); return; @@ -1987,8 +2072,9 @@ static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ObjCRequiresPropertyDefsAttr( - Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static bool checkAvailabilityAttr(Sema &S, SourceRange Range, @@ -2030,13 +2116,33 @@ static bool checkAvailabilityAttr(Sema &S, SourceRange Range, return false; } -AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range, +/// \brief Check whether the two versions match. +/// +/// If either version tuple is empty, then they are assumed to match. If +/// \p BeforeIsOkay is true, then \p X can be less than or equal to \p Y. +static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, + bool BeforeIsOkay) { + if (X.empty() || Y.empty()) + return true; + + if (X == Y) + return true; + + if (BeforeIsOkay && X < Y) + return true; + + return false; +} + +AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, bool IsUnavailable, - StringRef Message) { + StringRef Message, + bool Override, + unsigned AttrSpellingListIndex) { VersionTuple MergedIntroduced = Introduced; VersionTuple MergedDeprecated = Deprecated; VersionTuple MergedObsoleted = Obsoleted; @@ -2062,18 +2168,47 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range, VersionTuple OldDeprecated = OldAA->getDeprecated(); VersionTuple OldObsoleted = OldAA->getObsoleted(); bool OldIsUnavailable = OldAA->getUnavailable(); - StringRef OldMessage = OldAA->getMessage(); - - if ((!OldIntroduced.empty() && !Introduced.empty() && - OldIntroduced != Introduced) || - (!OldDeprecated.empty() && !Deprecated.empty() && - OldDeprecated != Deprecated) || - (!OldObsoleted.empty() && !Obsoleted.empty() && - OldObsoleted != Obsoleted) || - (OldIsUnavailable != IsUnavailable) || - (OldMessage != Message)) { - Diag(OldAA->getLocation(), diag::warn_mismatched_availability); - Diag(Range.getBegin(), diag::note_previous_attribute); + + if (!versionsMatch(OldIntroduced, Introduced, Override) || + !versionsMatch(Deprecated, OldDeprecated, Override) || + !versionsMatch(Obsoleted, OldObsoleted, Override) || + !(OldIsUnavailable == IsUnavailable || + (Override && !OldIsUnavailable && IsUnavailable))) { + if (Override) { + int Which = -1; + VersionTuple FirstVersion; + VersionTuple SecondVersion; + if (!versionsMatch(OldIntroduced, Introduced, Override)) { + Which = 0; + FirstVersion = OldIntroduced; + SecondVersion = Introduced; + } else if (!versionsMatch(Deprecated, OldDeprecated, Override)) { + Which = 1; + FirstVersion = Deprecated; + SecondVersion = OldDeprecated; + } else if (!versionsMatch(Obsoleted, OldObsoleted, Override)) { + Which = 2; + FirstVersion = Obsoleted; + SecondVersion = OldObsoleted; + } + + if (Which == -1) { + Diag(OldAA->getLocation(), + diag::warn_mismatched_availability_override_unavail) + << AvailabilityAttr::getPrettyPlatformName(Platform->getName()); + } else { + Diag(OldAA->getLocation(), + diag::warn_mismatched_availability_override) + << Which + << AvailabilityAttr::getPrettyPlatformName(Platform->getName()) + << FirstVersion.getAsString() << SecondVersion.getAsString(); + } + Diag(Range.getBegin(), diag::note_overridden_method); + } else { + Diag(OldAA->getLocation(), diag::warn_mismatched_availability); + Diag(Range.getBegin(), diag::note_previous_attribute); + } + Attrs.erase(Attrs.begin() + i); --e; continue; @@ -2115,7 +2250,8 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range, MergedDeprecated, MergedObsoleted)) { return ::new (Context) AvailabilityAttr(Range, Context, Platform, Introduced, Deprecated, - Obsoleted, IsUnavailable, Message); + Obsoleted, IsUnavailable, Message, + AttrSpellingListIndex); } return NULL; } @@ -2124,11 +2260,18 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { IdentifierInfo *Platform = Attr.getParameterName(); SourceLocation PlatformLoc = Attr.getParameterLoc(); - + unsigned Index = Attr.getAttributeSpellingListIndex(); + if (AvailabilityAttr::getPrettyPlatformName(Platform->getName()).empty()) S.Diag(PlatformLoc, diag::warn_availability_unknown_platform) << Platform; + NamedDecl *ND = dyn_cast<NamedDecl>(D); + if (!ND) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + AvailabilityChange Introduced = Attr.getAvailabilityIntroduced(); AvailabilityChange Deprecated = Attr.getAvailabilityDeprecated(); AvailabilityChange Obsoleted = Attr.getAvailabilityObsoleted(); @@ -2139,37 +2282,69 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, if (SE) Str = SE->getString(); - AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(D, Attr.getRange(), + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, Attr.getRange(), Platform, Introduced.Version, Deprecated.Version, Obsoleted.Version, - IsUnavailable, Str); + IsUnavailable, Str, + /*Override=*/false, + Index); if (NewAttr) D->addAttr(NewAttr); } +template <class T> +static T *mergeVisibilityAttr(Sema &S, Decl *D, SourceRange range, + typename T::VisibilityType value, + unsigned attrSpellingListIndex) { + T *existingAttr = D->getAttr<T>(); + if (existingAttr) { + typename T::VisibilityType existingValue = existingAttr->getVisibility(); + if (existingValue == value) + return NULL; + S.Diag(existingAttr->getLocation(), diag::err_mismatched_visibility); + S.Diag(range.getBegin(), diag::note_previous_attribute); + D->dropAttr<T>(); + } + return ::new (S.Context) T(range, S.Context, value, attrSpellingListIndex); +} + VisibilityAttr *Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, - VisibilityAttr::VisibilityType Vis) { + VisibilityAttr::VisibilityType Vis, + unsigned AttrSpellingListIndex) { + return ::mergeVisibilityAttr<VisibilityAttr>(*this, D, Range, Vis, + AttrSpellingListIndex); +} + +TypeVisibilityAttr *Sema::mergeTypeVisibilityAttr(Decl *D, SourceRange Range, + TypeVisibilityAttr::VisibilityType Vis, + unsigned AttrSpellingListIndex) { + return ::mergeVisibilityAttr<TypeVisibilityAttr>(*this, D, Range, Vis, + AttrSpellingListIndex); +} + +static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr, + bool isTypeVisibility) { + // Visibility attributes don't mean anything on a typedef. if (isa<TypedefNameDecl>(D)) { - Diag(Range.getBegin(), diag::warn_attribute_ignored) << "visibility"; - return NULL; + S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) + << Attr.getName(); + return; } - VisibilityAttr *ExistingAttr = D->getAttr<VisibilityAttr>(); - if (ExistingAttr) { - VisibilityAttr::VisibilityType ExistingVis = ExistingAttr->getVisibility(); - if (ExistingVis == Vis) - return NULL; - Diag(ExistingAttr->getLocation(), diag::err_mismatched_visibility); - Diag(Range.getBegin(), diag::note_previous_attribute); - D->dropAttr<VisibilityAttr>(); + + // 'type_visibility' can only go on a type or namespace. + if (isTypeVisibility && + !(isa<TagDecl>(D) || + isa<ObjCInterfaceDecl>(D) || + isa<NamespaceDecl>(D))) { + S.Diag(Attr.getRange().getBegin(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedTypeOrNamespace; + return; } - return ::new (Context) VisibilityAttr(Range, Context, Vis); -} -static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. - if(!checkAttributeNumArgs(S, Attr, 1)) + if (!checkAttributeNumArgs(S, Attr, 1)) return; Expr *Arg = Attr.getArg(0); @@ -2178,13 +2353,13 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!Str || !Str->isAscii()) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_not_string) - << "visibility" << 1; + << (isTypeVisibility ? "type_visibility" : "visibility") << 1; return; } StringRef TypeStr = Str->getString(); VisibilityAttr::VisibilityType type; - + if (TypeStr == "default") type = VisibilityAttr::Default; else if (TypeStr == "hidden") @@ -2205,9 +2380,17 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - VisibilityAttr *NewAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type); - if (NewAttr) - D->addAttr(NewAttr); + unsigned Index = Attr.getAttributeSpellingListIndex(); + clang::Attr *newAttr; + if (isTypeVisibility) { + newAttr = S.mergeTypeVisibilityAttr(D, Attr.getRange(), + (TypeVisibilityAttr::VisibilityType) type, + Index); + } else { + newAttr = S.mergeVisibilityAttr(D, Attr.getRange(), type, Index); + } + if (newAttr) + D->addAttr(newAttr); } static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, @@ -2274,7 +2457,9 @@ static void handleObjCExceptionAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) ObjCExceptionAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCExceptionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2305,7 +2490,9 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { // case. S.Diag(D->getLocation(), diag::warn_nsobject_attribute); } - D->addAttr(::new (S.Context) ObjCNSObjectAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ObjCNSObjectAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void @@ -2320,7 +2507,9 @@ handleOverloadableAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) OverloadableAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + OverloadableAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2344,7 +2533,9 @@ static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) BlocksAttr(Attr.getRange(), S.Context, type)); + D->addAttr(::new (S.Context) + BlocksAttr(Attr.getRange(), S.Context, type, + Attr.getAttributeSpellingListIndex())); } static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2436,8 +2627,9 @@ static void handleSentinelAttr(Sema &S, Decl *D, const AttributeList &Attr) { << Attr.getName() << ExpectedFunctionMethodOrBlock; return; } - D->addAttr(::new (S.Context) SentinelAttr(Attr.getRange(), S.Context, sentinel, - nullPos)); + D->addAttr(::new (S.Context) + SentinelAttr(Attr.getRange(), S.Context, sentinel, nullPos, + Attr.getAttributeSpellingListIndex())); } static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2445,9 +2637,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) if (!checkAttributeNumArgs(S, Attr, 0)) return; - if (!isFunction(D) && !isa<ObjCMethodDecl>(D)) { + if (!isFunction(D) && !isa<ObjCMethodDecl>(D) && !isa<CXXRecordDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << ExpectedFunctionOrMethod; + << Attr.getName() << ExpectedFunctionMethodOrClass; return; } @@ -2463,7 +2655,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr) return; } - D->addAttr(::new (S.Context) WarnUnusedResultAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + WarnUnusedResultAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2485,13 +2679,9 @@ static void handleWeakAttr(Sema &S, Decl *D, const AttributeList &Attr) { 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.getRange(), S.Context)); + nd->addAttr(::new (S.Context) + WeakAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2518,7 +2708,9 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) WeakImportAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + WeakImportAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } // Handles reqd_work_group_size and work_group_size_hint. @@ -2568,15 +2760,57 @@ static void handleWorkGroupSize(Sema &S, Decl *D, if (Attr.getKind() == AttributeList::AT_ReqdWorkGroupSize) D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(Attr.getRange(), S.Context, - WGSize[0], WGSize[1], WGSize[2])); + WGSize[0], WGSize[1], WGSize[2], + Attr.getAttributeSpellingListIndex())); else D->addAttr(::new (S.Context) WorkGroupSizeHintAttr(Attr.getRange(), S.Context, - WGSize[0], WGSize[1], WGSize[2])); + WGSize[0], WGSize[1], WGSize[2], + Attr.getAttributeSpellingListIndex())); +} + +static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { + assert(Attr.getKind() == AttributeList::AT_VecTypeHint); + + // Attribute has 1 argument. + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg()); + + if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && + (ParmType->isBooleanType() || + !ParmType->isIntegralType(S.getASTContext()))) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint) + << ParmType; + return; + } + + if (Attr.getKind() == AttributeList::AT_VecTypeHint && + D->hasAttr<VecTypeHintAttr>()) { + VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); + if (A->getTypeHint() != ParmType) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); + return; + } + } + + D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, + ParmType, Attr.getLoc())); +} + +static void handleEndianAttr(Sema &S, Decl *D, const AttributeList &Attr) { + if (!dyn_cast<VarDecl>(D)) + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << "endian" + << 9; + StringRef EndianType = Attr.getParameterName()->getName(); + if (EndianType != "host" && EndianType != "device") + S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_endian) << EndianType; } SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, - StringRef Name) { + StringRef Name, + unsigned AttrSpellingListIndex) { if (SectionAttr *ExistingAttr = D->getAttr<SectionAttr>()) { if (ExistingAttr->getName() == Name) return NULL; @@ -2584,7 +2818,8 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, Diag(Range.getBegin(), diag::note_previous_attribute); return NULL; } - return ::new (Context) SectionAttr(Range, Context, Name); + return ::new (Context) SectionAttr(Range, Context, Name, + AttrSpellingListIndex); } static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2614,8 +2849,10 @@ static void handleSectionAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(SE->getLocStart(), diag::err_attribute_section_local_variable); return; } + + unsigned Index = Attr.getAttributeSpellingListIndex(); SectionAttr *NewAttr = S.mergeSectionAttr(D, Attr.getRange(), - SE->getString()); + SE->getString(), Index); if (NewAttr) D->addAttr(NewAttr); } @@ -2632,7 +2869,9 @@ static void handleNothrowAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Existing->getLocation().isInvalid()) Existing->setRange(Attr.getRange()); } else { - D->addAttr(::new (S.Context) NoThrowAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoThrowAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } } @@ -2647,7 +2886,9 @@ static void handleConstAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Existing->getLocation().isInvalid()) Existing->setRange(Attr.getRange()); } else { - D->addAttr(::new (S.Context) ConstAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ConstAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex() )); } } @@ -2656,7 +2897,9 @@ static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 0)) return; - D->addAttr(::new (S.Context) PureAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PureAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -2715,8 +2958,11 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD)); + D->addAttr(::new (S.Context) + CleanupAttr(Attr.getRange(), S.Context, FD, + Attr.getAttributeSpellingListIndex())); S.MarkFunctionReferenced(Attr.getParameterLoc(), FD); + S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc()); } /// Handle __attribute__((format_arg((idx)))) attribute based on @@ -2790,8 +3036,9 @@ static void handleFormatArgAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) FormatArgAttr(Attr.getRange(), S.Context, - Idx.getZExtValue())); + D->addAttr(::new (S.Context) + FormatArgAttr(Attr.getRange(), S.Context, Idx.getZExtValue(), + Attr.getAttributeSpellingListIndex())); } enum FormatAttrKind { @@ -2866,12 +3113,14 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, Attr.setInvalid(); return; } - D->addAttr(::new (S.Context) InitPriorityAttr(Attr.getRange(), S.Context, - prioritynum)); + D->addAttr(::new (S.Context) + InitPriorityAttr(Attr.getRange(), S.Context, prioritynum, + Attr.getAttributeSpellingListIndex())); } FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, - int FormatIdx, int FirstArg) { + int FormatIdx, int FirstArg, + unsigned AttrSpellingListIndex) { // Check whether we already have an equivalent format attribute. for (specific_attr_iterator<FormatAttr> i = D->specific_attr_begin<FormatAttr>(), @@ -2889,8 +3138,8 @@ FormatAttr *Sema::mergeFormatAttr(Decl *D, SourceRange Range, StringRef Format, } } - return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, - FirstArg); + return ::new (Context) FormatAttr(Range, Context, Format, FormatIdx, FirstArg, + AttrSpellingListIndex); } /// Handle __attribute__((format(type,idx,firstarg))) attributes based on @@ -3030,7 +3279,8 @@ static void handleFormatAttr(Sema &S, Decl *D, const AttributeList &Attr) { FormatAttr *NewAttr = S.mergeFormatAttr(D, Attr.getRange(), Format, Idx.getZExtValue(), - FirstArg.getZExtValue()); + FirstArg.getZExtValue(), + Attr.getAttributeSpellingListIndex()); if (NewAttr) D->addAttr(NewAttr); } @@ -3099,7 +3349,9 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, } } - RD->addAttr(::new (S.Context) TransparentUnionAttr(Attr.getRange(), S.Context)); + RD->addAttr(::new (S.Context) + TransparentUnionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3124,8 +3376,10 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { if ((*i)->getAnnotation() == SE->getString()) return; } - D->addAttr(::new (S.Context) AnnotateAttr(Attr.getRange(), S.Context, - SE->getString())); + + D->addAttr(::new (S.Context) + AnnotateAttr(Attr.getRange(), S.Context, SE->getString(), + Attr.getAttributeSpellingListIndex())); } static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3135,34 +3389,77 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { 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.getRange(), S.Context, - true, 0, Attr.isDeclspecAttribute())); + D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, + true, 0, Attr.getAttributeSpellingListIndex())); return; } - S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0), - Attr.isDeclspecAttribute()); -} + Expr *E = Attr.getArg(0); + if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { + S.Diag(Attr.getEllipsisLoc(), + diag::err_pack_expansion_without_parameter_packs); + return; + } -void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, - bool isDeclSpec) { - // FIXME: Handle pack-expansions here. - if (DiagnoseUnexpandedParameterPack(E)) + if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) return; + S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(), + Attr.isPackExpansion()); +} + +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, + unsigned SpellingListIndex, bool IsPackExpansion) { + AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex); + SourceLocation AttrLoc = AttrRange.getBegin(); + + // C++11 alignas(...) and C11 _Alignas(...) have additional requirements. + if (TmpAttr.isAlignas()) { + // C++11 [dcl.align]p1: + // An alignment-specifier may be applied to a variable or to a class + // data member, but it shall not be applied to a bit-field, a function + // parameter, the formal parameter of a catch clause, or a variable + // declared with the register storage class specifier. An + // alignment-specifier may also be applied to the declaration of a class + // or enumeration type. + // C11 6.7.5/2: + // An alignment attribute shall not be specified in a declaration of + // a typedef, or a bit-field, or a function, or a parameter, or an + // object declared with the register storage-class specifier. + int DiagKind = -1; + if (isa<ParmVarDecl>(D)) { + DiagKind = 0; + } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (VD->getStorageClass() == SC_Register) + DiagKind = 1; + if (VD->isExceptionVariable()) + DiagKind = 2; + } else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { + if (FD->isBitField()) + DiagKind = 3; + } else if (!isa<TagDecl>(D)) { + Diag(AttrLoc, diag::err_attribute_wrong_decl_type) + << (TmpAttr.isC11() ? "'_Alignas'" : "'alignas'") + << (TmpAttr.isC11() ? ExpectedVariableOrField + : ExpectedVariableFieldOrTag); + return; + } + if (DiagKind != -1) { + Diag(AttrLoc, diag::err_alignas_attribute_wrong_decl_type) + << TmpAttr.isC11() << DiagKind; + return; + } + } + if (E->isTypeDependent() || E->isValueDependent()) { // Save dependent expressions in the AST to be instantiated. - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, E, - isDeclSpec)); + AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); return; } - - SourceLocation AttrLoc = AttrRange.getBegin(); + // FIXME: Cache the number on the Attr object? llvm::APSInt Alignment(32); ExprResult ICE @@ -3171,32 +3468,79 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, /*AllowFold*/ false); if (ICE.isInvalid()) return; - if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { + + // C++11 [dcl.align]p2: + // -- if the constant expression evaluates to zero, the alignment + // specifier shall have no effect + // C11 6.7.5p6: + // An alignment specification of zero has no effect. + if (!(TmpAttr.isAlignas() && !Alignment) && + !llvm::isPowerOf2_64(Alignment.getZExtValue())) { Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) << E->getSourceRange(); return; } - if (isDeclSpec) { + + if (TmpAttr.isDeclspec()) { // We've already verified it's a power of 2, now let's make sure it's // 8192 or less. if (Alignment.getZExtValue() > 8192) { - Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) + Diag(AttrLoc, diag::err_attribute_aligned_greater_than_8192) << E->getSourceRange(); return; } } - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, ICE.take(), - isDeclSpec)); + AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true, + ICE.take(), SpellingListIndex); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); } -void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, - bool isDeclSpec) { +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, + unsigned SpellingListIndex, bool IsPackExpansion) { // FIXME: Cache the number on the Attr object if non-dependent? // FIXME: Perform checking of type validity - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS, - isDeclSpec)); - return; + AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS, + SpellingListIndex); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); +} + +void Sema::CheckAlignasUnderalignment(Decl *D) { + assert(D->hasAttrs() && "no attributes on decl"); + + QualType Ty; + if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) + Ty = VD->getType(); + else + Ty = Context.getTagDeclType(cast<TagDecl>(D)); + if (Ty->isDependentType() || Ty->isIncompleteType()) + return; + + // C++11 [dcl.align]p5, C11 6.7.5/4: + // The combined effect of all alignment attributes in a declaration shall + // not specify an alignment that is less strict than the alignment that + // would otherwise be required for the entity being declared. + AlignedAttr *AlignasAttr = 0; + unsigned Align = 0; + for (specific_attr_iterator<AlignedAttr> + I = D->specific_attr_begin<AlignedAttr>(), + E = D->specific_attr_end<AlignedAttr>(); I != E; ++I) { + if (I->isAlignmentDependent()) + return; + if (I->isAlignas()) + AlignasAttr = *I; + Align = std::max(Align, I->getAlignment(Context)); + } + + if (AlignasAttr && Align) { + CharUnits RequestedAlign = Context.toCharUnitsFromBits(Align); + CharUnits NaturalAlign = Context.getTypeAlignInChars(Ty); + if (NaturalAlign > RequestedAlign) + Diag(AlignasAttr->getLocation(), diag::err_alignas_underaligned) + << Ty << (unsigned)NaturalAlign.getQuantity(); + } } /// handleModeAttr - This attribute modifies the width of a decl with primitive @@ -3260,6 +3604,10 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (Str == "pointer") DestWidth = S.Context.getTargetInfo().getPointerWidth(0); break; + case 11: + if (Str == "unwind_word") + DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); + break; } QualType OldTy; @@ -3386,7 +3734,9 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) NoDebugAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoDebugAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3401,7 +3751,9 @@ static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) NoInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NoInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, @@ -3417,8 +3769,9 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) NoInstrumentFunctionAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NoInstrumentFunctionAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -3435,7 +3788,9 @@ static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDAConstantAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDAConstantAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "constant"; } @@ -3455,7 +3810,9 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDADeviceAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDADeviceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "device"; } @@ -3476,10 +3833,10 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { FunctionDecl *FD = cast<FunctionDecl>(D); if (!FD->getResultType()->isVoidType()) { TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens(); - if (FunctionTypeLoc* FTL = dyn_cast<FunctionTypeLoc>(&TL)) { + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) << FD->getType() - << FixItHint::CreateReplacement(FTL->getResultLoc().getSourceRange(), + << FixItHint::CreateReplacement(FTL.getResultLoc().getSourceRange(), "void"); } else { S.Diag(FD->getTypeSpecStartLoc(), diag::err_kern_type_not_void_return) @@ -3488,7 +3845,9 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDAGlobalAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDAGlobalAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "global"; } @@ -3507,7 +3866,9 @@ static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) CUDAHostAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDAHostAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "host"; } @@ -3519,14 +3880,15 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (!checkAttributeNumArgs(S, Attr, 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.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CUDASharedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "shared"; } @@ -3549,16 +3911,19 @@ static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) GNUInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + GNUInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (hasDeclarator(D)) return; + const FunctionDecl *FD = dyn_cast<FunctionDecl>(D); // 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)) + if (S.CheckCallingConvAttr(Attr, CC, FD)) return; if (!isa<ObjCMethodDecl>(D)) { @@ -3569,19 +3934,29 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { switch (Attr.getKind()) { case AttributeList::AT_FastCall: - D->addAttr(::new (S.Context) FastCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + FastCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_StdCall: - D->addAttr(::new (S.Context) StdCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + StdCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_ThisCall: - D->addAttr(::new (S.Context) ThisCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ThisCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_CDecl: - D->addAttr(::new (S.Context) CDeclAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CDeclAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_Pascal: - D->addAttr(::new (S.Context) PascalAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PascalAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_Pcs: { PcsAttr::PCSType PCS; @@ -3596,11 +3971,20 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { llvm_unreachable("unexpected calling convention in pcs attribute"); } - D->addAttr(::new (S.Context) PcsAttr(Attr.getRange(), S.Context, PCS)); + D->addAttr(::new (S.Context) + PcsAttr(Attr.getRange(), S.Context, PCS, + Attr.getAttributeSpellingListIndex())); return; } case AttributeList::AT_PnaclCall: - D->addAttr(::new (S.Context) PnaclCallAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + PnaclCallAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); + return; + case AttributeList::AT_IntelOclBicc: + D->addAttr(::new (S.Context) + IntelOclBiccAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; default: @@ -3613,7 +3997,24 @@ static void handleOpenCLKernelAttr(Sema &S, Decl *D, const AttributeList &Attr){ D->addAttr(::new (S.Context) OpenCLKernelAttr(Attr.getRange(), S.Context)); } -bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { +static void handleOpenCLImageAccessAttr(Sema &S, Decl *D, const AttributeList &Attr){ + assert(!Attr.isInvalid()); + + Expr *E = Attr.getArg(0); + llvm::APSInt ArgNum(32); + if (E->isTypeDependent() || E->isValueDependent() || + !E->isIntegerConstantExpr(ArgNum, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << Attr.getName()->getName() << E->getSourceRange(); + return; + } + + D->addAttr(::new (S.Context) OpenCLImageAccessAttr( + Attr.getRange(), S.Context, ArgNum.getZExtValue())); +} + +bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + const FunctionDecl *FD) { if (attr.isInvalid()) return true; @@ -3656,6 +4057,7 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { return true; } case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break; + case AttributeList::AT_IntelOclBicc: CC = CC_IntelOclBicc; break; default: llvm_unreachable("unexpected attribute kind"); } @@ -3663,7 +4065,12 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); if (A == TargetInfo::CCCR_Warning) { Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); - CC = TI.getDefaultCallingConv(); + + TargetInfo::CallingConvMethodType MT = TargetInfo::CCMT_Unknown; + if (FD) + MT = FD->isCXXInstanceMember() ? TargetInfo::CCMT_Member : + TargetInfo::CCMT_NonMember; + CC = TI.getDefaultCallingConv(MT); } return false; @@ -3682,7 +4089,9 @@ static void handleRegparmAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - D->addAttr(::new (S.Context) RegparmAttr(Attr.getRange(), S.Context, numParams)); + D->addAttr(::new (S.Context) + RegparmAttr(Attr.getRange(), S.Context, numParams, + Attr.getAttributeSpellingListIndex())); } /// Checks a regparm attribute, returning true if it is ill-formed and @@ -3762,9 +4171,11 @@ static void handleLaunchBoundsAttr(Sema &S, Decl *D, const AttributeList &Attr){ } } - D->addAttr(::new (S.Context) CUDALaunchBoundsAttr(Attr.getRange(), S.Context, - MaxThreads.getZExtValue(), - MinBlocks.getZExtValue())); + D->addAttr(::new (S.Context) + CUDALaunchBoundsAttr(Attr.getRange(), S.Context, + MaxThreads.getZExtValue(), + MinBlocks.getZExtValue(), + Attr.getAttributeSpellingListIndex())); } else { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "launch_bounds"; } @@ -3815,12 +4226,10 @@ static void handleArgumentWithTypeTagAttr(Sema &S, Decl *D, } } - D->addAttr(::new (S.Context) ArgumentWithTypeTagAttr(Attr.getRange(), - S.Context, - ArgumentKind, - ArgumentIdx, - TypeTagIdx, - IsPointer)); + D->addAttr(::new (S.Context) + ArgumentWithTypeTagAttr(Attr.getRange(), S.Context, ArgumentKind, + ArgumentIdx, TypeTagIdx, IsPointer, + Attr.getAttributeSpellingListIndex())); } static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, @@ -3834,13 +4243,12 @@ static void handleTypeTagForDatatypeAttr(Sema &S, Decl *D, QualType MatchingCType = S.GetTypeFromParser(Attr.getMatchingCType(), NULL); - D->addAttr(::new (S.Context) TypeTagForDatatypeAttr( - Attr.getRange(), - S.Context, - PointerKind, - MatchingCType, - Attr.getLayoutCompatible(), - Attr.getMustBeNull())); + D->addAttr(::new (S.Context) + TypeTagForDatatypeAttr(Attr.getRange(), S.Context, PointerKind, + MatchingCType, + Attr.getLayoutCompatible(), + Attr.getMustBeNull(), + Attr.getAttributeSpellingListIndex())); } //===----------------------------------------------------------------------===// @@ -3882,9 +4290,13 @@ static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) { } if (cf) - param->addAttr(::new (S.Context) CFConsumedAttr(Attr.getRange(), S.Context)); + param->addAttr(::new (S.Context) + CFConsumedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else - param->addAttr(::new (S.Context) NSConsumedAttr(Attr.getRange(), S.Context)); + param->addAttr(::new (S.Context) + NSConsumedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNSConsumesSelfAttr(Sema &S, Decl *D, @@ -3895,7 +4307,9 @@ static void handleNSConsumesSelfAttr(Sema &S, Decl *D, return; } - D->addAttr(::new (S.Context) NSConsumesSelfAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + NSConsumesSelfAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, @@ -3947,24 +4361,29 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, default: llvm_unreachable("invalid ownership attribute"); case AttributeList::AT_NSReturnsAutoreleased: - D->addAttr(::new (S.Context) NSReturnsAutoreleasedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NSReturnsAutoreleasedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_CFReturnsNotRetained: - D->addAttr(::new (S.Context) CFReturnsNotRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + CFReturnsNotRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_NSReturnsNotRetained: - D->addAttr(::new (S.Context) NSReturnsNotRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NSReturnsNotRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_CFReturnsRetained: - D->addAttr(::new (S.Context) CFReturnsRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + CFReturnsRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; case AttributeList::AT_NSReturnsRetained: - D->addAttr(::new (S.Context) NSReturnsRetainedAttr(Attr.getRange(), - S.Context)); + D->addAttr(::new (S.Context) + NSReturnsRetainedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); return; }; } @@ -3994,8 +4413,9 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, return; } - method->addAttr( - ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context)); + method->addAttr(::new (S.Context) + ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context, + attr.getAttributeSpellingListIndex())); } static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, @@ -4021,8 +4441,9 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, return; } - method->addAttr( - ::new (S.Context) ObjCRequiresSuperAttr(attr.getRange(), S.Context)); + method->addAttr(::new (S.Context) + ObjCRequiresSuperAttr(attr.getRange(), S.Context, + attr.getAttributeSpellingListIndex())); } /// Handle cf_audited_transfer and cf_unknown_transfer. @@ -4052,11 +4473,13 @@ static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { // All clear; add the attribute. if (IsAudited) { - D->addAttr( - ::new (S.Context) CFAuditedTransferAttr(A.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CFAuditedTransferAttr(A.getRange(), S.Context, + A.getAttributeSpellingListIndex())); } else { - D->addAttr( - ::new (S.Context) CFUnknownTransferAttr(A.getRange(), S.Context)); + D->addAttr(::new (S.Context) + CFUnknownTransferAttr(A.getRange(), S.Context, + A.getAttributeSpellingListIndex())); } } @@ -4086,8 +4509,9 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D, } } - D->addAttr(::new (S.Context) NSBridgedAttr(Attr.getRange(), S.Context, - ParmName)); + D->addAttr(::new (S.Context) + NSBridgedAttr(Attr.getRange(), S.Context, ParmName, + Attr.getAttributeSpellingListIndex())); } static void handleObjCOwnershipAttr(Sema &S, Decl *D, @@ -4141,7 +4565,8 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D, } D->addAttr(::new (S.Context) - ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context)); + ObjCPreciseLifetimeAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } //===----------------------------------------------------------------------===// @@ -4189,15 +4614,16 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); return; } - } else if (!isxdigit(*I)) { + } else if (!isHexDigit(*I)) { S.Diag(Attr.getLoc(), diag::err_attribute_uuid_malformed_guid); return; } I++; } - D->addAttr(::new (S.Context) UuidAttr(Attr.getRange(), S.Context, - Str->getString())); + D->addAttr(::new (S.Context) + UuidAttr(Attr.getRange(), S.Context, Str->getString(), + Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "uuid"; } @@ -4211,13 +4637,19 @@ static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { AttributeList::Kind Kind = Attr.getKind(); if (Kind == AttributeList::AT_SingleInheritance) D->addAttr( - ::new (S.Context) SingleInheritanceAttr(Attr.getRange(), S.Context)); + ::new (S.Context) + SingleInheritanceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_MultipleInheritance) D->addAttr( - ::new (S.Context) MultipleInheritanceAttr(Attr.getRange(), S.Context)); + ::new (S.Context) + MultipleInheritanceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_VirtualInheritance) D->addAttr( - ::new (S.Context) VirtualInheritanceAttr(Attr.getRange(), S.Context)); + ::new (S.Context) + VirtualInheritanceAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -4225,20 +4657,25 @@ static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { AttributeList::Kind Kind = Attr.getKind(); if (Kind == AttributeList::AT_Ptr32) D->addAttr( - ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context)); + ::new (S.Context) Ptr32Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_Ptr64) D->addAttr( - ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context)); + ::new (S.Context) Ptr64Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else if (Kind == AttributeList::AT_Win64) D->addAttr( - ::new (S.Context) Win64Attr(Attr.getRange(), S.Context)); + ::new (S.Context) Win64Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } static void handleForceInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.LangOpts.MicrosoftExt) - D->addAttr(::new (S.Context) ForceInlineAttr(Attr.getRange(), S.Context)); + D->addAttr(::new (S.Context) + ForceInlineAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -4261,12 +4698,11 @@ static void ProcessNonInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr) { switch (Attr.getKind()) { - case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; - case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; - case AttributeList::AT_IBOutletCollection: - handleIBOutletCollection(S, D, Attr); break; + case AttributeList::AT_IBAction: handleIBAction(S, D, Attr); break; + case AttributeList::AT_IBOutlet: handleIBOutlet(S, D, Attr); break; + case AttributeList::AT_IBOutletCollection: + handleIBOutletCollection(S, D, Attr); break; case AttributeList::AT_AddressSpace: - case AttributeList::AT_OpenCLImageAccess: case AttributeList::AT_ObjCGC: case AttributeList::AT_VectorSize: case AttributeList::AT_NeonVectorType: @@ -4291,10 +4727,14 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Annotate: handleAnnotateAttr (S, D, Attr); break; case AttributeList::AT_Availability:handleAvailabilityAttr(S, D, Attr); break; case AttributeList::AT_CarriesDependency: - handleDependencyAttr (S, D, Attr); break; + handleDependencyAttr(S, scope, D, Attr); + break; case AttributeList::AT_Common: handleCommonAttr (S, D, Attr); break; case AttributeList::AT_CUDAConstant:handleConstantAttr (S, D, Attr); break; case AttributeList::AT_Constructor: handleConstructorAttr (S, D, Attr); break; + case AttributeList::AT_CXX11NoReturn: + handleCXX11NoReturnAttr(S, D, Attr); + break; case AttributeList::AT_Deprecated: handleAttrWithMessage<DeprecatedAttr>(S, D, Attr, "deprecated"); break; @@ -4364,6 +4804,13 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ReqdWorkGroupSize: handleWorkGroupSize(S, D, Attr); break; + case AttributeList::AT_VecTypeHint: + handleVecTypeHint(S, D, Attr); break; + + case AttributeList::AT_Endian: + handleEndianAttr(S, D, Attr); + break; + case AttributeList::AT_InitPriority: handleInitPriorityAttr(S, D, Attr); break; @@ -4386,7 +4833,12 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, handleReturnsTwiceAttr(S, D, Attr); break; case AttributeList::AT_Used: handleUsedAttr (S, D, Attr); break; - case AttributeList::AT_Visibility: handleVisibilityAttr (S, D, Attr); break; + case AttributeList::AT_Visibility: + handleVisibilityAttr(S, D, Attr, false); + break; + case AttributeList::AT_TypeVisibility: + handleVisibilityAttr(S, D, Attr, true); + break; case AttributeList::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, Attr); break; case AttributeList::AT_Weak: handleWeakAttr (S, D, Attr); break; @@ -4423,11 +4875,15 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Pascal: case AttributeList::AT_Pcs: case AttributeList::AT_PnaclCall: + case AttributeList::AT_IntelOclBicc: handleCallConvAttr(S, D, Attr); break; case AttributeList::AT_OpenCLKernel: handleOpenCLKernelAttr(S, D, Attr); break; + case AttributeList::AT_OpenCLImageAccess: + handleOpenCLImageAccessAttr(S, D, Attr); + break; // Microsoft attributes: case AttributeList::AT_MsStruct: @@ -4460,11 +4916,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ScopedLockable: handleScopedLockableAttr(S, D, Attr); break; - case AttributeList::AT_NoAddressSafetyAnalysis: - handleNoAddressSafetyAttr(S, D, Attr); + case AttributeList::AT_NoSanitizeAddress: + handleNoSanitizeAddressAttr(S, D, Attr); break; case AttributeList::AT_NoThreadSafetyAnalysis: - handleNoThreadSafetyAttr(S, D, Attr); + handleNoThreadSafetyAnalysis(S, D, Attr); + break; + case AttributeList::AT_NoSanitizeThread: + handleNoSanitizeThread(S, D, Attr); + break; + case AttributeList::AT_NoSanitizeMemory: + handleNoSanitizeMemory(S, D, Attr); break; case AttributeList::AT_Lockable: handleLockableAttr(S, D, Attr); @@ -4530,19 +4992,17 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, /// 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). +/// silently ignore it if a GNU attribute. static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr, - bool NonInheritable, bool Inheritable) { + bool NonInheritable, bool Inheritable, + bool IncludeCXX11Attributes) { if (Attr.isInvalid()) return; - // Type attributes are still treated as declaration attributes by - // ParseMicrosoftTypeAttributes and ParseBorlandTypeAttributes. We don't - // want to process them, however, because we will simply warn about ignoring - // them. So instead, we will bail out early. - if (Attr.isMSTypespecAttribute()) + // Ignore C++11 attributes on declarator chunks: they appertain to the type + // instead. + if (Attr.isCXX11Attribute() && !IncludeCXX11Attributes) return; if (NonInheritable) @@ -4556,17 +5016,19 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, /// 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(*this, S, D, *l, NonInheritable, Inheritable); - } + bool NonInheritable, bool Inheritable, + bool IncludeCXX11Attributes) { + for (const AttributeList* l = AttrList; l; l = l->getNext()) + ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable, + IncludeCXX11Attributes); // 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(); + cast<NamedDecl>(D)->getNameAsString(); + D->dropAttr<WeakRefAttr>(); return; } } @@ -4592,7 +5054,7 @@ bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { for ( ; A; A = A->getNext()) { // Only warn if the attribute is an unignored, non-type attribute. - if (A->isUsedAsTypeAttr()) continue; + if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; if (A->getKind() == AttributeList::IgnoredAttribute) continue; if (A->getKind() == AttributeList::UnknownAttribute) { @@ -4630,8 +5092,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), Loc, Loc, DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), - SC_None, SC_None, - false/*isInlineSpecified*/, + SC_None, false/*isInlineSpecified*/, FD->hasPrototype(), false/*isConstexprSpecified*/); NewD = NewFD; @@ -4656,8 +5117,7 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(), VD->getInnerLocStart(), VD->getLocation(), II, VD->getType(), VD->getTypeSourceInfo(), - VD->getStorageClass(), - VD->getStorageClassAsWritten()); + VD->getStorageClass()); if (VD->getQualifier()) { VarDecl *NewVD = cast<VarDecl>(NewD); NewVD->setQualifierInfo(VD->getQualifierLoc()); @@ -4689,30 +5149,37 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { } } -/// 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) { +void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { // It's valid to "forward-declare" #pragma weak, in which case we // have to do this. - if (Inheritable) { - LoadExternalWeakUndeclaredIdentifiers(); - if (!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; - } + LoadExternalWeakUndeclaredIdentifiers(); + if (!WeakUndeclaredIdentifiers.empty()) { + NamedDecl *ND = NULL; + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + if (VD->isExternC()) + ND = VD; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isExternC()) + ND = FD; + if (ND) { + if (IdentifierInfo *Id = ND->getIdentifier()) { + llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I + = WeakUndeclaredIdentifiers.find(Id); + if (I != WeakUndeclaredIdentifiers.end()) { + WeakInfo W = I->second; + DeclApplyPragmaWeak(S, ND, W); + WeakUndeclaredIdentifiers[Id] = W; } } } } +} +/// 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) { // Apply decl attributes from the DeclSpec if present. if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable); @@ -4723,7 +5190,8 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD, // 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); + ProcessDeclAttributeList(S, D, Attrs, NonInheritable, Inheritable, + /*IncludeCXX11Attributes=*/false); // Finally, apply any attributes on the decl itself. if (const AttributeList *Attrs = PD.getAttributes()) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 16eddf8..35890e6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -12,16 +12,11 @@ //===----------------------------------------------------------------------===// #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/Sema/ScopeInfo.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/CharUnits.h" #include "clang/AST/DeclVisitor.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" @@ -30,12 +25,18 @@ #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/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/SmallString.h" +#include "clang/Sema/CXXFieldCollector.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include <map> #include <set> @@ -251,7 +252,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, return true; Arg = Result.takeAs<Expr>(); - CheckImplicitConversions(Arg, EqualLoc); + CheckCompletedExpr(Arg, EqualLoc); Arg = MaybeCreateExprWithCleanups(Arg); // Okay: add the default argument to the parameter @@ -351,16 +352,25 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { // 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. + bool MightBeFunction = D.isFunctionDeclarationContext(); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { DeclaratorChunk &chunk = D.getTypeObject(i); if (chunk.Kind == DeclaratorChunk::Function) { + if (MightBeFunction) { + // This is a function declaration. It can have default arguments, but + // keep looking in case its return type is a function type with default + // arguments. + MightBeFunction = false; + continue; + } 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()); + << SourceRange((*Toks)[1].getLocation(), + Toks->back().getLocation()); delete Toks; chunk.Fun.ArgInfo[argIdx].DefaultArgTokens = 0; } else if (Param->getDefaultArg()) { @@ -369,6 +379,8 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { Param->setDefaultArg(0); } } + } else if (chunk.Kind != DeclaratorChunk::Paren) { + MightBeFunction = false; } } } @@ -517,19 +529,26 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, 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; - } } } } + // DR1344: If a default argument is added outside a class definition and that + // default argument makes the function a special member function, the program + // is ill-formed. This can only happen for constructors. + if (isa<CXXConstructorDecl>(New) && + New->getMinRequiredArguments() < Old->getMinRequiredArguments()) { + CXXSpecialMember NewSM = getSpecialMember(cast<CXXMethodDecl>(New)), + OldSM = getSpecialMember(cast<CXXMethodDecl>(Old)); + if (NewSM != OldSM) { + ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments()); + assert(NewParam->hasDefaultArg()); + Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special) + << NewParam->getDefaultArgRange() << NewSM; + Diag(Old->getLocation(), diag::note_previous_declaration); + } + } + // C++11 [dcl.constexpr]p1: If any declaration of a function or function // template has a constexpr specifier then all its declarations shall // contain the constexpr specifier. @@ -875,7 +894,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { // - its function-body shall be [...] a compound-statement that contains only CompoundStmt *CompBody = cast<CompoundStmt>(Body); - llvm::SmallVector<SourceLocation, 4> ReturnStmts; + SmallVector<SourceLocation, 4> ReturnStmts; for (CompoundStmt::body_iterator BodyIt = CompBody->body_begin(), BodyEnd = CompBody->body_end(); BodyIt != BodyEnd; ++BodyIt) { switch ((*BodyIt)->getStmtClass()) { @@ -985,13 +1004,14 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { // C++11 [dcl.constexpr]p4: // - every constructor involved in initializing non-static data members and // base class sub-objects shall be a constexpr constructor. - llvm::SmallVector<PartialDiagnosticAt, 8> Diags; + SmallVector<PartialDiagnosticAt, 8> Diags; if (!Expr::isPotentialConstantExpr(Dcl, Diags)) { - Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr) + Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr) << isa<CXXConstructorDecl>(Dcl); for (size_t I = 0, N = Diags.size(); I != N; ++I) Diag(Diags[I].first, Diags[I].second); - return false; + // Don't return false here: we allow this for compatibility in + // system headers. } return true; @@ -1163,6 +1183,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, /// 'public bar' and 'virtual private baz' are each base-specifiers. BaseResult Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, + ParsedAttributes &Attributes, bool Virtual, AccessSpecifier Access, ParsedType basetype, SourceLocation BaseLoc, SourceLocation EllipsisLoc) { @@ -1174,6 +1195,22 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, if (!Class) return true; + // We do not support any C++11 attributes on base-specifiers yet. + // Diagnose any attributes we see. + if (!Attributes.empty()) { + for (AttributeList *Attr = Attributes.getList(); Attr; + Attr = Attr->getNext()) { + if (Attr->isInvalid() || + Attr->getKind() == AttributeList::IgnoredAttribute) + continue; + Diag(Attr->getLoc(), + Attr->getKind() == AttributeList::UnknownAttribute + ? diag::warn_unknown_attribute_ignored + : diag::err_base_specifier_attribute) + << Attr->getName(); + } + } + TypeSourceInfo *TInfo = 0; GetTypeFromParser(basetype, &TInfo); @@ -1274,29 +1311,25 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases, (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 (!getLangOpts().CPlusPlus) return false; - CXXRecordDecl *DerivedRD = GetClassForType(Derived); + CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; - CXXRecordDecl *BaseRD = GetClassForType(Base); + CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; - + + // If either the base or the derived type is invalid, don't try to + // check whether one is derived from the other. + if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) + return false; + // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); } @@ -1307,11 +1340,11 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { if (!getLangOpts().CPlusPlus) return false; - CXXRecordDecl *DerivedRD = GetClassForType(Derived); + CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; - CXXRecordDecl *BaseRD = GetClassForType(Base); + CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); if (!BaseRD) return false; @@ -1556,7 +1589,7 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { /// bitfield width if there is one, 'InitExpr' specifies the initializer if /// one has been parsed, and 'InitStyle' is set if an in-class initializer is /// present (but parsing it has been deferred). -Decl * +NamedDecl * Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BW, const VirtSpecifiers &VS, @@ -1657,7 +1690,36 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && !isFunc); - Decl *Member; + if (DS.isConstexprSpecified() && isInstField) { + SemaDiagnosticBuilder B = + Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member); + SourceLocation ConstexprLoc = DS.getConstexprSpecLoc(); + if (InitStyle == ICIS_NoInit) { + B << 0 << 0 << FixItHint::CreateReplacement(ConstexprLoc, "const"); + D.getMutableDeclSpec().ClearConstexprSpec(); + const char *PrevSpec; + unsigned DiagID; + bool Failed = D.getMutableDeclSpec().SetTypeQual(DeclSpec::TQ_const, ConstexprLoc, + PrevSpec, DiagID, getLangOpts()); + (void)Failed; + assert(!Failed && "Making a constexpr member const shouldn't fail"); + } else { + B << 1; + const char *PrevSpec; + unsigned DiagID; + if (D.getMutableDeclSpec().SetStorageClassSpec( + *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID)) { + assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable && + "This is the only DeclSpec that should fail to be applied"); + B << 1; + } else { + B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static "); + isInstField = false; + } + } + } + + NamedDecl *Member; if (isInstField) { CXXScopeSpec &SS = D.getCXXScopeSpec(); @@ -1711,7 +1773,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, InitStyle, AS); assert(Member && "HandleField never returns null"); } else { - assert(InitStyle == ICIS_NoInit); + assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static); Member = HandleDeclarator(S, D, TemplateParameterLists); if (!Member) { @@ -1795,7 +1857,11 @@ namespace { public: typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited; UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context), - S(S), VD(VD) { + S(S) { + if (IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(VD)) + this->VD = IFD->getAnonField(); + else + this->VD = VD; } void HandleExpr(Expr *E) { @@ -1812,23 +1878,33 @@ namespace { if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { if (isa<EnumConstantDecl>(ME->getMemberDecl())) - return; + return; + + // FieldME is the inner-most MemberExpr that is not an anonymous struct + // or union. + MemberExpr *FieldME = ME; + Expr *Base = E; while (isa<MemberExpr>(Base)) { - ME = dyn_cast<MemberExpr>(Base); - if (VarDecl *VarD = dyn_cast<VarDecl>(ME->getMemberDecl())) - if (VarD->hasGlobalStorage()) - return; + ME = cast<MemberExpr>(Base); + + if (isa<VarDecl>(ME->getMemberDecl())) + return; + + if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) + if (!FD->isAnonymousStructOrUnion()) + FieldME = ME; + Base = ME->getBase(); } - if (VD == ME->getMemberDecl() && isa<CXXThisExpr>(Base)) { + if (VD == FieldME->getMemberDecl() && isa<CXXThisExpr>(Base)) { unsigned diag = VD->getType()->isReferenceType() ? diag::warn_reference_field_is_uninit : diag::warn_field_is_uninit; - S.Diag(ME->getExprLoc(), diag) << ME->getMemberNameInfo().getName(); - return; + S.Diag(FieldME->getExprLoc(), diag) << VD; } + return; } if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { @@ -1909,11 +1985,7 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, } ExprResult Init = InitExpr; - if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent() && - !FD->getDeclContext()->isDependentContext()) { - // Note: We don't type-check when we're in a dependent context, because - // the initialization-substitution code does not properly handle direct - // list initialization. We have the same hackaround for ctor-initializers. + if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { if (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) { Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) << /*at end of ctor*/1 << InitExpr->getSourceRange(); @@ -1930,14 +2002,12 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, FD->setInvalidDecl(); return; } - - CheckImplicitConversions(Init.get(), InitLoc); } - // C++0x [class.base.init]p7: + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - Init = MaybeCreateExprWithCleanups(Init); + Init = ActOnFinishFullExpr(Init.take(), InitLoc); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -2096,10 +2166,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD, // Look for a member, first. DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); - if (Result.first != Result.second) { + if (!Result.empty()) { ValueDecl *Member; - if ((Member = dyn_cast<FieldDecl>(*Result.first)) || - (Member = dyn_cast<IndirectFieldDecl>(*Result.first))) { + if ((Member = dyn_cast<FieldDecl>(Result.front())) || + (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) << MemberOrBase @@ -2295,10 +2365,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { Args = ParenList->getExprs(); NumArgs = ParenList->getNumExprs(); - } else { - InitListExpr *InitList = cast<InitListExpr>(Init); + } else if (InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) { Args = InitList->getInits(); NumArgs = InitList->getNumInits(); + } else { + // Template instantiation doesn't reconstruct ParenListExprs for us. + Args = &Init; + NumArgs = 1; } if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc) @@ -2349,29 +2422,15 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, if (MemberInit.isInvalid()) return true; - CheckImplicitConversions(MemberInit.get(), - InitRange.getBegin()); - - // C++0x [class.base.init]p7: + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - MemberInit = MaybeCreateExprWithCleanups(MemberInit); + MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); 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. - // 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()) { - // The existing Init will do fine. - } else { - Init = MemberInit.get(); - CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); - } + Init = MemberInit.get(); + CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); } if (DirectMember) { @@ -2389,7 +2448,7 @@ MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, CXXRecordDecl *ClassDecl) { SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); - if (!LangOpts.CPlusPlus0x) + if (!LangOpts.CPlusPlus11) return Diag(NameLoc, diag::err_delegating_ctor) << TInfo->getTypeLoc().getLocalSourceRange(); Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); @@ -2421,12 +2480,11 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() && "Delegating constructor with no target?"); - CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin()); - - // C++0x [class.base.init]p7: + // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - DelegationInit = MaybeCreateExprWithCleanups(DelegationInit); + DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), + InitRange.getBegin()); if (DelegationInit.isInvalid()) return true; @@ -2555,12 +2613,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (BaseInit.isInvalid()) return true; - CheckImplicitConversions(BaseInit.get(), InitRange.getBegin()); - - // C++0x [class.base.init]p7: - // The initialization of each base and member constitutes a + // C++11 [class.base.init]p7: + // The initialization of each base and member constitutes a // full-expression. - BaseInit = MaybeCreateExprWithCleanups(BaseInit); + BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); if (BaseInit.isInvalid()) return true; @@ -2582,9 +2638,10 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, } // Create a static_cast\<T&&>(expr). -static Expr *CastForMoving(Sema &SemaRef, Expr *E) { - QualType ExprType = E->getType(); - QualType TargetType = SemaRef.Context.getRValueReferenceType(ExprType); +static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) { + if (T.isNull()) T = E->getType(); + QualType TargetType = SemaRef.BuildReferenceType( + T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName()); SourceLocation ExprLoc = E->getLocStart(); TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo( TargetType, ExprLoc); @@ -2599,7 +2656,8 @@ static Expr *CastForMoving(Sema &SemaRef, Expr *E) { enum ImplicitInitializerKind { IIK_Default, IIK_Copy, - IIK_Move + IIK_Move, + IIK_Inherit }; static bool @@ -2615,6 +2673,35 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, ExprResult BaseInit; switch (ImplicitInitKind) { + case IIK_Inherit: { + const CXXRecordDecl *Inherited = + Constructor->getInheritedConstructor()->getParent(); + const CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl(); + if (Base && Inherited->getCanonicalDecl() == Base->getCanonicalDecl()) { + // C++11 [class.inhctor]p8: + // Each expression in the expression-list is of the form + // static_cast<T&&>(p), where p is the name of the corresponding + // constructor parameter and T is the declared type of p. + SmallVector<Expr*, 16> Args; + for (unsigned I = 0, E = Constructor->getNumParams(); I != E; ++I) { + ParmVarDecl *PD = Constructor->getParamDecl(I); + ExprResult ArgExpr = + SemaRef.BuildDeclRefExpr(PD, PD->getType().getNonReferenceType(), + VK_LValue, SourceLocation()); + if (ArgExpr.isInvalid()) + return true; + Args.push_back(CastForMoving(SemaRef, ArgExpr.take(), PD->getType())); + } + + InitializationKind InitKind = InitializationKind::CreateDirect( + Constructor->getLocation(), SourceLocation(), SourceLocation()); + InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, + Args.data(), Args.size()); + BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, Args); + break; + } + } + // Fall through. case IIK_Default: { InitializationKind InitKind = InitializationKind::CreateDefault(Constructor->getLocation()); @@ -2765,7 +2852,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc, IterationVarName, SizeType, SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None, SC_None); + SC_None); IndexVariables.push_back(IterationVar); // Create a reference to the iteration variable. @@ -2837,7 +2924,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, return false; } - assert(ImplicitInitKind == IIK_Default && "Unhandled implicit init kind!"); + assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) && + "Unhandled implicit init kind!"); QualType FieldBaseElementType = SemaRef.Context.getBaseElementType(Field->getType()); @@ -2928,6 +3016,8 @@ struct BaseAndFieldInfo { IIK = IIK_Copy; else if (Generated && Ctor->isMoveConstructor()) IIK = IIK_Move; + else if (Ctor->getInheritedConstructor()) + IIK = IIK_Inherit; else IIK = IIK_Default; } @@ -2939,6 +3029,7 @@ struct BaseAndFieldInfo { return true; case IIK_Default: + case IIK_Inherit: return false; } @@ -3059,19 +3150,17 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, return false; } -bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, - CXXCtorInitializer **Initializers, - unsigned NumInitializers, - bool AnyErrors) { +bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, + ArrayRef<CXXCtorInitializer *> Initializers) { if (Constructor->isDependentContext()) { // Just store the initializers as written, they will be checked during // instantiation. - if (NumInitializers > 0) { - Constructor->setNumCtorInitializers(NumInitializers); + if (!Initializers.empty()) { + Constructor->setNumCtorInitializers(Initializers.size()); CXXCtorInitializer **baseOrMemberInitializers = - new (Context) CXXCtorInitializer*[NumInitializers]; - memcpy(baseOrMemberInitializers, Initializers, - NumInitializers * sizeof(CXXCtorInitializer*)); + new (Context) CXXCtorInitializer*[Initializers.size()]; + memcpy(baseOrMemberInitializers, Initializers.data(), + Initializers.size() * sizeof(CXXCtorInitializer*)); Constructor->setCtorInitializers(baseOrMemberInitializers); } @@ -3092,7 +3181,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool HadError = false; - for (unsigned i = 0; i < NumInitializers; i++) { + for (unsigned i = 0; i < Initializers.size(); i++) { CXXCtorInitializer *Member = Initializers[i]; if (Member->isBaseInitializer()) @@ -3168,7 +3257,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, // If we're not generating the implicit copy/move constructor, then we'll // handle anonymous struct/union fields based on their individual // indirect fields. - if (F->isAnonymousStructOrUnion() && Info.IIK == IIK_Default) + if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove()) continue; if (CollectFieldInitializer(*this, Info, F)) @@ -3177,7 +3266,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, } // Beyond this point, we only consider default initialization. - if (Info.IIK != IIK_Default) + if (Info.isImplicitCopyOrMove()) continue; if (IndirectFieldDecl *F = dyn_cast<IndirectFieldDecl>(*Mem)) { @@ -3195,7 +3284,7 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, } } - NumInitializers = Info.AllToInit.size(); + unsigned NumInitializers = Info.AllToInit.size(); if (NumInitializers > 0) { Constructor->setNumCtorInitializers(NumInitializers); CXXCtorInitializer **baseOrMemberInitializers = @@ -3213,13 +3302,17 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, return HadError; } -static void *GetKeyForTopLevelField(FieldDecl *Field) { - // For anonymous unions, use the class declaration as the key. +static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) { if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { - if (RT->getDecl()->isAnonymousStructOrUnion()) - return static_cast<void *>(RT->getDecl()); + const RecordDecl *RD = RT->getDecl(); + if (RD->isAnonymousStructOrUnion()) { + for (RecordDecl::field_iterator Field = RD->field_begin(), + E = RD->field_end(); Field != E; ++Field) + PopulateKeysForFields(*Field, IdealInits); + return; + } } - return static_cast<void *>(Field); + IdealInits.push_back(Field); } static void *GetKeyForBase(ASTContext &Context, QualType BaseType) { @@ -3231,40 +3324,19 @@ static void *GetKeyForMember(ASTContext &Context, 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); + return Member->getAnyMember(); } -static void -DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, - const CXXConstructorDecl *Constructor, - CXXCtorInitializer **Inits, - unsigned NumInits) { +static void DiagnoseBaseOrMemInitializerOrder( + Sema &SemaRef, const CXXConstructorDecl *Constructor, + ArrayRef<CXXCtorInitializer *> Inits) { 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) { + for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { CXXCtorInitializer *Init = Inits[InitIndex]; if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order, Init->getSourceLocation()) @@ -3303,14 +3375,14 @@ DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef, if (Field->isUnnamedBitfield()) continue; - IdealInitKeys.push_back(GetKeyForTopLevelField(*Field)); + PopulateKeysForFields(*Field, IdealInitKeys); } unsigned NumIdealInits = IdealInitKeys.size(); unsigned IdealIndex = 0; CXXCtorInitializer *PrevInit = 0; - for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) { + for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { CXXCtorInitializer *Init = Inits[InitIndex]; void *InitKey = GetKeyForMember(SemaRef.Context, Init); @@ -3360,7 +3432,7 @@ bool CheckRedundantInit(Sema &S, return false; } - if (FieldDecl *Field = Init->getMember()) + if (FieldDecl *Field = Init->getAnyMember()) S.Diag(Init->getSourceLocation(), diag::err_multiple_mem_initialization) << Field->getDeclName() @@ -3420,8 +3492,7 @@ bool CheckRedundantUnionInit(Sema &S, /// ActOnMemInitializers - Handle the member initializers for a constructor. void Sema::ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, - CXXCtorInitializer **meminits, - unsigned NumMemInits, + ArrayRef<CXXCtorInitializer*> MemInits, bool AnyErrors) { if (!ConstructorDecl) return; @@ -3436,9 +3507,6 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, 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*. @@ -3448,7 +3516,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, RedundantUnionMap MemberUnions; bool HadError = false; - for (unsigned i = 0; i < NumMemInits; i++) { + for (unsigned i = 0; i < MemInits.size(); i++) { CXXCtorInitializer *Init = MemInits[i]; // Set the source order index. @@ -3466,7 +3534,7 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, } else { assert(Init->isDelegatingInitializer()); // This must be the only initializer - if (NumMemInits != 1) { + if (MemInits.size() != 1) { Diag(Init->getSourceLocation(), diag::err_delegating_initializer_alone) << Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange(); @@ -3481,9 +3549,9 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, if (HadError) return; - DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits, NumMemInits); + DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits); - SetCtorInitializers(Constructor, MemInits, NumMemInits, AnyErrors); + SetCtorInitializers(Constructor, AnyErrors, MemInits); } void @@ -3605,7 +3673,7 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(CDtorDecl)) - SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false); + SetCtorInitializers(Constructor, /*AnyErrors=*/false); } bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, @@ -3748,7 +3816,7 @@ struct CheckAbstractUsage { switch (TL.getTypeLocClass()) { #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ - case TypeLoc::CLASS: Check(cast<CLASS##TypeLoc>(TL), Sel); break; + case TypeLoc::CLASS: Check(TL.castAs<CLASS##TypeLoc>(), Sel); break; #include "clang/AST/TypeLocNodes.def" } } @@ -3933,9 +4001,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // 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; + DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; + ++I) { + NamedDecl *D = *I; if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) || isa<IndirectFieldDecl>(D)) { Diag(D->getLocation(), diag::err_member_name_of_class) @@ -3958,18 +4027,34 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { DiagnoseAbstractType(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) { + // See if a method overloads virtual methods in a base + // class without overriding any. if (!M->isStatic()) DiagnoseHiddenVirtualMethods(Record, *M); + + // Check whether the explicitly-defaulted special members are valid. + if (!M->isInvalidDecl() && M->isExplicitlyDefaulted()) + CheckExplicitlyDefaultedSpecialMember(*M); + + // For an explicitly defaulted or deleted special member, we defer + // determining triviality until the class is complete. That time is now! + if (!M->isImplicit() && !M->isUserProvided()) { + CXXSpecialMember CSM = getSpecialMember(*M); + if (CSM != CXXInvalid) { + M->setTrivial(SpecialMemberIsTrivial(*M, CSM)); + + // Inform the class that we've finished declaring this member. + Record->finishedDefaultedOrDeletedMember(*M); + } + } } } - // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member + // C++11 [dcl.constexpr]p8: A constexpr specifier for a non-static member // function that is not a constructor declares that member function to be // const. [...] The class of which that function is a member shall be // a literal type. @@ -3977,7 +4062,10 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { // If the class has virtual bases, any constexpr members will already have // been diagnosed by the checks performed on the member declaration, so // suppress this (less useful) diagnostic. - if (LangOpts.CPlusPlus0x && !Record->isDependentType() && + // + // We delay this until we know whether an explicitly-defaulted (or deleted) + // destructor for the class is trivial. + if (LangOpts.CPlusPlus11 && !Record->isDependentType() && !Record->isLiteral() && !Record->getNumVBases()) { for (CXXRecordDecl::method_iterator M = Record->method_begin(), MEnd = Record->method_end(); @@ -4005,22 +4093,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { } } - // Declare inherited constructors. We do this eagerly here because: - // - The standard requires an eager diagnostic for conflicting inherited + // Declare inheriting constructors. We do this eagerly here because: + // - The standard requires an eager diagnostic for conflicting inheriting // 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); -} - -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()) - CheckExplicitlyDefaultedSpecialMember(*MI); + // have inheriting constructors. + DeclareInheritingConstructors(Record); } /// Is the special member function which would be selected to perform the @@ -4043,7 +4123,7 @@ static bool specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, static bool defaultedSpecialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, bool ConstArg) { - if (!S.getLangOpts().CPlusPlus0x) + if (!S.getLangOpts().CPlusPlus11) return false; // C++11 [dcl.constexpr]p4: @@ -4136,7 +4216,9 @@ computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) { case Sema::CXXInvalid: break; } - llvm_unreachable("only special members have implicit exception specs"); + assert(cast<CXXConstructorDecl>(MD)->getInheritedConstructor() && + "only special members have implicit exception specs"); + return S.ComputeInheritingCtorExceptionSpec(cast<CXXConstructorDecl>(MD)); } static void @@ -4145,8 +4227,7 @@ updateExceptionSpec(Sema &S, FunctionDecl *FD, const FunctionProtoType *FPT, FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); ExceptSpec.getEPI(EPI); const FunctionProtoType *NewFPT = cast<FunctionProtoType>( - S.Context.getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), - FPT->getNumArgs(), EPI)); + S.Context.getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI)); FD->setType(QualType(NewFPT, 0)); } @@ -4172,9 +4253,6 @@ void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) CanonicalFPT, ExceptSpec); } -static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl); -static bool isImplicitCopyAssignmentArgConst(Sema &S, CXXRecordDecl *ClassDecl); - void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { CXXRecordDecl *RD = MD->getParent(); CXXSpecialMember CSM = getSpecialMember(MD); @@ -4205,37 +4283,19 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { Diag(MD->getLocation(), diag::err_defaulted_special_member_params) << CSM << MD->getSourceRange(); HadError = true; + } else if (MD->isVariadic()) { + Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) + << CSM << MD->getSourceRange(); + HadError = true; } const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>(); - // Compute argument constness, constexpr, and triviality. bool CanHaveConstParam = false; - bool Trivial = false; - switch (CSM) { - case CXXDefaultConstructor: - Trivial = RD->hasTrivialDefaultConstructor(); - break; - case CXXCopyConstructor: - CanHaveConstParam = isImplicitCopyCtorArgConst(*this, RD); - Trivial = RD->hasTrivialCopyConstructor(); - break; - case CXXCopyAssignment: - CanHaveConstParam = isImplicitCopyAssignmentArgConst(*this, RD); - Trivial = RD->hasTrivialCopyAssignment(); - break; - case CXXMoveConstructor: - Trivial = RD->hasTrivialMoveConstructor(); - break; - case CXXMoveAssignment: - Trivial = RD->hasTrivialMoveAssignment(); - break; - case CXXDestructor: - Trivial = RD->hasTrivialDestructor(); - break; - case CXXInvalid: - llvm_unreachable("non-special member explicitly defaulted!"); - } + if (CSM == CXXCopyConstructor) + CanHaveConstParam = RD->implicitCopyConstructorHasConstParam(); + else if (CSM == CXXCopyAssignment) + CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam(); QualType ReturnType = Context.VoidTy; if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { @@ -4284,14 +4344,6 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { } HadError = true; } - - // If a function is explicitly defaulted on its first declaration, it shall - // have the same parameter type as if it had been implicitly declared. - // (Presumably this is to prevent it from being trivial?) - if (!HasConstParam && CanHaveConstParam && First) - Diag(MD->getLocation(), - diag::err_defaulted_special_member_copy_non_const_param) - << (CSM == CXXCopyAssignment); } else if (ExpectedParams) { // A copy assignment operator can take its argument by value, but a // defaulted one cannot. @@ -4300,16 +4352,6 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { HadError = true; } - // Rebuild the type with the implicit exception specification added, if we - // are going to need it. - const FunctionProtoType *ImplicitType = 0; - if (First || Type->hasExceptionSpec()) { - FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); - computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI); - ImplicitType = cast<FunctionProtoType>( - Context.getFunctionType(ReturnType, &ArgType, ExpectedParams, EPI)); - } - // C++11 [dcl.fct.def.default]p2: // An explicitly-defaulted function may be declared constexpr only if it // would have been implicitly declared as constexpr, @@ -4324,13 +4366,23 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // FIXME: Explain why the constructor can't be constexpr. HadError = true; } + // and may have an explicit exception-specification only if it is compatible // with the exception-specification on the implicit declaration. - if (Type->hasExceptionSpec() && - CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) << CSM, - PDiag(), ImplicitType, SourceLocation(), Type, MD->getLocation())) - HadError = true; + if (Type->hasExceptionSpec()) { + // Delay the check if this is the first declaration of the special member, + // since we may not have parsed some necessary in-class initializers yet. + if (First) { + // If the exception specification needs to be instantiated, do so now, + // before we clobber it with an EST_Unevaluated specification below. + if (Type->getExceptionSpecType() == EST_Uninstantiated) { + InstantiateExceptionSpec(MD->getLocStart(), MD); + Type = MD->getType()->getAs<FunctionProtoType>(); + } + DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type)); + } else + CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type); + } // If a function is explicitly defaulted on its first declaration, if (First) { @@ -4340,16 +4392,18 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // -- it is implicitly considered to have the same exception-specification // as if it had been implicitly declared, - MD->setType(QualType(ImplicitType, 0)); - - // Such a function is also trivial if the implicitly-declared function - // would have been. - MD->setTrivial(Trivial); + FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); + EPI.ExceptionSpecType = EST_Unevaluated; + EPI.ExceptionSpecDecl = MD; + MD->setType(Context.getFunctionType(ReturnType, + ArrayRef<QualType>(&ArgType, + ExpectedParams), + EPI)); } if (ShouldDeleteSpecialMember(MD, CSM)) { if (First) { - MD->setDeletedAsWritten(); + SetDeclDeleted(MD, MD->getLocation()); } else { // C++11 [dcl.fct.def.default]p4: // [For a] user-provided explicitly-defaulted function [...] if such a @@ -4363,6 +4417,36 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { MD->setInvalidDecl(); } +/// Check whether the exception specification provided for an +/// explicitly-defaulted special member matches the exception specification +/// that would have been generated for an implicit special member, per +/// C++11 [dcl.fct.def.default]p2. +void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( + CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) { + // Compute the implicit exception specification. + FunctionProtoType::ExtProtoInfo EPI; + computeImplicitExceptionSpec(*this, MD->getLocation(), MD).getEPI(EPI); + const FunctionProtoType *ImplicitType = cast<FunctionProtoType>( + Context.getFunctionType(Context.VoidTy, ArrayRef<QualType>(), EPI)); + + // Ensure that it matches. + CheckEquivalentExceptionSpec( + PDiag(diag::err_incorrect_defaulted_exception_spec) + << getSpecialMember(MD), PDiag(), + ImplicitType, SourceLocation(), + SpecifiedType, MD->getLocation()); +} + +void Sema::CheckDelayedExplicitlyDefaultedMemberExceptionSpecs() { + for (unsigned I = 0, N = DelayedDefaultedMemberExceptionSpecs.size(); + I != N; ++I) + CheckExplicitlyDefaultedMemberExceptionSpec( + DelayedDefaultedMemberExceptionSpecs[I].first, + DelayedDefaultedMemberExceptionSpecs[I].second); + + DelayedDefaultedMemberExceptionSpecs.clear(); +} + namespace { struct SpecialMemberDeletionInfo { Sema &S; @@ -4688,7 +4772,7 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, return false; CXXRecordDecl *RD = MD->getParent(); assert(!RD->isDependentType() && "do deletion after instantiation"); - if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl()) + if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl()) return false; // C++11 [expr.lambda.prim]p19: @@ -4722,12 +4806,28 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, if (RD->hasUserDeclaredMoveConstructor() && (!getLangOpts().MicrosoftMode || CSM == CXXCopyConstructor)) { if (!Diagnose) return true; - UserDeclaredMove = RD->getMoveConstructor(); + + // Find any user-declared move constructor. + for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), + E = RD->ctor_end(); I != E; ++I) { + if (I->isMoveConstructor()) { + UserDeclaredMove = *I; + break; + } + } assert(UserDeclaredMove); } else if (RD->hasUserDeclaredMoveAssignment() && (!getLangOpts().MicrosoftMode || CSM == CXXCopyAssignment)) { if (!Diagnose) return true; - UserDeclaredMove = RD->getMoveAssignmentOperator(); + + // Find any user-declared move assignment operator. + for (CXXRecordDecl::method_iterator I = RD->method_begin(), + E = RD->method_end(); I != E; ++I) { + if (I->isMoveAssignmentOperator()) { + UserDeclaredMove = *I; + break; + } + } assert(UserDeclaredMove); } @@ -4783,6 +4883,422 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, return false; } +/// Perform lookup for a special member of the specified kind, and determine +/// whether it is trivial. If the triviality can be determined without the +/// lookup, skip it. This is intended for use when determining whether a +/// special member of a containing object is trivial, and thus does not ever +/// perform overload resolution for default constructors. +/// +/// If \p Selected is not \c NULL, \c *Selected will be filled in with the +/// member that was most likely to be intended to be trivial, if any. +static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, + Sema::CXXSpecialMember CSM, unsigned Quals, + CXXMethodDecl **Selected) { + if (Selected) + *Selected = 0; + + switch (CSM) { + case Sema::CXXInvalid: + llvm_unreachable("not a special member"); + + case Sema::CXXDefaultConstructor: + // C++11 [class.ctor]p5: + // A default constructor is trivial if: + // - all the [direct subobjects] have trivial default constructors + // + // Note, no overload resolution is performed in this case. + if (RD->hasTrivialDefaultConstructor()) + return true; + + if (Selected) { + // If there's a default constructor which could have been trivial, dig it + // out. Otherwise, if there's any user-provided default constructor, point + // to that as an example of why there's not a trivial one. + CXXConstructorDecl *DefCtor = 0; + if (RD->needsImplicitDefaultConstructor()) + S.DeclareImplicitDefaultConstructor(RD); + for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(), + CE = RD->ctor_end(); CI != CE; ++CI) { + if (!CI->isDefaultConstructor()) + continue; + DefCtor = *CI; + if (!DefCtor->isUserProvided()) + break; + } + + *Selected = DefCtor; + } + + return false; + + case Sema::CXXDestructor: + // C++11 [class.dtor]p5: + // A destructor is trivial if: + // - all the direct [subobjects] have trivial destructors + if (RD->hasTrivialDestructor()) + return true; + + if (Selected) { + if (RD->needsImplicitDestructor()) + S.DeclareImplicitDestructor(RD); + *Selected = RD->getDestructor(); + } + + return false; + + case Sema::CXXCopyConstructor: + // C++11 [class.copy]p12: + // A copy constructor is trivial if: + // - the constructor selected to copy each direct [subobject] is trivial + if (RD->hasTrivialCopyConstructor()) { + if (Quals == Qualifiers::Const) + // We must either select the trivial copy constructor or reach an + // ambiguity; no need to actually perform overload resolution. + return true; + } else if (!Selected) { + return false; + } + // In C++98, we are not supposed to perform overload resolution here, but we + // treat that as a language defect, as suggested on cxx-abi-dev, to treat + // cases like B as having a non-trivial copy constructor: + // struct A { template<typename T> A(T&); }; + // struct B { mutable A a; }; + goto NeedOverloadResolution; + + case Sema::CXXCopyAssignment: + // C++11 [class.copy]p25: + // A copy assignment operator is trivial if: + // - the assignment operator selected to copy each direct [subobject] is + // trivial + if (RD->hasTrivialCopyAssignment()) { + if (Quals == Qualifiers::Const) + return true; + } else if (!Selected) { + return false; + } + // In C++98, we are not supposed to perform overload resolution here, but we + // treat that as a language defect. + goto NeedOverloadResolution; + + case Sema::CXXMoveConstructor: + case Sema::CXXMoveAssignment: + NeedOverloadResolution: + Sema::SpecialMemberOverloadResult *SMOR = + S.LookupSpecialMember(RD, CSM, + Quals & Qualifiers::Const, + Quals & Qualifiers::Volatile, + /*RValueThis*/false, /*ConstThis*/false, + /*VolatileThis*/false); + + // The standard doesn't describe how to behave if the lookup is ambiguous. + // We treat it as not making the member non-trivial, just like the standard + // mandates for the default constructor. This should rarely matter, because + // the member will also be deleted. + if (SMOR->getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) + return true; + + if (!SMOR->getMethod()) { + assert(SMOR->getKind() == + Sema::SpecialMemberOverloadResult::NoMemberOrDeleted); + return false; + } + + // We deliberately don't check if we found a deleted special member. We're + // not supposed to! + if (Selected) + *Selected = SMOR->getMethod(); + return SMOR->getMethod()->isTrivial(); + } + + llvm_unreachable("unknown special method kind"); +} + +static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) { + for (CXXRecordDecl::ctor_iterator CI = RD->ctor_begin(), CE = RD->ctor_end(); + CI != CE; ++CI) + if (!CI->isImplicit()) + return *CI; + + // Look for constructor templates. + typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter; + for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); TI != TE; ++TI) { + if (CXXConstructorDecl *CD = + dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl())) + return CD; + } + + return 0; +} + +/// The kind of subobject we are checking for triviality. The values of this +/// enumeration are used in diagnostics. +enum TrivialSubobjectKind { + /// The subobject is a base class. + TSK_BaseClass, + /// The subobject is a non-static data member. + TSK_Field, + /// The object is actually the complete object. + TSK_CompleteObject +}; + +/// Check whether the special member selected for a given type would be trivial. +static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, + QualType SubType, + Sema::CXXSpecialMember CSM, + TrivialSubobjectKind Kind, + bool Diagnose) { + CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl(); + if (!SubRD) + return true; + + CXXMethodDecl *Selected; + if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(), + Diagnose ? &Selected : 0)) + return true; + + if (Diagnose) { + if (!Selected && CSM == Sema::CXXDefaultConstructor) { + S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor) + << Kind << SubType.getUnqualifiedType(); + if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD)) + S.Diag(CD->getLocation(), diag::note_user_declared_ctor); + } else if (!Selected) + S.Diag(SubobjLoc, diag::note_nontrivial_no_copy) + << Kind << SubType.getUnqualifiedType() << CSM << SubType; + else if (Selected->isUserProvided()) { + if (Kind == TSK_CompleteObject) + S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided) + << Kind << SubType.getUnqualifiedType() << CSM; + else { + S.Diag(SubobjLoc, diag::note_nontrivial_user_provided) + << Kind << SubType.getUnqualifiedType() << CSM; + S.Diag(Selected->getLocation(), diag::note_declared_at); + } + } else { + if (Kind != TSK_CompleteObject) + S.Diag(SubobjLoc, diag::note_nontrivial_subobject) + << Kind << SubType.getUnqualifiedType() << CSM; + + // Explain why the defaulted or deleted special member isn't trivial. + S.SpecialMemberIsTrivial(Selected, CSM, Diagnose); + } + } + + return false; +} + +/// Check whether the members of a class type allow a special member to be +/// trivial. +static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, + Sema::CXXSpecialMember CSM, + bool ConstArg, bool Diagnose) { + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); FI != FE; ++FI) { + if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) + continue; + + QualType FieldType = S.Context.getBaseElementType(FI->getType()); + + // Pretend anonymous struct or union members are members of this class. + if (FI->isAnonymousStructOrUnion()) { + if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(), + CSM, ConstArg, Diagnose)) + return false; + continue; + } + + // C++11 [class.ctor]p5: + // A default constructor is trivial if [...] + // -- no non-static data member of its class has a + // brace-or-equal-initializer + if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) { + if (Diagnose) + S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << *FI; + return false; + } + + // Objective C ARC 4.3.5: + // [...] nontrivally ownership-qualified types are [...] not trivially + // default constructible, copy constructible, move constructible, copy + // assignable, move assignable, or destructible [...] + if (S.getLangOpts().ObjCAutoRefCount && + FieldType.hasNonTrivialObjCLifetime()) { + if (Diagnose) + S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) + << RD << FieldType.getObjCLifetime(); + return false; + } + + if (ConstArg && !FI->isMutable()) + FieldType.addConst(); + if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, CSM, + TSK_Field, Diagnose)) + return false; + } + + return true; +} + +/// Diagnose why the specified class does not have a trivial special member of +/// the given kind. +void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { + QualType Ty = Context.getRecordType(RD); + if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) + Ty.addConst(); + + checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, CSM, + TSK_CompleteObject, /*Diagnose*/true); +} + +/// Determine whether a defaulted or deleted special member function is trivial, +/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, +/// C++11 [class.copy]p25, and C++11 [class.dtor]p5. +bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, + bool Diagnose) { + assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough"); + + CXXRecordDecl *RD = MD->getParent(); + + bool ConstArg = false; + + // C++11 [class.copy]p12, p25: + // A [special member] is trivial if its declared parameter type is the same + // as if it had been implicitly declared [...] + switch (CSM) { + case CXXDefaultConstructor: + case CXXDestructor: + // Trivial default constructors and destructors cannot have parameters. + break; + + case CXXCopyConstructor: + case CXXCopyAssignment: { + // Trivial copy operations always have const, non-volatile parameter types. + ConstArg = true; + const ParmVarDecl *Param0 = MD->getParamDecl(0); + const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>(); + if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) { + if (Diagnose) + Diag(Param0->getLocation(), diag::note_nontrivial_param_type) + << Param0->getSourceRange() << Param0->getType() + << Context.getLValueReferenceType( + Context.getRecordType(RD).withConst()); + return false; + } + break; + } + + case CXXMoveConstructor: + case CXXMoveAssignment: { + // Trivial move operations always have non-cv-qualified parameters. + const ParmVarDecl *Param0 = MD->getParamDecl(0); + const RValueReferenceType *RT = + Param0->getType()->getAs<RValueReferenceType>(); + if (!RT || RT->getPointeeType().getCVRQualifiers()) { + if (Diagnose) + Diag(Param0->getLocation(), diag::note_nontrivial_param_type) + << Param0->getSourceRange() << Param0->getType() + << Context.getRValueReferenceType(Context.getRecordType(RD)); + return false; + } + break; + } + + case CXXInvalid: + llvm_unreachable("not a special member"); + } + + // FIXME: We require that the parameter-declaration-clause is equivalent to + // that of an implicit declaration, not just that the declared parameter type + // matches, in order to prevent absuridities like a function simultaneously + // being a trivial copy constructor and a non-trivial default constructor. + // This issue has not yet been assigned a core issue number. + if (MD->getMinRequiredArguments() < MD->getNumParams()) { + if (Diagnose) + Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(), + diag::note_nontrivial_default_arg) + << MD->getParamDecl(MD->getMinRequiredArguments())->getSourceRange(); + return false; + } + if (MD->isVariadic()) { + if (Diagnose) + Diag(MD->getLocation(), diag::note_nontrivial_variadic); + return false; + } + + // C++11 [class.ctor]p5, C++11 [class.dtor]p5: + // A copy/move [constructor or assignment operator] is trivial if + // -- the [member] selected to copy/move each direct base class subobject + // is trivial + // + // C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [default constructor or destructor] is trivial if + // -- all the direct base classes have trivial [default constructors or + // destructors] + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); BI != BE; ++BI) + if (!checkTrivialSubobjectCall(*this, BI->getLocStart(), + ConstArg ? BI->getType().withConst() + : BI->getType(), + CSM, TSK_BaseClass, Diagnose)) + return false; + + // C++11 [class.ctor]p5, C++11 [class.dtor]p5: + // A copy/move [constructor or assignment operator] for a class X is + // trivial if + // -- for each non-static data member of X that is of class type (or array + // thereof), the constructor selected to copy/move that member is + // trivial + // + // C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [default constructor or destructor] is trivial if + // -- for all of the non-static data members of its class that are of class + // type (or array thereof), each such class has a trivial [default + // constructor or destructor] + if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, Diagnose)) + return false; + + // C++11 [class.dtor]p5: + // A destructor is trivial if [...] + // -- the destructor is not virtual + if (CSM == CXXDestructor && MD->isVirtual()) { + if (Diagnose) + Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD; + return false; + } + + // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: + // A [special member] for class X is trivial if [...] + // -- class X has no virtual functions and no virtual base classes + if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) { + if (!Diagnose) + return false; + + if (RD->getNumVBases()) { + // Check for virtual bases. We already know that the corresponding + // member in all bases is trivial, so vbases must all be direct. + CXXBaseSpecifier &BS = *RD->vbases_begin(); + assert(BS.isVirtual()); + Diag(BS.getLocStart(), diag::note_nontrivial_has_virtual) << RD << 1; + return false; + } + + // Must have a virtual method. + for (CXXRecordDecl::method_iterator MI = RD->method_begin(), + ME = RD->method_end(); MI != ME; ++MI) { + if (MI->isVirtual()) { + SourceLocation MLoc = MI->getLocStart(); + Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0; + return false; + } + } + + llvm_unreachable("dynamic class with no vbases and no virtual functions"); + } + + // Looks like it's trivial! + return true; +} + /// \brief Data used with FindHiddenVirtualMethod namespace { struct FindHiddenVirtualMethodData { @@ -4823,9 +5339,9 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, bool foundSameNameMethod = false; SmallVector<CXXMethodDecl *, 8> overloadedMethods; for (Path.Decls = BaseRecord->lookup(Name); - Path.Decls.first != Path.Decls.second; - ++Path.Decls.first) { - NamedDecl *D = *Path.Decls.first; + !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + NamedDecl *D = Path.Decls.front(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { MD = MD->getCanonicalDecl(); foundSameNameMethod = true; @@ -4877,10 +5393,10 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { // 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) { - NamedDecl *ND = *res.first; - if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first)) + DeclContext::lookup_result R = DC->lookup(MD->getDeclName()); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { + NamedDecl *ND = *I; + if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I)) ND = shad->getTargetDecl(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods); @@ -4935,39 +5451,53 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { if (!ClassDecl->hasUserDeclaredConstructor()) ++ASTContext::NumImplicitDefaultConstructors; - if (!ClassDecl->hasUserDeclaredCopyConstructor()) + if (!ClassDecl->hasUserDeclaredCopyConstructor()) { ++ASTContext::NumImplicitCopyConstructors; - if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveConstructor()) + // If the properties or semantics of the copy constructor couldn't be + // determined while the class was being declared, force a declaration + // of it now. + if (ClassDecl->needsOverloadResolutionForCopyConstructor()) + DeclareImplicitCopyConstructor(ClassDecl); + } + + if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) { ++ASTContext::NumImplicitMoveConstructors; + if (ClassDecl->needsOverloadResolutionForMoveConstructor()) + DeclareImplicitMoveConstructor(ClassDecl); + } + if (!ClassDecl->hasUserDeclaredCopyAssignment()) { ++ASTContext::NumImplicitCopyAssignmentOperators; - - // If we have a dynamic class, then the copy assignment operator may be + + // 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()) + // it shows up in the right place in the vtable and that we diagnose + // problems with the implicit exception specification. + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForCopyAssignment()) DeclareImplicitCopyAssignment(ClassDecl); } - if (getLangOpts().CPlusPlus0x && ClassDecl->needsImplicitMoveAssignment()) { + if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) { ++ASTContext::NumImplicitMoveAssignmentOperators; // Likewise for the move assignment operator. - if (ClassDecl->isDynamicClass()) + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForMoveAssignment()) DeclareImplicitMoveAssignment(ClassDecl); } if (!ClassDecl->hasUserDeclaredDestructor()) { ++ASTContext::NumImplicitDestructors; - - // If we have a dynamic class, then the destructor may be virtual, so we + + // 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()) + if (ClassDecl->isDynamicClass() || + ClassDecl->needsOverloadResolutionForDestructor()) DeclareImplicitDestructor(ClassDecl); } } @@ -5150,8 +5680,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; - return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), - Proto->getNumArgs(), EPI); + return Context.getFunctionType(Context.VoidTy, Proto->getArgTypes(), EPI); } /// CheckConstructor - Checks a fully-formed constructor for @@ -5331,7 +5860,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, EPI.Variadic = false; EPI.TypeQuals = 0; EPI.RefQualifier = RQ_None; - return Context.getFunctionType(Context.VoidTy, 0, 0, EPI); + return Context.getFunctionType(Context.VoidTy, ArrayRef<QualType>(), EPI); } /// CheckConversionDeclarator - Called by ActOnDeclarator to check the @@ -5412,12 +5941,13 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // 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()); + R = Context.getFunctionType(ConvType, ArrayRef<QualType>(), + Proto->getExtProtoInfo()); // C++0x explicit conversion operators. if (D.getDeclSpec().isExplicitSpecified()) Diag(D.getDeclSpec().getExplicitSpecLoc(), - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_explicit_conversion_functions : diag::ext_explicit_conversion_functions) << SourceRange(D.getDeclSpec().getExplicitSpecLoc()); @@ -5551,11 +6081,11 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, 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; + DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; + ++I) { + if ((*I)->getIdentifierNamespace() & IDNS) { + PrevDecl = *I; break; } } @@ -5978,7 +6508,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S, Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); } - // FIXME: We ignore attributes for now. + if (UDir) + ProcessDeclAttributeList(S, UDir, AttrList); + return UDir; } @@ -6019,14 +6551,12 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, case UnqualifiedId::IK_ConstructorTemplateId: // C++11 inheriting constructors. Diag(Name.getLocStart(), - getLangOpts().CPlusPlus0x ? - // FIXME: Produce warn_cxx98_compat_using_decl_constructor - // instead once inheriting constructors work. - diag::err_using_decl_constructor_unsupported : + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_using_decl_constructor : diag::err_using_decl_constructor) << SS.getRange(); - if (getLangOpts().CPlusPlus0x) break; + if (getLangOpts().CPlusPlus11) break; return 0; @@ -6046,7 +6576,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, if (!TargetName) return 0; - // Warn about using declarations. + // Warn about access declarations. // TODO: store that the declaration was written without 'using' and // talk about access decls instead of using decls in the // diagnostics. @@ -6116,7 +6646,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // 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 (!getLangOpts().CPlusPlus0x && CurContext->isRecord()) { + if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) { DeclContext *OrigDC = Orig->getDeclContext(); // Handle enums and anonymous structs. @@ -6605,7 +7135,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext)) return true; - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { // 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 @@ -6694,6 +7224,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, MultiTemplateParamsArg TemplateParamLists, SourceLocation UsingLoc, UnqualifiedId &Name, + AttributeList *AttrList, TypeResult Type) { // Skip up to the relevant declaration scope. while (S->getFlags() & Scope::TemplateParamScope) @@ -6740,6 +7271,8 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, if (Invalid) NewTD->setInvalidDecl(); + ProcessDeclAttributeList(S, NewTD, AttrList); + CheckTypedefForVariablyModifiedType(S, NewTD); Invalid |= NewTD->isInvalidDecl(); @@ -6969,6 +7502,43 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, return ExceptSpec; } +Sema::ImplicitExceptionSpecification +Sema::ComputeInheritingCtorExceptionSpec(CXXMethodDecl *MD) { + ImplicitExceptionSpecification ExceptSpec(*this); + // FIXME: Compute the exception spec. + return ExceptSpec; +} + +namespace { +/// RAII object to register a special member as being currently declared. +struct DeclaringSpecialMember { + Sema &S; + Sema::SpecialMemberDecl D; + bool WasAlreadyBeingDeclared; + + DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM) + : S(S), D(RD, CSM) { + WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D); + if (WasAlreadyBeingDeclared) + // This almost never happens, but if it does, ensure that our cache + // doesn't contain a stale result. + S.SpecialMemberCache.clear(); + + // FIXME: Register a note to be produced if we encounter an error while + // declaring the special member. + } + ~DeclaringSpecialMember() { + if (!WasAlreadyBeingDeclared) + S.SpecialMembersBeingDeclared.erase(D); + } + + /// \brief Are we already trying to declare this special member? + bool isAlreadyBeingDeclared() const { + return WasAlreadyBeingDeclared; + } +}; +} + CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXRecordDecl *ClassDecl) { // C++ [class.ctor]p5: @@ -6977,9 +7547,13 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( // 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() && + assert(ClassDecl->needsImplicitDefaultConstructor() && "Should not build implicit default constructor!"); + DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; + bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, CXXDefaultConstructor, false); @@ -6998,24 +7572,29 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); DefaultCon->setImplicit(); - DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); // Build an exception specification pointing back at this constructor. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = DefaultCon; - DefaultCon->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + DefaultCon->setType(Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(), + EPI)); + + // We don't need to use SpecialMemberIsTrivial here; triviality for default + // constructors is easy to compute. + DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); + + if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) + SetDeclDeleted(DefaultCon, ClassLoc); // Note that we have declared this constructor. ++ASTContext::NumImplicitDefaultConstructorsDeclared; - + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(DefaultCon, S, false); ClassDecl->addDecl(DefaultCon); - if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) - DefaultCon->setDeletedAsWritten(); - return DefaultCon; } @@ -7031,7 +7610,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, SynthesizedFunctionScope Scope(*this, Constructor); DiagnosticErrorTrap Trap(Diags); - if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) || + if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl); @@ -7051,16 +7630,12 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { - if (!D) return; - AdjustDeclIfTemplate(D); - - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D); - - if (!ClassDecl->isDependentType()) - CheckExplicitlyDefaultedMethods(ClassDecl); + // Check that any explicitly-defaulted methods have exception specifications + // compatible with their implicit exception specifications. + CheckDelayedExplicitlyDefaultedMemberExceptionSpecs(); } -void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { +void Sema::DeclareInheritingConstructors(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. @@ -7075,6 +7650,8 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { // If we inherit constructors from anything that is dependent, just // abort processing altogether. We'll get another chance for the // instantiations. + // FIXME: We need to ensure that any call to a constructor of this class + // is considered instantiation-dependent in this case. return; } BasesToInheritFrom.push_back(Base->castAs<RecordType>()); @@ -7083,18 +7660,19 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { if (BasesToInheritFrom.empty()) return; + // FIXME: Constructor templates. + // 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 [...] + // C++11 [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) { + CtorIt != CtorE; ++CtorIt) ExistingConstructors.insert( Context.getCanonicalType(CtorIt->getType()).getTypePtr()); - } DeclarationName CreatedCtorName = Context.DeclarationNames.getCXXConstructorName( @@ -7126,62 +7704,71 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { 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 + // C++11 [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 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. + // end of the parameter-type-list, and + // FIXME: ...also constructor templates. 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) { + // Determine whether this would be a copy or move constructor for the + // derived class. + if (BaseCtorType->getNumArgs() >= 1 && + BaseCtorType->getArgType(0)->isReferenceType() && + Context.hasSameUnqualifiedType( + BaseCtorType->getArgType(0)->getPointeeType(), + Context.getTagDeclType(ClassDecl))) + CanBeCopyOrMove = true; + + ArrayRef<QualType> ArgTypes(BaseCtorType->getArgTypes()); + FunctionProtoType::ExtProtoInfo EPI = BaseCtorType->getExtProtoInfo(); + // Core issue (no number yet): the ellipsis is always discarded. + if (EPI.Variadic) { + Diag(UsingLoc, diag::warn_using_decl_constructor_ellipsis); + Diag(BaseCtor->getLocation(), + diag::note_using_decl_constructor_ellipsis); + EPI.Variadic = false; + } + + for (unsigned Params = BaseCtor->getMinRequiredArguments(), + MaxParams = BaseCtor->getNumParams(); + Params <= MaxParams; ++Params) { // Skip default constructors. They're never inherited. - if (params == 0) + if (Params == 0) continue; - // Skip copy and move constructors for the same reason. - if (CanBeCopyOrMove && params == 1) + + // Skip copy and move constructors for both base and derived class + // 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 { - 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(); - } + QualType NewCtorType = + Context.getFunctionType(Context.VoidTy, ArgTypes.slice(0, Params), + EPI); const Type *CanonicalNewCtorType = - Context.getCanonicalType(NewCtorType); + Context.getCanonicalType(NewCtorType).getTypePtr(); - // Now that we have the type, first check if the class already has a - // constructor with this signature. + // C++11 [class.inhctor]p3: + // ... a constructor is implicitly declared with the same constructor + // characteristics unless there is a user-declared constructor with + // the same signature in the class where the using-declaration appears if (ExistingConstructors.count(CanonicalNewCtorType)) continue; - // Then we check if we have already declared an inherited constructor - // with this signature. + // C++11 [class.inhctor]p7: + // If two using-declarations declare inheriting constructors with the + // same signature, the program is ill-formed std::pair<ConstructorToSourceMap::iterator, bool> result = InheritedConstructors.insert(std::make_pair( CanonicalNewCtorType, @@ -7203,35 +7790,47 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { diag::note_using_decl_constructor_conflict_previous_ctor); Diag(PrevCtor->getLocation(), diag::note_using_decl_constructor_conflict_previous_using); + } else { + // Core issue (no number): if the same inheriting constructor is + // produced by multiple base class constructors from the same base + // class, the inheriting constructor is defined as deleted. + SetDeclDeleted(result.first->second.second, UsingLoc); } continue; } // OK, we're there, now add the constructor. - // C++0x [class.inhctor]p8: [...] that would be performed by a - // user-written inline constructor [...] DeclarationNameInfo DNI(CreatedCtorName, UsingLoc); CXXConstructorDecl *NewCtor = CXXConstructorDecl::Create( - Context, ClassDecl, UsingLoc, DNI, QualType(NewCtorType, 0), + Context, ClassDecl, UsingLoc, DNI, NewCtorType, /*TInfo=*/0, BaseCtor->isExplicit(), /*Inline=*/true, - /*ImplicitlyDeclared=*/true, - // FIXME: Due to a defect in the standard, we treat inherited - // constructors as constexpr even if that makes them ill-formed. - /*Constexpr=*/BaseCtor->isConstexpr()); + /*ImplicitlyDeclared=*/true, /*Constexpr=*/BaseCtor->isConstexpr()); NewCtor->setAccess(BaseCtor->getAccess()); + // Build an unevaluated exception specification for this constructor. + EPI.ExceptionSpecType = EST_Unevaluated; + EPI.ExceptionSpecDecl = NewCtor; + NewCtor->setType(Context.getFunctionType(Context.VoidTy, + ArgTypes.slice(0, Params), + EPI)); + // Build up the parameter decls and add them. 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)); + for (unsigned i = 0; i < Params; ++i) { + ParmVarDecl *PD = ParmVarDecl::Create(Context, NewCtor, + UsingLoc, UsingLoc, + /*IdentifierInfo=*/0, + BaseCtorType->getArgType(i), + /*TInfo=*/0, SC_None, + /*DefaultArg=*/0); + PD->setScopeInfo(0, i); + PD->setImplicit(); + ParamDecls.push_back(PD); } NewCtor->setParams(ParamDecls); NewCtor->setInheritedConstructor(BaseCtor); + if (BaseCtor->isDeleted()) + SetDeclDeleted(NewCtor, UsingLoc); ClassDecl->addDecl(NewCtor); result.first->second.second = NewCtor; @@ -7240,6 +7839,35 @@ void Sema::DeclareInheritedConstructors(CXXRecordDecl *ClassDecl) { } } +void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor) { + CXXRecordDecl *ClassDecl = Constructor->getParent(); + assert(Constructor->getInheritedConstructor() && + !Constructor->doesThisDeclarationHaveABody() && + !Constructor->isDeleted()); + + SynthesizedFunctionScope Scope(*this, Constructor); + DiagnosticErrorTrap Trap(Diags); + if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_inhctor_synthesized_at) + << Context.getTagDeclType(ClassDecl); + Constructor->setInvalidDecl(); + return; + } + + SourceLocation Loc = Constructor->getLocation(); + Constructor->setBody(new (Context) CompoundStmt(Loc)); + + Constructor->setUsed(); + MarkVTableUsed(CurrentLocation, ClassDecl); + + if (ASTMutationListener *L = getASTMutationListener()) { + L->CompletedImplicitDefinition(Constructor); + } +} + + Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) { CXXRecordDecl *ClassDecl = MD->getParent(); @@ -7290,6 +7918,11 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { // 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. + assert(ClassDecl->needsImplicitDestructor()); + + DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; // Create the actual destructor declaration. CanQualType ClassType @@ -7305,13 +7938,23 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { Destructor->setAccess(AS_public); Destructor->setDefaulted(); Destructor->setImplicit(); - Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); // Build an exception specification pointing back at this destructor. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = Destructor; - Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + Destructor->setType(Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(), + EPI)); + + AddOverriddenMethods(ClassDecl, Destructor); + + // We don't need to use SpecialMemberIsTrivial here; triviality for + // destructors is easy to compute. + Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); + + if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) + SetDeclDeleted(Destructor, ClassLoc); // Note that we have declared this destructor. ++ASTContext::NumImplicitDestructorsDeclared; @@ -7321,11 +7964,6 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { PushOnScopeChains(Destructor, S, false); ClassDecl->addDecl(Destructor); - AddOverriddenMethods(ClassDecl, Destructor); - - if (ShouldDeleteSpecialMember(Destructor, CXXDestructor)) - Destructor->setDeletedAsWritten(); - return Destructor; } @@ -7369,6 +8007,14 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, /// \brief Perform any semantic analysis which needs to be delayed until all /// pending class member declarations have been parsed. void Sema::ActOnFinishCXXMemberDecls() { + // If the context is an invalid C++ class, just suppress these checks. + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) { + if (Record->isInvalidDecl()) { + DelayedDestructorExceptionSpecChecks.clear(); + return; + } + } + // Perform any deferred checking of exception specifications for virtual // destructors. for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size(); @@ -7385,7 +8031,7 @@ void Sema::ActOnFinishCXXMemberDecls() { void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor) { - assert(getLangOpts().CPlusPlus0x && + assert(getLangOpts().CPlusPlus11 && "adjusting dtor exception specs was introduced in c++11"); // C++11 [class.dtor]p3: @@ -7403,7 +8049,9 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo(); EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = Destructor; - Destructor->setType(Context.getFunctionType(Context.VoidTy, 0, 0, EPI)); + Destructor->setType(Context.getFunctionType(Context.VoidTy, + ArrayRef<QualType>(), + EPI)); // 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 @@ -7412,6 +8060,60 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, // needs to be done somewhere else. } +/// When generating a defaulted copy or move assignment operator, if a field +/// should be copied with __builtin_memcpy rather than via explicit assignments, +/// do so. This optimization only applies for arrays of scalars, and for arrays +/// of class type where the selected copy/move-assignment operator is trivial. +static StmtResult +buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From) { + // Compute the size of the memory buffer to be copied. + QualType SizeType = S.Context.getSizeType(); + llvm::APInt Size(S.Context.getTypeSize(SizeType), + S.Context.getTypeSizeInChars(T).getQuantity()); + + // Take the address of the field references for "from" and "to". We + // directly construct UnaryOperators here because semantic analysis + // does not permit us to take the address of an xvalue. + From = new (S.Context) UnaryOperator(From, UO_AddrOf, + S.Context.getPointerType(From->getType()), + VK_RValue, OK_Ordinary, Loc); + To = new (S.Context) UnaryOperator(To, UO_AddrOf, + S.Context.getPointerType(To->getType()), + VK_RValue, OK_Ordinary, Loc); + + const Type *E = T->getBaseElementTypeUnsafe(); + bool NeedsCollectableMemCpy = + E->isRecordType() && E->getAs<RecordType>()->getDecl()->hasObjectMember(); + + // Create a reference to the __builtin_objc_memmove_collectable function + StringRef MemCpyName = NeedsCollectableMemCpy ? + "__builtin_objc_memmove_collectable" : + "__builtin_memcpy"; + LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc, + Sema::LookupOrdinaryName); + S.LookupName(R, S.TUScope, true); + + FunctionDecl *MemCpy = R.getAsSingle<FunctionDecl>(); + if (!MemCpy) + // Something went horribly wrong earlier, and we will have complained + // about it. + return StmtError(); + + ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy, + VK_RValue, Loc, 0); + assert(MemCpyRef.isUsable() && "Builtin reference cannot fail"); + + Expr *CallArgs[] = { + To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc) + }; + ExprResult Call = S.ActOnCallExpr(/*Scope=*/0, MemCpyRef.take(), + Loc, CallArgs, Loc); + + assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); + return S.Owned(Call.takeAs<Stmt>()); +} + /// \brief Builds a statement that copies/moves the given entity from \p From to /// \c To. /// @@ -7437,13 +8139,14 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, /// /// \param Depth Internal parameter recording the depth of the recursion. /// -/// \returns A statement or a loop that copies the expressions. +/// \returns A statement or a loop that copies the expressions, or StmtResult(0) +/// if a memcpy should be used instead. static StmtResult -BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, - Expr *To, Expr *From, - bool CopyingBaseSubobject, bool Copying, - unsigned Depth = 0) { - // C++0x [class.copy]p28: +buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From, + bool CopyingBaseSubobject, bool Copying, + unsigned Depth = 0) { + // C++11 [class.copy]p28: // Each subobject is assigned in the manner appropriate to its type: // // - if the subobject is of class type, as if by a call to operator= with @@ -7451,32 +8154,41 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // subobject of x as a single function argument (as if by explicit // qualification; that is, ignoring any possible virtual overriding // functions in more derived classes); + // + // C++03 [class.copy]p13: + // - 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/move-assignment operator. - LookupResult::Filter F = OpLookup.makeFilter(); - while (F.hasNext()) { - NamedDecl *D = F.next(); - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) - if (Method->isCopyAssignmentOperator() || - (!Copying && Method->isMoveAssignmentOperator())) - continue; - F.erase(); + // Prior to C++11, filter out any result that isn't a copy/move-assignment + // operator. + if (!S.getLangOpts().CPlusPlus11) { + LookupResult::Filter F = OpLookup.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) + if (Method->isCopyAssignmentOperator() || + (!Copying && Method->isMoveAssignmentOperator())) + continue; + + F.erase(); + } + F.done(); } - F.done(); - + // Suppress the protected check (C++ [class.protected]) for each of the - // assignment operators we found. This strange dance is required when + // 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 + // 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, @@ -7491,20 +8203,20 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, 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; const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); - SS.MakeTrivial(S.Context, - NestedNameSpecifier::Create(S.Context, 0, false, + SS.MakeTrivial(S.Context, + NestedNameSpecifier::Create(S.Context, 0, false, CanonicalT), Loc); - + // Create the reference to operator=. ExprResult OpEqualRef - = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, + = S.BuildMemberReferenceExpr(To, T, Loc, /*isArrow=*/false, SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/0, OpLookup, @@ -7512,39 +8224,46 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) return StmtError(); - + // Build the call to the assignment operator. - ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/0, + 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 we built a call to a trivial 'operator=' while copying an array, + // bail out. We'll replace the whole shebang with a memcpy. + CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get()); + if (CE && CE->getMethodDecl()->isTrivial() && Depth) + return StmtResult((Stmt*)0); + + // Convert to an expression-statement, and clean up any produced + // temporaries. + return S.ActOnExprStmt(Call); } - // - if the subobject is of scalar type, the built-in assignment + // - if the subobject is of scalar type, the built-in assignment // operator is used. - const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); + 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>()); + return S.ActOnExprStmt(Assignment); } - - // - if the subobject is an array, each element is assigned, in the + + // - 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; { @@ -7556,8 +8275,8 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, S.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None, 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)); @@ -7572,7 +8291,26 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Create the DeclStmt that holds the iteration variable. Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); - + + // Subscript the "from" and "to" expressions with the iteration variable. + From = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(From, Loc, + IterationVarRefRVal, + Loc)); + To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, + IterationVarRefRVal, + Loc)); + if (!Copying) // Cast to rvalue + From = CastForMoving(S, From); + + // Build the copy/move for an individual element of the array. + StmtResult Copy = + buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(), + To, From, CopyingBaseSubobject, + Copying, Depth + 1); + // Bail out if copying fails or if we determined that we should use memcpy. + if (Copy.isInvalid() || !Copy.get()) + return Copy; + // Create the comparison against the array bound. llvm::APInt Upper = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); @@ -7581,104 +8319,38 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, VK_RValue, OK_Ordinary, Loc, false); - + // 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, - IterationVarRefRVal, - Loc)); - To = AssertSuccess(S.CreateBuiltinArraySubscriptExpr(To, Loc, - IterationVarRefRVal, - Loc)); - if (!Copying) // Cast to rvalue - From = CastForMoving(S, From); - // Build the copy/move for an individual element of the array. - StmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(), - To, From, CopyingBaseSubobject, - Copying, 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), + 0, S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.take()); } -/// Determine whether an implicit copy assignment operator for ClassDecl has a -/// const argument. -/// FIXME: It ought to be possible to store this on the record. -static bool isImplicitCopyAssignmentArgConst(Sema &S, - CXXRecordDecl *ClassDecl) { - if (ClassDecl->isInvalidDecl()) - return true; +static StmtResult +buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, + Expr *To, Expr *From, + bool CopyingBaseSubobject, bool Copying) { + // Maybe we should use a memcpy? + if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() && + T.isTriviallyCopyableType(S.Context)) + return buildMemcpyForAssignmentOp(S, Loc, T, To, From); - // 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 - // -- 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(); - Base != BaseEnd; ++Base) { - // We'll handle this below - if (S.getLangOpts().CPlusPlus0x && Base->isVirtual()) - continue; + StmtResult Result(buildSingleCopyAssignRecursively(S, Loc, T, To, From, + CopyingBaseSubobject, + Copying, 0)); - assert(!Base->getType()->isDependentType() && - "Cannot generate implicit members for class with dependent bases."); - CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); - if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, false, 0)) - return false; - } + // If we ended up picking a trivial assignment operator for an array of a + // non-trivially-copyable class type, just emit a memcpy. + if (!Result.isInvalid() && !Result.get()) + return buildMemcpyForAssignmentOp(S, Loc, T, To, From); - // In C++11, the above citation has "or virtual" added - if (S.getLangOpts().CPlusPlus0x) { - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), - BaseEnd = ClassDecl->vbases_end(); - Base != BaseEnd; ++Base) { - assert(!Base->getType()->isDependentType() && - "Cannot generate implicit members for class with dependent bases."); - CXXRecordDecl *BaseClassDecl = Base->getType()->getAsCXXRecordDecl(); - if (!S.LookupCopyingAssignment(BaseClassDecl, Qualifiers::Const, - false, 0)) - return false; - } - } - - // -- 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(); - Field != FieldEnd; ++Field) { - QualType FieldType = S.Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) - if (!S.LookupCopyingAssignment(FieldClassDecl, Qualifiers::Const, - false, 0)) - return false; - } - - // Otherwise, the implicitly declared copy assignment operator will - // have the form - // - // X& X::operator=(X&) - - return true; + return Result; } Sema::ImplicitExceptionSpecification @@ -7748,10 +8420,15 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { // 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. + assert(ClassDecl->needsImplicitCopyAssignment()); + + DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment); + if (DSM.isAlreadyBeingDeclared()) + return 0; QualType ArgType = Context.getTypeDeclType(ClassDecl); QualType RetType = Context.getLValueReferenceType(ArgType); - if (isImplicitCopyAssignmentArgConst(*this, ClassDecl)) + if (ClassDecl->implicitCopyAssignmentHasConstParam()) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); @@ -7762,45 +8439,49 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, /*isStatic=*/false, - /*StorageClassAsWritten=*/SC_None, + /*TInfo=*/0, + /*StorageClass=*/SC_None, /*isInline=*/true, /*isConstexpr=*/false, SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setDefaulted(); CopyAssignment->setImplicit(); - CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = CopyAssignment; - CopyAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1, EPI)); + CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // 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); - - // Note that we have added this copy-assignment operator. - ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; - if (Scope *S = getScopeForContext(ClassDecl)) - PushOnScopeChains(CopyAssignment, S, false); - ClassDecl->addDecl(CopyAssignment); - + AddOverriddenMethods(ClassDecl, CopyAssignment); + + CopyAssignment->setTrivial( + ClassDecl->needsOverloadResolutionForCopyAssignment() + ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) + : ClassDecl->hasTrivialCopyAssignment()); + // C++0x [class.copy]p19: // .... If the class definition does not explicitly declare a copy // assignment operator, there is no user-declared move constructor, and // there is no user-declared move assignment operator, a copy assignment // operator is implicitly declared as defaulted. if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) - CopyAssignment->setDeletedAsWritten(); + SetDeclDeleted(CopyAssignment, ClassLoc); + + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyAssignment, S, false); + ClassDecl->addDecl(CopyAssignment); - AddOverriddenMethods(ClassDecl, CopyAssignment); return CopyAssignment; } @@ -7892,7 +8573,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, VK_LValue, &BasePath); // Build the copy. - StmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, + StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType, To.get(), From, /*CopyingBaseSubobject=*/true, /*Copying=*/true); @@ -7907,11 +8588,6 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, 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(); @@ -7969,99 +8645,9 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, 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() && !FieldType.isVolatileQualified() - && BaseType.hasTrivialAssignment(Context, /*Copying=*/true)) { - // 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, - Context.BuiltinFnTy, - VK_RValue, 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, - Context.BuiltinFnTy, - VK_RValue, Loc, 0).take(); - assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); - } - - SmallVector<Expr*, 8> CallArgs; - 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, CallArgs, - Loc); - else - Call = ActOnCallExpr(/*Scope=*/0, - BuiltinMemCpyRef, - Loc, 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, + StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType, To.get(), From.get(), /*CopyingBaseSubobject=*/false, /*Copying=*/true); @@ -8188,10 +8774,7 @@ hasVirtualBaseWithNonTrivialMoveAssignment(Sema &S, CXXRecordDecl *ClassDecl) { if (BaseClass->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(BaseClass); - // If the class has both a trivial move assignment and a non-trivial move - // assignment, hasTrivialMoveAssignment() is false. - if (BaseClass->hasDeclaredMoveAssignment() && - !BaseClass->hasTrivialMoveAssignment()) + if (BaseClass->hasNonTrivialMoveAssignment()) return true; } @@ -8215,14 +8798,18 @@ hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) { return true; if (IsConstructor) { + // FIXME: Need this because otherwise hasMoveConstructor isn't guaranteed to + // give the right answer. if (ClassDecl->needsImplicitMoveConstructor()) S.DeclareImplicitMoveConstructor(ClassDecl); - return ClassDecl->hasDeclaredMoveConstructor(); + return ClassDecl->hasMoveConstructor(); } + // FIXME: Need this because otherwise hasMoveAssignment isn't guaranteed to + // give the right answer. if (ClassDecl->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(ClassDecl); - return ClassDecl->hasDeclaredMoveAssignment(); + return ClassDecl->hasMoveAssignment(); } /// Determine whether all non-static data members and direct or virtual bases @@ -8266,6 +8853,10 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { // - [first 4 bullets] assert(ClassDecl->needsImplicitMoveAssignment()); + DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment); + if (DSM.isAlreadyBeingDeclared()) + return 0; + // [Checked after we build the declaration] // - the move assignment operator would not be implicitly defined as // deleted, @@ -8296,32 +8887,34 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { DeclarationNameInfo NameInfo(Name, ClassLoc); CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/0, /*isStatic=*/false, - /*StorageClassAsWritten=*/SC_None, + /*TInfo=*/0, + /*StorageClass=*/SC_None, /*isInline=*/true, /*isConstexpr=*/false, SourceLocation()); MoveAssignment->setAccess(AS_public); MoveAssignment->setDefaulted(); MoveAssignment->setImplicit(); - MoveAssignment->setTrivial(ClassDecl->hasTrivialMoveAssignment()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = MoveAssignment; - MoveAssignment->setType(Context.getFunctionType(RetType, &ArgType, 1, EPI)); + MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); // Add the parameter to the operator. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, ClassLoc, ClassLoc, /*Id=*/0, ArgType, /*TInfo=*/0, - SC_None, SC_None, 0); MoveAssignment->setParams(FromParam); - // Note that we have added this copy-assignment operator. - ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; + AddOverriddenMethods(ClassDecl, MoveAssignment); + + MoveAssignment->setTrivial( + ClassDecl->needsOverloadResolutionForMoveAssignment() + ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) + : ClassDecl->hasTrivialMoveAssignment()); // C++0x [class.copy]p9: // If the definition of a class X does not explicitly declare a move @@ -8337,11 +8930,13 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { return 0; } + // Note that we have added this copy-assignment operator. + ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; + if (Scope *S = getScopeForContext(ClassDecl)) PushOnScopeChains(MoveAssignment, S, false); ClassDecl->addDecl(MoveAssignment); - AddOverriddenMethods(ClassDecl, MoveAssignment); return MoveAssignment; } @@ -8431,7 +9026,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, VK_LValue, &BasePath); // Build the move. - StmtResult Move = BuildSingleCopyAssign(*this, Loc, BaseType, + StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType, To.get(), From, /*CopyingBaseSubobject=*/true, /*Copying=*/false); @@ -8446,11 +9041,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, Statements.push_back(Move.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(); @@ -8513,104 +9103,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, "Member reference with rvalue base must be rvalue except for reference " "members, which aren't allowed for move assignment."); - // 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 move-assignment - // operators. - if (FieldType->isArrayType() && !FieldType.isVolatileQualified() - && BaseType.hasTrivialAssignment(Context, /*Copying=*/false)) { - // 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". We - // directly construct UnaryOperators here because semantic analysis - // does not permit us to take the address of an xvalue. - From = new (Context) UnaryOperator(From.get(), UO_AddrOf, - Context.getPointerType(From.get()->getType()), - VK_RValue, OK_Ordinary, Loc); - To = new (Context) UnaryOperator(To.get(), UO_AddrOf, - Context.getPointerType(To.get()->getType()), - VK_RValue, OK_Ordinary, Loc); - - 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, - Context.BuiltinFnTy, - VK_RValue, 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, - Context.BuiltinFnTy, - VK_RValue, Loc, 0).take(); - assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); - } - - SmallVector<Expr*, 8> CallArgs; - 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, CallArgs, - Loc); - else - Call = ActOnCallExpr(/*Scope=*/0, - BuiltinMemCpyRef, - Loc, CallArgs, - Loc); - - assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); - Statements.push_back(Call.takeAs<Expr>()); - continue; - } - // Build the move of this field. - StmtResult Move = BuildSingleCopyAssign(*this, Loc, FieldType, + StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType, To.get(), From.get(), /*CopyingBaseSubobject=*/false, /*Copying=*/false); @@ -8620,7 +9114,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MoveAssignOperator->setInvalidDecl(); return; } - + // Success! Record the copy. Statements.push_back(Move.takeAs<Stmt>()); } @@ -8662,70 +9156,6 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } } -/// Determine whether an implicit copy constructor for ClassDecl has a const -/// argument. -/// FIXME: It ought to be possible to store this on the record. -static bool isImplicitCopyCtorArgConst(Sema &S, CXXRecordDecl *ClassDecl) { - if (ClassDecl->isInvalidDecl()) - return true; - - // C++ [class.copy]p5: - // The implicitly-declared copy constructor for a class X will - // have the form - // - // X::X(const X&) - // - // if - // -- 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(); - Base != BaseEnd; ++Base) { - // Virtual bases are handled below. - if (Base->isVirtual()) - continue; - - CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - // FIXME: This lookup is wrong. If the copy ctor for a member or base is - // ambiguous, we should still produce a constructor with a const-qualified - // parameter. - if (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const)) - return false; - } - - 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 (!S.LookupCopyingConstructor(BaseClassDecl, Qualifiers::Const)) - return false; - } - - // -- 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(); - Field != FieldEnd; ++Field) { - QualType FieldType = S.Context.getBaseElementType(Field->getType()); - if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) { - if (!S.LookupCopyingConstructor(FieldClassDecl, Qualifiers::Const)) - return false; - } - } - - // Otherwise, the implicitly declared copy constructor will have - // the form - // - // X::X(X&) - - return true; -} - Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) { CXXRecordDecl *ClassDecl = MD->getParent(); @@ -8786,10 +9216,15 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // C++ [class.copy]p4: // If the class definition does not explicitly declare a copy // constructor, one is declared implicitly. + assert(ClassDecl->needsImplicitCopyConstructor()); + + DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; QualType ClassType = Context.getTypeDeclType(ClassDecl); QualType ArgType = ClassType; - bool Const = isImplicitCopyCtorArgConst(*this, ClassDecl); + bool Const = ClassDecl->implicitCopyConstructorHasConstParam(); if (Const) ArgType = ArgType.withConst(); ArgType = Context.getLValueReferenceType(ArgType); @@ -8812,30 +9247,26 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( Constexpr); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); - CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = CopyConstructor; CopyConstructor->setType( - Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + Context.getFunctionType(Context.VoidTy, ArgType, EPI)); - // 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); - if (Scope *S = getScopeForContext(ClassDecl)) - PushOnScopeChains(CopyConstructor, S, false); - ClassDecl->addDecl(CopyConstructor); + CopyConstructor->setTrivial( + ClassDecl->needsOverloadResolutionForCopyConstructor() + ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) + : ClassDecl->hasTrivialCopyConstructor()); // C++11 [class.copy]p8: // ... If the class definition does not explicitly declare a copy @@ -8843,7 +9274,14 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( // user-declared move assignment operator, a copy constructor is implicitly // declared as defaulted. if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) - CopyConstructor->setDeletedAsWritten(); + SetDeclDeleted(CopyConstructor, ClassLoc); + + // Note that we have declared this constructor. + ++ASTContext::NumImplicitCopyConstructorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyConstructor, S, false); + ClassDecl->addDecl(CopyConstructor); return CopyConstructor; } @@ -8862,7 +9300,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, SynthesizedFunctionScope Scope(*this, CopyConstructor); DiagnosticErrorTrap Trap(Diags); - if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) || + if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXCopyConstructor << Context.getTagDeclType(ClassDecl); @@ -8957,6 +9395,10 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( // - [first 4 bullets] assert(ClassDecl->needsImplicitMoveConstructor()); + DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor); + if (DSM.isAlreadyBeingDeclared()) + return 0; + // [Checked after we build the declaration] // - the move assignment operator would not be implicitly defined as // deleted, @@ -8991,24 +9433,27 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( Constexpr); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); - MoveConstructor->setTrivial(ClassDecl->hasTrivialMoveConstructor()); // Build an exception specification pointing back at this member. FunctionProtoType::ExtProtoInfo EPI; EPI.ExceptionSpecType = EST_Unevaluated; EPI.ExceptionSpecDecl = MoveConstructor; MoveConstructor->setType( - Context.getFunctionType(Context.VoidTy, &ArgType, 1, EPI)); + Context.getFunctionType(Context.VoidTy, ArgType, EPI)); // Add the parameter to the constructor. ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, ClassLoc, ClassLoc, /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, - SC_None, SC_None, 0); MoveConstructor->setParams(FromParam); + MoveConstructor->setTrivial( + ClassDecl->needsOverloadResolutionForMoveConstructor() + ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) + : ClassDecl->hasTrivialMoveConstructor()); + // C++0x [class.copy]p9: // If the definition of a class X does not explicitly declare a move // constructor, one will be implicitly declared as defaulted if and only if: @@ -9045,7 +9490,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, SynthesizedFunctionScope Scope(*this, MoveConstructor); DiagnosticErrorTrap Trap(Diags); - if (SetCtorInitializers(MoveConstructor, 0, 0, /*AnyErrors=*/false) || + if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXMoveConstructor << Context.getTagDeclType(ClassDecl); @@ -9077,8 +9522,8 @@ bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { CXXMethodDecl *CallOperator = cast<CXXMethodDecl>( - *Lambda->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + Lambda->lookup( + S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); CallOperator->setUsed(); } @@ -9100,12 +9545,12 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( // Return the address of the __invoke function. DeclarationName InvokeName = &Context.Idents.get("__invoke"); CXXMethodDecl *Invoke - = cast<CXXMethodDecl>(*Lambda->lookup(InvokeName).first); + = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front()); Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(), VK_LValue, Conv->getLocation()).take(); assert(FunctionRef && "Can't refer to __invoke function?"); Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take(); - Conv->setBody(new (Context) CompoundStmt(Context, &Return, 1, + Conv->setBody(new (Context) CompoundStmt(Context, Return, Conv->getLocation(), Conv->getLocation())); @@ -9164,7 +9609,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( // Set the body of the conversion function. Stmt *ReturnS = Return.take(); - Conv->setBody(new (Context) CompoundStmt(Context, &ReturnS, 1, + Conv->setBody(new (Context) CompoundStmt(Context, ReturnS, Conv->getLocation(), Conv->getLocation())); @@ -9198,6 +9643,7 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, bool HadMultipleCandidates, + bool IsListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { @@ -9221,7 +9667,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs, HadMultipleCandidates, - RequiresZeroInit, ConstructKind, ParenRange); + IsListInitialization, RequiresZeroInit, + ConstructKind, ParenRange); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -9231,39 +9678,19 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, bool HadMultipleCandidates, + bool IsListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { MarkFunctionReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, - HadMultipleCandidates, /*FIXME*/false, - RequiresZeroInit, + HadMultipleCandidates, + IsListInitialization, RequiresZeroInit, static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), ParenRange)); } -bool Sema::InitializeVarWithConstructor(VarDecl *VD, - CXXConstructorDecl *Constructor, - MultiExprArg Exprs, - bool HadMultipleCandidates) { - // FIXME: Provide the correct paren SourceRange when available. - ExprResult TempResult = - BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, - Exprs, HadMultipleCandidates, false, - CXXConstructExpr::CK_Complete, SourceRange()); - if (TempResult.isInvalid()) - return true; - - Expr *Temp = TempResult.takeAs<Expr>(); - CheckImplicitConversions(Temp, VD->getLocation()); - MarkFunctionReferenced(VD->getLocation(), Constructor); - Temp = MaybeCreateExprWithCleanups(Temp); - VD->setInit(Temp); - - return false; -} - void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { if (VD->isInvalidDecl()) return; @@ -9301,7 +9728,8 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, SmallVectorImpl<Expr*> &ConvertedArgs, - bool AllowExplicit) { + bool AllowExplicit, + bool IsListInitialization) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); Expr **Args = ArgsPtr.data(); @@ -9322,12 +9750,15 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, SmallVector<Expr *, 8> AllArgs; bool Invalid = GatherArgumentsForCall(Loc, Constructor, Proto, 0, Args, NumArgs, AllArgs, - CallType, AllowExplicit); + CallType, AllowExplicit, + IsListInitialization); ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); DiagnoseSentinelCalls(Constructor, Loc, AllArgs.data(), AllArgs.size()); - CheckConstructorCall(Constructor, AllArgs.data(), AllArgs.size(), + CheckConstructorCall(Constructor, + llvm::makeArrayRef<const Expr *>(AllArgs.data(), + AllArgs.size()), Proto, Loc); return Invalid; @@ -9766,6 +10197,19 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, return LinkageSpec; } +Decl *Sema::ActOnEmptyDeclaration(Scope *S, + AttributeList *AttrList, + SourceLocation SemiLoc) { + Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); + // Attribute declarations appertain to empty declaration so we handle + // them here. + if (AttrList) + ProcessDeclAttributeList(S, ED, AttrList); + + CurContext->addDecl(ED); + return ED; +} + /// \brief Perform semantic analysis for the variable declaration that /// occurs within a C++ catch clause, returning the newly-created /// variable. @@ -9833,7 +10277,7 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, } VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, - ExDeclType, TInfo, SC_None, SC_None); + ExDeclType, TInfo, SC_None); ExDecl->setExceptionVariable(true); // In ARC, infer 'retaining' for variables of retainable type. @@ -9842,6 +10286,9 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, if (!Invalid && !ExDeclType->isDependentType()) { if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) { + // Insulate this from anything else we might currently be parsing. + EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated); + // 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 @@ -9893,8 +10340,8 @@ Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { bool Invalid = D.isInvalidType(); // Check for unexpanded parameter packs. - if (TInfo && DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, - UPPC_ExceptionType)) { + if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, + UPPC_ExceptionType)) { TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, D.getIdentifierLoc()); Invalid = true; @@ -9970,7 +10417,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, Failed = true; if (!Failed && !Cond) { - llvm::SmallString<256> MsgBuffer; + SmallString<256> MsgBuffer; llvm::raw_svector_ostream Msg(MsgBuffer); AssertMessage->printPretty(Msg, 0, getPrintingPolicy()); Diag(StaticAssertLoc, diag::err_static_assert_failed) @@ -10007,47 +10454,49 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, // 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(); + } 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(); + std::string InsertionText = std::string(" ") + RD->getKindName(); - Diag(TypeRange.getBegin(), - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_unelaborated_friend_type : - diag::ext_unelaborated_friend_type) - << (unsigned) RD->getTagKind() - << T - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), - InsertionText); - } else { + Diag(TypeRange.getBegin(), + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_unelaborated_friend_type : + diag::ext_unelaborated_friend_type) + << (unsigned) RD->getTagKind() + << T + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + InsertionText); + } else { + Diag(FriendLoc, + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_nonclass_type_friend : + diag::ext_nonclass_type_friend) + << T + << TypeRange; + } + } else if (T->getAs<EnumType>()) { Diag(FriendLoc, - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_nonclass_type_friend : - diag::ext_nonclass_type_friend) + getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_enum_friend : + diag::ext_enum_friend) << T << TypeRange; } - } else if (T->getAs<EnumType>()) { - Diag(FriendLoc, - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_enum_friend : - diag::ext_enum_friend) - << T - << TypeRange; - } - // C++11 [class.friend]p3: - // A friend declaration that does not declare a function shall have one - // of the following forms: - // friend elaborated-type-specifier ; - // friend simple-type-specifier ; - // friend typename-specifier ; - if (getLangOpts().CPlusPlus0x && LocStart != FriendLoc) - Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T; + // C++11 [class.friend]p3: + // A friend declaration that does not declare a function shall have one + // of the following forms: + // friend elaborated-type-specifier ; + // friend simple-type-specifier ; + // friend typename-specifier ; + if (getLangOpts().CPlusPlus11 && LocStart != FriendLoc) + Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T; + } // If the type specifier in a friend declaration designates a (possibly // cv-qualified) class type, that class is declared as a friend; otherwise, @@ -10060,7 +10509,8 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, + IdentifierInfo *Name, + SourceLocation NameLoc, AttributeList *Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -10132,19 +10582,20 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa<DependentNameType>(T)) { - DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + DependentNameTypeLoc TL = + TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(NameLoc); } else { - ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); + ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(QualifierLoc); - cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(NameLoc); + TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc); } FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, - TSI, FriendLoc); + TSI, FriendLoc, TempParamLists); Friend->setAccess(AS_public); CurContext->addDecl(Friend); return Friend; @@ -10160,13 +10611,13 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); TL.setElaboratedKeywordLoc(TagLoc); TL.setQualifierLoc(SS.getWithLocInContext(Context)); TL.setNameLoc(NameLoc); FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, - TSI, FriendLoc); + TSI, FriendLoc, TempParamLists); Friend->setAccess(AS_public); Friend->setUnsupportedFriend(true); CurContext->addDecl(Friend); @@ -10260,8 +10711,8 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, return D; } -Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, - MultiTemplateParamsArg TemplateParams) { +NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParams) { const DeclSpec &DS = D.getDeclSpec(); assert(DS.isFriendSpecified()); @@ -10372,17 +10823,6 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, 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++11 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)) - Diag(DS.getFriendSpecLoc(), - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_friend_is_member : - diag::err_friend_is_member); - DCScope = getScopeForDeclContext(S, DC); // C++ [class.friend]p6: @@ -10427,7 +10867,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, // class that is not a member of the class . . . if (DC->Equals(CurContext)) Diag(DS.getFriendSpecLoc(), - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_friend_is_member : diag::err_friend_is_member); @@ -10534,11 +10974,12 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { AdjustDeclIfTemplate(Dcl); - FunctionDecl *Fn = dyn_cast<FunctionDecl>(Dcl); + FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Dcl); if (!Fn) { Diag(DelLoc, diag::err_deleted_non_function); return; } + if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { // Don't consider the implicit declaration we generate for explicit // specializations. FIXME: Do not generate these implicit declarations. @@ -10549,41 +10990,34 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { } // If the declaration wasn't the first, we delete the function anyway for // recovery. + Fn = Fn->getCanonicalDecl(); } - Fn->setDeletedAsWritten(); - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); - if (!MD) + if (Fn->isDeleted()) return; - // A deleted special member function is trivial if the corresponding - // implicitly-declared function would have been. - switch (getSpecialMember(MD)) { - case CXXInvalid: - break; - case CXXDefaultConstructor: - MD->setTrivial(MD->getParent()->hasTrivialDefaultConstructor()); - break; - case CXXCopyConstructor: - MD->setTrivial(MD->getParent()->hasTrivialCopyConstructor()); - break; - case CXXMoveConstructor: - MD->setTrivial(MD->getParent()->hasTrivialMoveConstructor()); - break; - case CXXCopyAssignment: - MD->setTrivial(MD->getParent()->hasTrivialCopyAssignment()); - break; - case CXXMoveAssignment: - MD->setTrivial(MD->getParent()->hasTrivialMoveAssignment()); - break; - case CXXDestructor: - MD->setTrivial(MD->getParent()->hasTrivialDestructor()); - break; + // See if we're deleting a function which is already known to override a + // non-deleted virtual function. + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) { + bool IssuedDiagnostic = false; + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) { + if (!(*MD->begin_overridden_methods())->isDeleted()) { + if (!IssuedDiagnostic) { + Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName(); + IssuedDiagnostic = true; + } + Diag((*I)->getLocation(), diag::note_overridden_virtual_function); + } + } } + + Fn->setDeletedAsWritten(); } void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Dcl); + CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Dcl); if (MD) { if (MD->getParent()->isDependentType()) { @@ -10609,11 +11043,19 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { // on it. Pattern->isDefined(Primary); + // If the method was defaulted on its first declaration, we will have + // already performed the checking in CheckCompletedCXXClass. Such a + // declaration doesn't trigger an implicit definition. if (Primary == Primary->getCanonicalDecl()) return; CheckExplicitlyDefaultedSpecialMember(MD); + // The exception specification is needed because we are defining the + // function. + ResolveExceptionSpec(DefaultLoc, + MD->getType()->castAs<FunctionProtoType>()); + switch (Member) { case CXXDefaultConstructor: { CXXConstructorDecl *CD = cast<CXXConstructorDecl>(MD); @@ -10683,6 +11125,40 @@ void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { } } +bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, + const CXXMethodDecl *Old) { + const FunctionType *NewFT = New->getType()->getAs<FunctionType>(); + const FunctionType *OldFT = Old->getType()->getAs<FunctionType>(); + + CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); + + // If the calling conventions match, everything is fine + if (NewCC == OldCC) + return false; + + // If either of the calling conventions are set to "default", we need to pick + // something more sensible based on the target. This supports code where the + // one method explicitly sets thiscall, and another has no explicit calling + // convention. + CallingConv Default = + Context.getTargetInfo().getDefaultCallingConv(TargetInfo::CCMT_Member); + if (NewCC == CC_Default) + NewCC = Default; + if (OldCC == CC_Default) + OldCC = Default; + + // If the calling conventions still don't match, then report the error + if (NewCC != OldCC) { + Diag(New->getLocation(), + diag::err_conflicting_overriding_cc_attributes) + << New->getDeclName() << New->getType() << Old->getType(); + Diag(Old->getLocation(), diag::note_overridden_virtual_function); + return true; + } + + return false; +} + bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, const CXXMethodDecl *Old) { QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType(); @@ -10949,7 +11425,7 @@ bool Sema::DefineUsedVTables() { // 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); + const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class); if (KeyFunction && !KeyFunction->hasBody()) { switch (KeyFunction->getTemplateSpecializationKind()) { case TSK_Undeclared: @@ -11006,7 +11482,7 @@ bool Sema::DefineUsedVTables() { Consumer.HandleVTable(Class, VTablesUsed[Canonical]); // Optionally warn if we're emitting a weak vtable. - if (Class->getLinkage() == ExternalLinkage && + if (Class->hasExternalLinkage() && Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { const FunctionDecl *KeyFunctionDef = 0; if (!KeyFunction || @@ -11228,7 +11704,7 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { return false; TypeLoc TL = TSInfo->getTypeLoc(); - FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL); + FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>(); if (!ProtoTL) return false; @@ -11239,12 +11715,12 @@ bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { // within a static member function as they are within a non-static member // function). [ Note: this is because declaration matching does not occur // until the complete declarator is known. - end note ] - const FunctionProtoType *Proto = ProtoTL->getTypePtr(); + const FunctionProtoType *Proto = ProtoTL.getTypePtr(); FindCXXThisExpr Finder(*this); // If the return type came after the cv-qualifier-seq, check it now. if (Proto->hasTrailingReturn() && - !Finder.TraverseTypeLoc(ProtoTL->getResultLoc())) + !Finder.TraverseTypeLoc(ProtoTL.getResultLoc())) return true; // Check the exception specification. @@ -11260,11 +11736,11 @@ bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { return false; TypeLoc TL = TSInfo->getTypeLoc(); - FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL); + FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>(); if (!ProtoTL) return false; - const FunctionProtoType *Proto = ProtoTL->getTypePtr(); + const FunctionProtoType *Proto = ProtoTL.getTypePtr(); FindCXXThisExpr Finder(*this); switch (Proto->getExceptionSpecType()) { @@ -11354,7 +11830,7 @@ Sema::checkExceptionSpecification(ExceptionSpecificationType EST, ArrayRef<ParsedType> DynamicExceptions, ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr, - llvm::SmallVectorImpl<QualType> &Exceptions, + SmallVectorImpl<QualType> &Exceptions, FunctionProtoType::ExtProtoInfo &EPI) { Exceptions.clear(); EPI.ExceptionSpecType = EST; diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index c4e91e8..5c26d7f 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -12,19 +12,19 @@ //===----------------------------------------------------------------------===// #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/ASTConsumer.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/ASTMutationListener.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" #include "clang/Basic/SourceManager.h" -#include "clang/Sema/DeclSpec.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/DenseSet.h" using namespace clang; @@ -109,8 +109,7 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method, } void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, - const ObjCMethodDecl *Overridden, - bool IsImplementation) { + const ObjCMethodDecl *Overridden) { if (Overridden->hasRelatedResultType() && !NewMethod->hasRelatedResultType()) { // This can only happen when the method follows a naming convention that @@ -152,7 +151,8 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, if (ObjCMethodFamily Family = Overridden->getMethodFamily()) Diag(Overridden->getLocation(), - diag::note_related_result_type_overridden_family) + diag::note_related_result_type_family) + << /*overridden method*/ 0 << Family; else Diag(Overridden->getLocation(), @@ -193,7 +193,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, /// \brief Check a method declaration for compatibility with the Objective-C /// ARC conventions. -static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) { +bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) { ObjCMethodFamily family = method->getMethodFamily(); switch (family) { case OMF_None: @@ -207,17 +207,17 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) { return false; case OMF_dealloc: - if (!S.Context.hasSameType(method->getResultType(), S.Context.VoidTy)) { + if (!Context.hasSameType(method->getResultType(), Context.VoidTy)) { SourceRange ResultTypeRange; if (const TypeSourceInfo *ResultTypeInfo = method->getResultTypeSourceInfo()) ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange(); if (ResultTypeRange.isInvalid()) - S.Diag(method->getLocation(), diag::error_dealloc_bad_result_type) + Diag(method->getLocation(), diag::error_dealloc_bad_result_type) << method->getResultType() << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)"); else - S.Diag(method->getLocation(), diag::error_dealloc_bad_result_type) + Diag(method->getLocation(), diag::error_dealloc_bad_result_type) << method->getResultType() << FixItHint::CreateReplacement(ResultTypeRange, "void"); return true; @@ -226,11 +226,11 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) { case OMF_init: // If the method doesn't obey the init rules, don't bother annotating it. - if (S.checkInitMethod(method, QualType())) + if (checkInitMethod(method, QualType())) return true; - method->addAttr(new (S.Context) NSConsumesSelfAttr(SourceLocation(), - S.Context)); + method->addAttr(new (Context) NSConsumesSelfAttr(SourceLocation(), + Context)); // Don't add a second copy of this attribute, but otherwise don't // let it be suppressed. @@ -249,8 +249,8 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) { break; } - method->addAttr(new (S.Context) NSReturnsRetainedAttr(SourceLocation(), - S.Context)); + method->addAttr(new (Context) NSReturnsRetainedAttr(SourceLocation(), + Context)); return false; } @@ -373,16 +373,29 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { ObjCMethodDecl *IMD = IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()); - if (IMD) - DiagnoseObjCImplementedDeprecations(*this, + if (IMD) { + ObjCImplDecl *ImplDeclOfMethodDef = + dyn_cast<ObjCImplDecl>(MDecl->getDeclContext()); + ObjCContainerDecl *ContDeclOfMethodDecl = + dyn_cast<ObjCContainerDecl>(IMD->getDeclContext()); + ObjCImplDecl *ImplDeclOfMethodDecl = 0; + if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl)) + ImplDeclOfMethodDecl = OID->getImplementation(); + else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) + ImplDeclOfMethodDecl = CD->getImplementation(); + // No need to issue deprecated warning if deprecated mehod in class/category + // is being implemented in its own implementation (no overriding is involved). + if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef) + DiagnoseObjCImplementedDeprecations(*this, dyn_cast<NamedDecl>(IMD), MDecl->getLocation(), 0); + } // If this is "dealloc" or "finalize", set some bit here. // Then in ActOnSuperMessage() (SemaExprObjC), set it back to false. // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set. // Only do this if the current class actually has a superclass. - if (IC->getSuperClass()) { + if (const ObjCInterfaceDecl *SuperClass = IC->getSuperClass()) { ObjCMethodFamily Family = MDecl->getMethodFamily(); if (Family == OMF_dealloc) { if (!(getLangOpts().ObjCAutoRefCount || @@ -395,8 +408,8 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { } else { const ObjCMethodDecl *SuperMethod = - IC->getSuperClass()->lookupMethod(MDecl->getSelector(), - MDecl->isInstanceMethod()); + SuperClass->lookupMethod(MDecl->getSelector(), + MDecl->isInstanceMethod()); getCurFunction()->ObjCShouldCallSuper = (SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>()); } @@ -508,8 +521,14 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { - if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) + if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) { SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl); + // This handles the following case: + // @interface NewI @end + // typedef NewI DeprI __attribute__((deprecated("blah"))) + // @interface SI : DeprI /* warn here */ @end + (void)DiagnoseUseOfDecl(const_cast<TypedefNameDecl*>(TDecl), SuperLoc); + } } } @@ -731,7 +750,9 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, // If this is a forward declaration and we are supposed to warn in this // case, do it. - if (WarnOnDeclarations && !PDecl->hasDefinition()) + // FIXME: Recover nicely in the hidden case. + if (WarnOnDeclarations && + (!PDecl->hasDefinition() || PDecl->getDefinition()->isHidden())) Diag(ProtocolId[i].second, diag::warn_undef_protocolref) << ProtocolId[i].first; Protocols.push_back(PDecl); @@ -837,16 +858,12 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, 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 (ObjCCategoryDecl *Previous + = IDecl->FindCategoryDeclaration(CategoryName)) { + // Class extensions can be declared multiple times, categories cannot. + Diag(CategoryLoc, diag::warn_dup_category_def) + << ClassName << CategoryName; + Diag(Previous->getLocation(), diag::note_previous_definition); } } @@ -1155,16 +1172,29 @@ void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, void Sema::WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl, unsigned DiagID) { // No point warning no definition of method which is 'unavailable'. - if (method->hasAttr<UnavailableAttr>()) + switch (method->getAvailability()) { + case AR_Available: + case AR_Deprecated: + break; + + // Don't warn about unavailable or not-yet-introduced methods. + case AR_NotYetIntroduced: + case AR_Unavailable: return; - 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(); + + // FIXME: For now ignore 'IncompleteImpl'. + // Previously we grouped all unimplemented methods under a single + // warning, but some users strongly voiced that they would prefer + // separate warnings. We will give that approach a try, as that + // matches what we do with protocols. + + Diag(ImpLoc, DiagID) << method->getDeclName(); + + // Issue a note to the original declaration. + SourceLocation MethodLoc = method->getLocStart(); + if (MethodLoc.isValid()) + Diag(MethodLoc, diag::note_method_declared_at) << method; } /// Determines if type B can be substituted for type A. Returns true if we can @@ -1571,6 +1601,11 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, NSIDecl = IDecl->lookupInheritedClass(&Context.Idents.get("NSProxy")); } + // If this is a forward protocol declaration, get its definition. + if (!PDecl->isThisDeclarationADefinition() && + PDecl->getDefinition()) + PDecl = PDecl->getDefinition(); + // 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 @@ -1603,8 +1638,6 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != DiagnosticsEngine::Ignored) { WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); - Diag(method->getLocation(), diag::note_method_declared_at) - << method->getDeclName(); Diag(CDecl->getLocation(), diag::note_required_for_protocol_at) << PDecl->getDeclName(); } @@ -1626,8 +1659,6 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != DiagnosticsEngine::Ignored) { WarnUndefinedMethod(ImpLoc, method, IncompleteImpl, DIAG); - Diag(method->getLocation(), diag::note_method_declared_at) - << method->getDeclName(); Diag(IDecl->getLocation(), diag::note_required_for_protocol_at) << PDecl->getDeclName(); } @@ -1662,7 +1693,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, !InsMap.count((*I)->getSelector())) { if (ImmediateClass) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, - diag::note_undef_method_impl); + diag::warn_undef_method_impl); continue; } else { ObjCMethodDecl *ImpMethodDecl = @@ -1692,7 +1723,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, if (!ClsMap.count((*I)->getSelector())) { if (ImmediateClass) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, - diag::note_undef_method_impl); + diag::warn_undef_method_impl); } else { ObjCMethodDecl *ImpMethodDecl = IMPDecl->getClassMethod((*I)->getSelector()); @@ -1712,24 +1743,27 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, // when checking that methods in implementation match their declaration, // i.e. when WarnCategoryMethodImpl is false, check declarations in class // extension; as well as those in categories. - if (!WarnCategoryMethodImpl) - for (const ObjCCategoryDecl *CDeclChain = I->getCategoryList(); - CDeclChain; CDeclChain = CDeclChain->getNextClassCategory()) + if (!WarnCategoryMethodImpl) { + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = I->visible_categories_begin(), + CatEnd = I->visible_categories_end(); + Cat != CatEnd; ++Cat) { MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, - IMPDecl, - const_cast<ObjCCategoryDecl *>(CDeclChain), - IncompleteImpl, false, + IMPDecl, *Cat, IncompleteImpl, false, WarnCategoryMethodImpl); - else + } + } else { // Also methods in class extensions need be looked at next. - for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = I->visible_extensions_begin(), + ExtEnd = I->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, - IMPDecl, - const_cast<ObjCCategoryDecl *>(ClsExtDecl), - IncompleteImpl, false, + IMPDecl, *Ext, IncompleteImpl, false, WarnCategoryMethodImpl); - + } + } + // Check for any implementation of a methods declared in protocol. for (ObjCInterfaceDecl::all_protocol_iterator PI = I->all_referenced_protocol_begin(), @@ -1832,11 +1866,12 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, 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); + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = I->visible_extensions_begin(), + ExtEnd = I->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + ImplMethodsVsClassMethods(S, IMPDecl, *Ext, IncompleteImpl); + } } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { // For extended class, unimplemented methods in its protocols will // be reported in the primary class. @@ -2017,6 +2052,10 @@ bool Sema::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, left->getResultType(), right->getResultType())) return false; + // If either is hidden, it is not considered to match. + if (left->isHidden() || right->isHidden()) + return false; + if (getLangOpts().ObjCAutoRefCount && (left->hasAttr<NSReturnsRetainedAttr>() != right->hasAttr<NSReturnsRetainedAttr>() || @@ -2141,61 +2180,79 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, if (Pos == MethodPool.end()) return 0; + // Gather the non-hidden methods. ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; + llvm::SmallVector<ObjCMethodDecl *, 4> Methods; + for (ObjCMethodList *M = &MethList; M; M = M->Next) { + if (M->Method && !M->Method->isHidden()) { + // If we're not supposed to warn about mismatches, we're done. + if (!warn) + return M->Method; + + Methods.push_back(M->Method); + } + } - if (warn && MethList.Method && MethList.Next) { - bool issueDiagnostic = false, issueError = false; - - // We support a warning which complains about *any* difference in - // method signature. - bool strictSelectorMatch = - (receiverIdOrClass && warn && - (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl, - R.getBegin()) != - DiagnosticsEngine::Ignored)); - if (strictSelectorMatch) - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { - if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, - MMS_strict)) { - issueDiagnostic = true; - break; - } + // If there aren't any visible methods, we're done. + // FIXME: Recover if there are any known-but-hidden methods? + if (Methods.empty()) + return 0; + + if (Methods.size() == 1) + return Methods[0]; + + // We found multiple methods, so we may have to complain. + bool issueDiagnostic = false, issueError = false; + + // We support a warning which complains about *any* difference in + // method signature. + bool strictSelectorMatch = + (receiverIdOrClass && warn && + (Diags.getDiagnosticLevel(diag::warn_strict_multiple_method_decl, + R.getBegin()) + != DiagnosticsEngine::Ignored)); + if (strictSelectorMatch) { + for (unsigned I = 1, N = Methods.size(); I != N; ++I) { + if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) { + issueDiagnostic = true; + break; } + } + } - // If we didn't see any strict differences, we won't see any loose - // differences. In ARC, however, we also need to check for loose - // mismatches, because most of them are errors. - if (!strictSelectorMatch || - (issueDiagnostic && getLangOpts().ObjCAutoRefCount)) - for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next) { - // This checks if the methods differ in type mismatch. - if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, - MMS_loose) && - !isAcceptableMethodMismatch(MethList.Method, Next->Method)) { - issueDiagnostic = true; - if (getLangOpts().ObjCAutoRefCount) - issueError = true; - break; - } + // If we didn't see any strict differences, we won't see any loose + // differences. In ARC, however, we also need to check for loose + // mismatches, because most of them are errors. + if (!strictSelectorMatch || + (issueDiagnostic && getLangOpts().ObjCAutoRefCount)) + for (unsigned I = 1, N = Methods.size(); I != N; ++I) { + // This checks if the methods differ in type mismatch. + if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_loose) && + !isAcceptableMethodMismatch(Methods[0], Methods[I])) { + issueDiagnostic = true; + if (getLangOpts().ObjCAutoRefCount) + issueError = true; + break; } + } - if (issueDiagnostic) { - if (issueError) - Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R; - else if (strictSelectorMatch) - Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R; - else - Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; + if (issueDiagnostic) { + if (issueError) + Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R; + else 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(), - issueError ? diag::note_possibility : 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(); - } + Diag(Methods[0]->getLocStart(), + issueError ? diag::note_possibility : diag::note_using) + << Methods[0]->getSourceRange(); + for (unsigned I = 1, N = Methods.size(); I != N; ++I) { + Diag(Methods[I]->getLocStart(), diag::note_also_found) + << Methods[I]->getSourceRange(); } - return MethList.Method; + } + return Methods[0]; } ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { @@ -2334,18 +2391,13 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, } } } - if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { - // Compares properties declared in this class to those of its - // super class. - ComparePropertiesInBaseAndSuper(I); - CompareProperties(I, I); + if (isa<ObjCInterfaceDecl>(ClassDecl)) { + // Nothing to do here. } 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); @@ -2370,11 +2422,12 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, // 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) { + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = IDecl->visible_extensions_begin(), + ExtEnd = IDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + for (ObjCContainerDecl::prop_iterator I = Ext->prop_begin(), + E = Ext->prop_end(); I != E; ++I) { ObjCPropertyDecl *Property = *I; // Skip over properties declared @dynamic if (const ObjCPropertyImplDecl *PIDecl @@ -2382,18 +2435,19 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; - - for (const ObjCCategoryDecl *CExtDecl = - IDecl->getFirstClassExtension(); - CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) { - if (ObjCMethodDecl *GetterMethod = - CExtDecl->getInstanceMethod(Property->getGetterName())) + + for (ObjCInterfaceDecl::visible_extensions_iterator + Ext = IDecl->visible_extensions_begin(), + ExtEnd = IDecl->visible_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (ObjCMethodDecl *GetterMethod + = Ext->getInstanceMethod(Property->getGetterName())) GetterMethod->setPropertyAccessor(true); if (!Property->isReadOnly()) - if (ObjCMethodDecl *SetterMethod = - CExtDecl->getInstanceMethod(Property->getSetterName())) + if (ObjCMethodDecl *SetterMethod + = Ext->getInstanceMethod(Property->getSetterName())) SetterMethod->setPropertyAccessor(true); - } + } } } ImplMethodsVsClassMethods(S, IC, IDecl); @@ -2442,12 +2496,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange 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 (ObjCCategoryDecl *Cat + = IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier())) { + ImplMethodsVsClassMethods(S, CatImplClass, Cat); } } } @@ -2682,9 +2733,12 @@ private: return; // - categories, - for (ObjCCategoryDecl *category = iface->getCategoryList(); - category; category = category->getNextClassCategory()) - search(category); + for (ObjCInterfaceDecl::known_categories_iterator + cat = iface->known_categories_begin(), + catEnd = iface->known_categories_end(); + cat != catEnd; ++cat) { + search(*cat); + } // - the super class, and if (ObjCInterfaceDecl *super = iface->getSuperClass()) @@ -2711,7 +2765,8 @@ private: void search(ObjCContainerDecl *container) { // Check for a method in this container which matches this selector. ObjCMethodDecl *meth = container->getMethod(Method->getSelector(), - Method->isInstanceMethod()); + Method->isInstanceMethod(), + /*AllowHidden=*/true); // If we find one, record it and bail out. if (meth) { @@ -2858,8 +2913,6 @@ Decl *Sema::ActOnMethodDeclaration( DI = 0; } else { ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI); - // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). - ArgType = Context.getAdjustedParameterType(ArgType); } LookupResult R(*this, ArgInfo[i].Name, ArgInfo[i].NameLoc, @@ -2883,7 +2936,7 @@ Decl *Sema::ActOnMethodDeclaration( ParmVarDecl* Param = CheckParameter(ObjCMethod, StartLoc, ArgInfo[i].NameLoc, ArgInfo[i].Name, - ArgType, DI, SC_None, SC_None); + ArgType, DI, SC_None); Param->setObjCMethodScopeInfo(i); @@ -2985,7 +3038,7 @@ Decl *Sema::ActOnMethodDeclaration( bool ARCError = false; if (getLangOpts().ObjCAutoRefCount) - ARCError = CheckARCMethodDecl(*this, ObjCMethod); + ARCError = CheckARCMethodDecl(ObjCMethod); // Infer the related result type when possible. if (!ARCError && RTC == Sema::RTC_Compatible && @@ -3114,7 +3167,7 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, } VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id, - T, TInfo, SC_None, SC_None); + T, TInfo, SC_None); New->setExceptionVariable(true); // In ARC, infer 'retaining' for variables of retainable type. @@ -3142,7 +3195,7 @@ Decl *Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); D.getMutableDeclSpec().ClearStorageClassSpecs(); - DiagnoseFunctionSpecifiers(D); + DiagnoseFunctionSpecifiers(D.getDeclSpec()); // Check that there are no default arguments inside the type of this // exception object (C++ only). diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index e1f4888..26c3d35 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -16,9 +16,9 @@ #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 "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -38,43 +38,55 @@ static const FunctionProtoType *GetUnderlyingFunction(QualType T) /// 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, - 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; +/// +/// \param[in,out] T The exception type. This will be decayed to a pointer type +/// when the input is an array or a function type. +bool Sema::CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range) { + // C++11 [except.spec]p2: + // A type cv T, "array of T", or "function returning T" denoted + // in an exception-specification is adjusted to type T, "pointer to T", or + // "pointer to function returning T", respectively. + // + // We also apply this rule in C++98. + if (T->isArrayType()) + T = Context.getArrayDecayedType(T); + else if (T->isFunctionType()) + T = Context.getPointerType(T); + + int Kind = 0; + QualType PointeeT = T; + if (const PointerType *PT = T->getAs<PointerType>()) { + PointeeT = PT->getPointeeType(); + Kind = 1; + + // cv void* is explicitly permitted, despite being a pointer to an + // incomplete type. + if (PointeeT->isVoidType()) + return false; + } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) { + PointeeT = RT->getPointeeType(); + Kind = 2; + + if (RT->isRValueReferenceType()) { + // C++11 [except.spec]p2: + // A type denoted in an exception-specification shall not denote [...] + // an rvalue reference type. + Diag(Range.getBegin(), diag::err_rref_in_exception_spec) + << T << Range; + return true; + } + } - // Again as before - if (T->isRecordType() && T->getAs<RecordType>()->isBeingDefined()) - return false; - - if (!T->isVoidType() && - RequireCompleteType(Range.getBegin(), T, - diag::err_incomplete_in_exception_spec, kind, Range)) + // C++11 [except.spec]p2: + // A type denoted in an exception-specification shall not denote an + // incomplete type other than a class currently being defined [...]. + // A type denoted in an exception-specification shall not denote a + // pointer or reference to an incomplete type, other than (cv) void* or a + // pointer or reference to a class currently being defined. + if (!(PointeeT->isRecordType() && + PointeeT->getAs<RecordType>()->isBeingDefined()) && + RequireCompleteType(Range.getBegin(), PointeeT, + diag::err_incomplete_in_exception_spec, Kind, Range)) return true; return false; @@ -112,7 +124,7 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { return SourceFPT; // Compute or instantiate the exception specification now. - if (FPT->getExceptionSpecType() == EST_Unevaluated) + if (SourceFPT->getExceptionSpecType() == EST_Unevaluated) EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl)); else InstantiateExceptionSpec(Loc, SourceDecl); @@ -159,7 +171,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // If a declaration of a function has an implicit // exception-specification, other declarations of the function shall // not specify an exception-specification. - if (getLangOpts().CPlusPlus0x && + if (getLangOpts().CPlusPlus11 && hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) { Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch) << hasImplicitExceptionSpec(Old); @@ -191,10 +203,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { Old->isExternC()) { FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); EPI.ExceptionSpecType = EST_DynamicNone; - QualType NewType = Context.getFunctionType(NewProto->getResultType(), - NewProto->arg_type_begin(), - NewProto->getNumArgs(), - EPI); + QualType NewType = + Context.getFunctionType(NewProto->getResultType(), + ArrayRef<QualType>(NewProto->arg_type_begin(), + NewProto->getNumArgs()), + EPI); New->setType(NewType); return false; } @@ -215,10 +228,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // Update the type of the function with the appropriate exception // specification. - QualType NewType = Context.getFunctionType(NewProto->getResultType(), - NewProto->arg_type_begin(), - NewProto->getNumArgs(), - EPI); + QualType NewType = + Context.getFunctionType(NewProto->getResultType(), + ArrayRef<QualType>(NewProto->arg_type_begin(), + NewProto->getNumArgs()), + EPI); New->setType(NewType); // If exceptions are disabled, suppress the warning about missing @@ -282,8 +296,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { 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 (FunctionTypeLoc FTLoc = TL.getAs<FunctionTypeLoc>()) + FixItLoc = PP.getLocForEndOfToken(FTLoc.getLocalRangeEnd()); } if (FixItLoc.isInvalid()) @@ -442,7 +456,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, // 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 (getLangOpts().CPlusPlus0x && IsOperatorNew) { + if (getLangOpts().CPlusPlus11 && IsOperatorNew) { const FunctionProtoType *WithExceptions = 0; if (OldEST == EST_None && NewEST == EST_Dynamic) WithExceptions = New; @@ -773,7 +787,7 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - if (getLangOpts().CPlusPlus0x && isa<CXXDestructorDecl>(New)) { + if (getLangOpts().CPlusPlus11 && 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()) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bf4abfc..76330f5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -12,13 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/DelayedDiagnostic.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/AnalysisBasedWarnings.h" -#include "clang/AST/ASTContext.h" +#include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -34,14 +30,17 @@ #include "clang/Basic/TargetInfo.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/AnalysisBasedWarnings.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Designator.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/Template.h" -#include "TreeTransform.h" using namespace clang; using namespace sema; @@ -163,7 +162,7 @@ static bool hasAnyExplicitStorageClass(const FunctionDecl *D) { for (FunctionDecl::redecl_iterator I = D->redecls_begin(), E = D->redecls_end(); I != E; ++I) { - if (I->getStorageClassAsWritten() != SC_None) + if (I->getStorageClass() != SC_None) return true; } return false; @@ -215,19 +214,24 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S, : diag::warn_internal_in_extern_inline) << /*IsVar=*/!UsedFn << D; - // Suggest "static" on the inline function, if possible. - if (!hasAnyExplicitStorageClass(Current)) { - const FunctionDecl *FirstDecl = Current->getCanonicalDecl(); - SourceLocation DeclBegin = FirstDecl->getSourceRange().getBegin(); - S.Diag(DeclBegin, diag::note_convert_inline_to_static) - << Current << FixItHint::CreateInsertion(DeclBegin, "static "); - } + S.MaybeSuggestAddingStaticToDecl(Current); S.Diag(D->getCanonicalDecl()->getLocation(), diag::note_internal_decl_declared_here) << D; } +void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { + const FunctionDecl *First = Cur->getFirstDeclaration(); + + // Suggest "static" on the function, if possible. + if (!hasAnyExplicitStorageClass(First)) { + SourceLocation DeclBegin = First->getSourceRange().getBegin(); + Diag(DeclBegin, diag::note_convert_inline_to_static) + << Cur << FixItHint::CreateInsertion(DeclBegin, "static "); + } +} + /// \brief Determine whether the use of this declaration is valid, and /// emit any corresponding diagnostics. /// @@ -288,12 +292,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, /// 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; @@ -457,6 +455,62 @@ static void CheckForNullPointerDereference(Sema &S, Expr *E) { } } +static void DiagnoseDirectIsaAccess(Sema &S, const ObjCIvarRefExpr *OIRE, + SourceLocation AssignLoc, + const Expr* RHS) { + const ObjCIvarDecl *IV = OIRE->getDecl(); + if (!IV) + return; + + DeclarationName MemberName = IV->getDeclName(); + IdentifierInfo *Member = MemberName.getAsIdentifierInfo(); + if (!Member || !Member->isStr("isa")) + return; + + const Expr *Base = OIRE->getBase(); + QualType BaseType = Base->getType(); + if (OIRE->isArrow()) + BaseType = BaseType->getPointeeType(); + if (const ObjCObjectType *OTy = BaseType->getAs<ObjCObjectType>()) + if (ObjCInterfaceDecl *IDecl = OTy->getInterface()) { + ObjCInterfaceDecl *ClassDeclared = 0; + ObjCIvarDecl *IV = IDecl->lookupInstanceVariable(Member, ClassDeclared); + if (!ClassDeclared->getSuperClass() + && (*ClassDeclared->ivar_begin()) == IV) { + if (RHS) { + NamedDecl *ObjectSetClass = + S.LookupSingleName(S.TUScope, + &S.Context.Idents.get("object_setClass"), + SourceLocation(), S.LookupOrdinaryName); + if (ObjectSetClass) { + SourceLocation RHSLocEnd = S.PP.getLocForEndOfToken(RHS->getLocEnd()); + S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_assign) << + FixItHint::CreateInsertion(OIRE->getLocStart(), "object_setClass(") << + FixItHint::CreateReplacement(SourceRange(OIRE->getOpLoc(), + AssignLoc), ",") << + FixItHint::CreateInsertion(RHSLocEnd, ")"); + } + else + S.Diag(OIRE->getLocation(), diag::warn_objc_isa_assign); + } else { + NamedDecl *ObjectGetClass = + S.LookupSingleName(S.TUScope, + &S.Context.Idents.get("object_getClass"), + SourceLocation(), S.LookupOrdinaryName); + if (ObjectGetClass) + S.Diag(OIRE->getExprLoc(), diag::warn_objc_isa_use) << + FixItHint::CreateInsertion(OIRE->getLocStart(), "object_getClass(") << + FixItHint::CreateReplacement( + SourceRange(OIRE->getOpLoc(), + OIRE->getLocEnd()), ")"); + else + S.Diag(OIRE->getLocation(), diag::warn_objc_isa_use); + } + S.Diag(IV->getLocation(), diag::note_ivar_decl); + } + } +} + ExprResult Sema::DefaultLvalueConversion(Expr *E) { // Handle any placeholder expressions which made it here. if (E->getType()->isPlaceholderType()) { @@ -489,8 +543,31 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { if (T->isVoidType()) return Owned(E); - CheckForNullPointerDereference(*this, E); + // OpenCL usually rejects direct accesses to values of 'half' type. + if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 && + T->isHalfType()) { + Diag(E->getExprLoc(), diag::err_opencl_half_load_store) + << 0 << T; + return ExprError(); + } + CheckForNullPointerDereference(*this, E); + if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(E->IgnoreParenCasts())) { + NamedDecl *ObjectGetClass = LookupSingleName(TUScope, + &Context.Idents.get("object_getClass"), + SourceLocation(), LookupOrdinaryName); + if (ObjectGetClass) + Diag(E->getExprLoc(), diag::warn_objc_isa_use) << + FixItHint::CreateInsertion(OISA->getLocStart(), "object_getClass(") << + FixItHint::CreateReplacement( + SourceRange(OISA->getOpLoc(), OISA->getIsaMemberLoc()), ")"); + else + Diag(E->getExprLoc(), diag::warn_objc_isa_use); + } + else if (const ObjCIvarRefExpr *OIRE = + dyn_cast<ObjCIvarRefExpr>(E->IgnoreParenCasts())) + DiagnoseDirectIsaAccess(*this, OIRE, SourceLocation(), /* Expr*/0); + // 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 @@ -504,6 +581,12 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { T = T.getUnqualifiedType(); UpdateMarkingForLValueToRValue(E); + + // Loading a __weak object implicitly retains the value, so we need a cleanup to + // balance that. + if (getLangOpts().ObjCAutoRefCount && + E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) + ExprNeedsCleanups = true; ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, 0, VK_RValue)); @@ -540,15 +623,14 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) { // First, convert to an r-value. ExprResult Res = DefaultFunctionArrayLvalueConversion(E); if (Res.isInvalid()) - return Owned(E); + return ExprError(); E = Res.take(); QualType Ty = E->getType(); assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); - // Half FP is a bit different: it's a storage-only type, meaning that any - // "use" of it should be promoted to float. - if (Ty->isHalfType()) + // Half FP have to be promoted to float unless it is natively supported + if (Ty->isHalfType() && !getLangOpts().NativeHalfType) return ImpCastExprToType(Res.take(), Context.FloatTy, CK_FloatingCast); // Try to perform integral promotions if the object has a theoretically @@ -583,19 +665,23 @@ ExprResult Sema::UsualUnaryConversions(Expr *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(). +/// do not have a prototype. Arguments that have type float or __fp16 +/// 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); + return ExprError(); E = Res.take(); - // If this is a 'float' (CVR qualified or typedef) promote to double. - if (Ty->isSpecificBuiltinType(BuiltinType::Float)) + // If this is a 'float' or '__fp16' (CVR qualified or typedef) promote to + // double. + const BuiltinType *BTy = Ty->getAs<BuiltinType>(); + if (BTy && (BTy->getKind() == BuiltinType::Half || + BTy->getKind() == BuiltinType::Float)) E = ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast).take(); // C++ performs lvalue-to-rvalue conversion as a default argument @@ -635,16 +721,16 @@ Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) { if (Ty.isCXX98PODType(Context)) return VAK_Valid; - // C++0x [expr.call]p7: - // Passing a potentially-evaluated argument of class type (Clause 9) + // C++11 [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, + // or a non-trivial destructor, with no corresponding parameter, // is conditionally-supported with implementation-defined semantics. - if (getLangOpts().CPlusPlus0x && !Ty->isDependentType()) + if (getLangOpts().CPlusPlus11 && !Ty->isDependentType()) if (CXXRecordDecl *Record = Ty->getAsCXXRecordDecl()) - if (Record->hasTrivialCopyConstructor() && - Record->hasTrivialMoveConstructor() && - Record->hasTrivialDestructor()) + if (!Record->hasNonTrivialCopyConstructor() && + !Record->hasNonTrivialMoveConstructor() && + !Record->hasNonTrivialDestructor()) return VAK_ValidInCXX11; if (getLangOpts().ObjCAutoRefCount && Ty->isObjCLifetimeType()) @@ -673,7 +759,7 @@ bool Sema::variadicArgumentPODCheck(const Expr *E, VariadicCallType CT) { return DiagRuntimeBehavior(E->getLocStart(), 0, PDiag(diag::warn_cannot_pass_non_pod_arg_to_vararg) - << getLangOpts().CPlusPlus0x << Ty << CT); + << getLangOpts().CPlusPlus11 << Ty << CT); } } // c++ rules are enforced elsewhere. @@ -938,54 +1024,24 @@ static QualType handleFloatConversion(Sema &S, ExprResult &LHS, /*convertFloat=*/!IsCompAssign); } -/// \brief Handle conversions with GCC complex int extension. Helper function -/// of UsualArithmeticConversions() -// FIXME: if the operands are (int, _Complex long), we currently -// don't promote the complex. Also, signedness? -static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, - ExprResult &RHS, QualType LHSType, - QualType RHSType, - bool IsCompAssign) { - const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType(); - const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType(); +typedef ExprResult PerformCastFn(Sema &S, Expr *operand, QualType toType); - if (LHSComplexInt && RHSComplexInt) { - int order = S.Context.getIntegerTypeOrder(LHSComplexInt->getElementType(), - RHSComplexInt->getElementType()); - assert(order && "inequal types with equal element ordering"); - if (order > 0) { - // _Complex int -> _Complex long - RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralComplexCast); - return LHSType; - } - - if (!IsCompAssign) - LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralComplexCast); - return RHSType; - } - - if (LHSComplexInt) { - // int -> _Complex int - // FIXME: This needs to take integer ranks into account - RHS = S.ImpCastExprToType(RHS.take(), LHSComplexInt->getElementType(), - CK_IntegralCast); - RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralRealToComplex); - return LHSType; - } +namespace { +/// These helper callbacks are placed in an anonymous namespace to +/// permit their use as function template parameters. +ExprResult doIntegralCast(Sema &S, Expr *op, QualType toType) { + return S.ImpCastExprToType(op, toType, CK_IntegralCast); +} - assert(RHSComplexInt); - // int -> _Complex int - // FIXME: This needs to take integer ranks into account - if (!IsCompAssign) { - LHS = S.ImpCastExprToType(LHS.take(), RHSComplexInt->getElementType(), - CK_IntegralCast); - LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralRealToComplex); - } - return RHSType; +ExprResult doComplexIntegralCast(Sema &S, Expr *op, QualType toType) { + return S.ImpCastExprToType(op, S.Context.getComplexType(toType), + CK_IntegralComplexCast); +} } /// \brief Handle integer arithmetic conversions. Helper function of /// UsualArithmeticConversions() +template <PerformCastFn doLHSCast, PerformCastFn doRHSCast> static QualType handleIntegerConversion(Sema &S, ExprResult &LHS, ExprResult &RHS, QualType LHSType, QualType RHSType, bool IsCompAssign) { @@ -996,29 +1052,29 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS, if (LHSSigned == RHSSigned) { // Same signedness; use the higher-ranked type if (order >= 0) { - RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast); + RHS = (*doRHSCast)(S, RHS.take(), LHSType); return LHSType; } else if (!IsCompAssign) - LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast); + LHS = (*doLHSCast)(S, LHS.take(), RHSType); return RHSType; } else if (order != (LHSSigned ? 1 : -1)) { // The unsigned type has greater than or equal rank to the // signed type, so use the unsigned type if (RHSSigned) { - RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast); + RHS = (*doRHSCast)(S, RHS.take(), LHSType); return LHSType; } else if (!IsCompAssign) - LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast); + LHS = (*doLHSCast)(S, LHS.take(), RHSType); return RHSType; } else if (S.Context.getIntWidth(LHSType) != S.Context.getIntWidth(RHSType)) { // 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) { - RHS = S.ImpCastExprToType(RHS.take(), LHSType, CK_IntegralCast); + RHS = (*doRHSCast)(S, RHS.take(), LHSType); return LHSType; } else if (!IsCompAssign) - LHS = S.ImpCastExprToType(LHS.take(), RHSType, CK_IntegralCast); + LHS = (*doLHSCast)(S, LHS.take(), RHSType); return RHSType; } else { // The signed type is higher-ranked than the unsigned type, @@ -1027,19 +1083,62 @@ static QualType handleIntegerConversion(Sema &S, ExprResult &LHS, // to the signed type. QualType result = S.Context.getCorrespondingUnsignedType(LHSSigned ? LHSType : RHSType); - RHS = S.ImpCastExprToType(RHS.take(), result, CK_IntegralCast); + RHS = (*doRHSCast)(S, RHS.take(), result); if (!IsCompAssign) - LHS = S.ImpCastExprToType(LHS.take(), result, CK_IntegralCast); + LHS = (*doLHSCast)(S, LHS.take(), result); return result; } } +/// \brief Handle conversions with GCC complex int extension. Helper function +/// of UsualArithmeticConversions() +static QualType handleComplexIntConversion(Sema &S, ExprResult &LHS, + ExprResult &RHS, QualType LHSType, + QualType RHSType, + bool IsCompAssign) { + const ComplexType *LHSComplexInt = LHSType->getAsComplexIntegerType(); + const ComplexType *RHSComplexInt = RHSType->getAsComplexIntegerType(); + + if (LHSComplexInt && RHSComplexInt) { + QualType LHSEltType = LHSComplexInt->getElementType(); + QualType RHSEltType = RHSComplexInt->getElementType(); + QualType ScalarType = + handleIntegerConversion<doComplexIntegralCast, doComplexIntegralCast> + (S, LHS, RHS, LHSEltType, RHSEltType, IsCompAssign); + + return S.Context.getComplexType(ScalarType); + } + + if (LHSComplexInt) { + QualType LHSEltType = LHSComplexInt->getElementType(); + QualType ScalarType = + handleIntegerConversion<doComplexIntegralCast, doIntegralCast> + (S, LHS, RHS, LHSEltType, RHSType, IsCompAssign); + QualType ComplexType = S.Context.getComplexType(ScalarType); + RHS = S.ImpCastExprToType(RHS.take(), ComplexType, + CK_IntegralRealToComplex); + + return ComplexType; + } + + assert(RHSComplexInt); + + QualType RHSEltType = RHSComplexInt->getElementType(); + QualType ScalarType = + handleIntegerConversion<doIntegralCast, doComplexIntegralCast> + (S, LHS, RHS, LHSType, RHSEltType, IsCompAssign); + QualType ComplexType = S.Context.getComplexType(ScalarType); + + if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.take(), ComplexType, + CK_IntegralRealToComplex); + return ComplexType; +} + /// 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 &LHS, ExprResult &RHS, bool IsCompAssign) { if (!IsCompAssign) { @@ -1104,10 +1203,11 @@ QualType Sema::UsualArithmeticConversions(ExprResult &LHS, ExprResult &RHS, IsCompAssign); // Finally, we have two differing integer types. - return handleIntegerConversion(*this, LHS, RHS, LHSType, RHSType, - IsCompAssign); + return handleIntegerConversion<doIntegralCast, doIntegralCast> + (*this, LHS, RHS, LHSType, RHSType, IsCompAssign); } + //===----------------------------------------------------------------------===// // Semantic Analysis for various Expression Types //===----------------------------------------------------------------------===// @@ -1149,6 +1249,12 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, TypeSourceInfo **Types, Expr **Exprs, unsigned NumAssocs) { + if (ControllingExpr->getType()->isPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(ControllingExpr); + if (result.isInvalid()) return ExprError(); + ControllingExpr = result.take(); + } + bool TypeErrorFound = false, IsResultDependent = ControllingExpr->isTypeDependent(), ContainsUnexpandedParameterPack @@ -1401,7 +1507,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, ExprResult Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, - const CXXScopeSpec *SS) { + const CXXScopeSpec *SS, NamedDecl *FoundD) { if (getLangOpts().CUDA) if (const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext)) if (const FunctionDecl *Callee = dyn_cast<FunctionDecl>(D)) { @@ -1425,7 +1531,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, : NestedNameSpecifierLoc(), SourceLocation(), D, refersToEnclosingScope, - NameInfo, Ty, VK); + NameInfo, Ty, VK, FoundD); MarkDeclRefReferenced(E); @@ -1533,9 +1639,10 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>( CallsUndergoingInstantiation.back()->getCallee()); - CXXMethodDecl *DepMethod; - if (CurMethod->getTemplatedKind() == + if (CurMethod->isDependentContext()) + DepMethod = CurMethod; + else if (CurMethod->getTemplatedKind() == FunctionDecl::TK_FunctionTemplateSpecialization) DepMethod = cast<CXXMethodDecl>(CurMethod->getPrimaryTemplate()-> getInstantiatedFromMemberTemplate()->getTemplatedDecl()); @@ -1642,9 +1749,13 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, << SS.getRange() << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), CorrectedStr); - if (ND) - Diag(ND->getLocation(), diag::note_previous_decl) - << CorrectedQuotedStr; + + unsigned diag = isa<ImplicitParamDecl>(ND) + ? diag::note_implicit_param_decl + : diag::note_previous_decl; + + Diag(ND->getLocation(), diag) + << CorrectedQuotedStr; // Tell the callee to try to recover. return false; @@ -1946,6 +2057,10 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, IdentifierInfo *II, bool AllowBuiltinCreation) { SourceLocation Loc = Lookup.getNameLoc(); ObjCMethodDecl *CurMethod = getCurMethodDecl(); + + // Check for error condition which is already reported. + if (!CurMethod) + return ExprError(); // 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 @@ -2009,14 +2124,15 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, if (SelfExpr.isInvalid()) return ExprError(); - MarkAnyDeclReferenced(Loc, IV); + MarkAnyDeclReferenced(Loc, IV, true); ObjCMethodFamily MF = CurMethod->getMethodFamily(); - if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize) + if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize && + !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV)) Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName(); ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(), - Loc, + Loc, IV->getLocation(), SelfExpr.take(), true, true); @@ -2321,8 +2437,8 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // 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()); + return BuildDeclarationNameExpr(SS, R.getLookupNameInfo(), R.getFoundDecl(), + R.getRepresentativeDecl()); // We only need to check the declaration if there's exactly one // result, because in the overloaded case the results can only be @@ -2350,7 +2466,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, - NamedDecl *D) { + NamedDecl *D, NamedDecl *FoundD) { assert(D && "Cannot refer to a NULL declaration"); assert(!isa<FunctionTemplateDecl>(D) && "Cannot refer unambiguously to a function template"); @@ -2546,7 +2662,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, break; } - return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS); + return BuildDeclRefExpr(VD, type, valueKind, NameInfo, &SS, FoundD); } } @@ -2565,8 +2681,14 @@ ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) { // string. Decl *currentDecl = getCurFunctionOrMethodDecl(); - if (!currentDecl && getCurBlock()) - currentDecl = getCurBlock()->TheDecl; + // Blocks and lambdas can occur at global scope. Don't emit a warning. + if (!currentDecl) { + if (const BlockScopeInfo *BSI = getCurBlock()) + currentDecl = BSI->TheDecl; + else if (const LambdaScopeInfo *LSI = getCurLambda()) + currentDecl = LSI->CallOperator; + } + if (!currentDecl) { Diag(Loc, diag::ext_predef_outside_function); currentDecl = Context.getTranslationUnitDecl(); @@ -2764,7 +2886,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { SourceLocation TokLoc = Tok.getLocation(); unsigned Length = Literal.getUDSuffixOffset(); QualType StrTy = Context.getConstantArrayType( - Context.CharTy, llvm::APInt(32, Length + 1), + Context.CharTy.withConst(), llvm::APInt(32, Length + 1), ArrayType::Normal, 0); Expr *Lit = StringLiteral::Create( Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii, @@ -2825,7 +2947,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { if (!getLangOpts().C99 && Literal.isLongLong) { if (getLangOpts().CPlusPlus) Diag(Tok.getLocation(), - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); else Diag(Tok.getLocation(), diag::ext_c99_longlong); @@ -2835,7 +2957,10 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth(); // The microsoft literal suffix extensions support 128-bit literals, which // may be wider than [u]intmax_t. - if (Literal.isMicrosoftInteger && MaxWidth < 128) + // FIXME: Actually, they don't. We seem to have accidentally invented the + // i128 suffix. + if (Literal.isMicrosoftInteger && MaxWidth < 128 && + PP.getTargetInfo().hasInt128Type()) MaxWidth = 128; llvm::APInt ResultVal(MaxWidth, 0); @@ -2905,7 +3030,8 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { // If it doesn't fit in unsigned long long, and we're using Microsoft // extensions, then its a 128-bit integer literal. - if (Ty.isNull() && Literal.isMicrosoftInteger) { + if (Ty.isNull() && Literal.isMicrosoftInteger && + PP.getTargetInfo().hasInt128Type()) { if (Literal.isUnsigned) Ty = Context.UnsignedInt128Ty; else @@ -2963,16 +3089,17 @@ static bool CheckExtensionTraitOperandType(Sema &S, QualType T, 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; + if (T->isFunctionType() && + (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) { + // sizeof(function)/alignof(function) is allowed as an extension. + S.Diag(Loc, diag::ext_sizeof_alignof_function_type) + << TraitKind << ArgRange; return false; } // Allow sizeof(void)/alignof(void) as an extension. if (T->isVoidType()) { - S.Diag(Loc, diag::ext_sizeof_void_type) << TraitKind << ArgRange; + S.Diag(Loc, diag::ext_sizeof_alignof_void_type) << TraitKind << ArgRange; return false; } @@ -2995,6 +3122,24 @@ static bool CheckObjCTraitOperandConstraints(Sema &S, QualType T, return false; } +/// \brief Check whether E is a pointer from a decayed array type (the decayed +/// pointer type is equal to T) and emit a warning if it is. +static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T, + Expr *E) { + // Don't warn if the operation changed the type. + if (T != E->getType()) + return; + + // Now look for array decays. + ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E); + if (!ICE || ICE->getCastKind() != CK_ArrayToPointerDecay) + return; + + S.Diag(Loc, diag::warn_sizeof_array_decay) << ICE->getSourceRange() + << ICE->getType() + << ICE->getSubExpr()->getType(); +} + /// \brief Check the constrains on expression operands to unary type expression /// and type traits. /// @@ -3048,6 +3193,16 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, } } } + + // Warn on "sizeof(array op x)" and "sizeof(x op array)", where the array + // decays into a pointer and returns an unintended result. This is most + // likely a typo for "sizeof(array) op x". + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E->IgnoreParens())) { + warnOnSizeofOnArrayDecay(*this, BO->getOperatorLoc(), BO->getType(), + BO->getLHS()); + warnOnSizeofOnArrayDecay(*this, BO->getOperatorLoc(), BO->getType(), + BO->getRHS()); + } } return false; @@ -3189,7 +3344,7 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, return ExprError(); if (ExprKind == UETT_SizeOf && E->getType()->isVariableArrayType()) { - PE = TranformToPotentiallyEvaluated(E); + PE = TransformToPotentiallyEvaluated(E); if (PE.isInvalid()) return ExprError(); E = PE.take(); } @@ -3292,33 +3447,56 @@ static bool checkArithmeticOnObjCPointer(Sema &S, } ExprResult -Sema::ActOnArraySubscriptExpr(Scope *S, Expr *Base, SourceLocation LLoc, - Expr *Idx, SourceLocation RLoc) { +Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc, + Expr *idx, SourceLocation rbLoc) { // Since this might be a postfix expression, get rid of ParenListExprs. - ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Base); - if (Result.isInvalid()) return ExprError(); - Base = Result.take(); + if (isa<ParenListExpr>(base)) { + ExprResult result = MaybeConvertParenListExprToParenExpr(S, base); + if (result.isInvalid()) return ExprError(); + base = result.take(); + } - Expr *LHSExp = Base, *RHSExp = Idx; + // Handle any non-overload placeholder types in the base and index + // expressions. We can't handle overloads here because the other + // operand might be an overloadable type, in which case the overload + // resolution for the operator overload should get the first crack + // at the overload. + if (base->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(base); + if (result.isInvalid()) return ExprError(); + base = result.take(); + } + if (idx->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(idx); + if (result.isInvalid()) return ExprError(); + idx = result.take(); + } + // Build an unanalyzed expression if either operand is type-dependent. if (getLangOpts().CPlusPlus && - (LHSExp->isTypeDependent() || RHSExp->isTypeDependent())) { - return Owned(new (Context) ArraySubscriptExpr(LHSExp, RHSExp, + (base->isTypeDependent() || idx->isTypeDependent())) { + return Owned(new (Context) ArraySubscriptExpr(base, idx, Context.DependentTy, VK_LValue, OK_Ordinary, - RLoc)); + rbLoc)); } + // Use C++ overloaded-operator rules if either operand has record + // type. The spec says to do this if either type is *overloadable*, + // but enum types can't declare subscript operators or conversion + // operators, so there's nothing interesting for overload resolution + // to do if there aren't any record types involved. + // + // ObjC pointers have their own subscripting logic that is not tied + // to overload resolution and so should not take this path. if (getLangOpts().CPlusPlus && - (LHSExp->getType()->isRecordType() || - LHSExp->getType()->isEnumeralType() || - RHSExp->getType()->isRecordType() || - RHSExp->getType()->isEnumeralType()) && - !LHSExp->getType()->isObjCObjectPointerType()) { - return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, Base, Idx); + (base->getType()->isRecordType() || + (!base->getType()->isObjCObjectPointerType() && + idx->getType()->isRecordType()))) { + return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, idx); } - return CreateBuiltinArraySubscriptExpr(Base, LLoc, Idx, RLoc); + return CreateBuiltinArraySubscriptExpr(base, lbLoc, idx, rbLoc); } ExprResult @@ -3525,7 +3703,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, return ExprError(); Expr *Arg = Result.takeAs<Expr>(); - CheckImplicitConversions(Arg, Param->getOuterLocStart()); + CheckCompletedExpr(Arg, Param->getOuterLocStart()); // Build the default argument expression. return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg)); } @@ -3687,7 +3865,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, Expr **Args, unsigned NumArgs, SmallVector<Expr *, 8> &AllArgs, VariadicCallType CallType, - bool AllowExplicit) { + bool AllowExplicit, + bool IsListInitialization) { unsigned NumArgsInProto = Proto->getNumArgs(); unsigned NumArgsToCheck = NumArgs; bool Invalid = false; @@ -3720,20 +3899,21 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, (!Param || !Param->hasAttr<CFConsumedAttr>())) Arg = stripARCUnbridgedCast(Arg); - InitializedEntity Entity = - Param? InitializedEntity::InitializeParameter(Context, Param) - : InitializedEntity::InitializeParameter(Context, ProtoArgType, - Proto->isArgConsumed(i)); + InitializedEntity Entity = Param ? + InitializedEntity::InitializeParameter(Context, Param, ProtoArgType) + : InitializedEntity::InitializeParameter(Context, ProtoArgType, + Proto->isArgConsumed(i)); ExprResult ArgE = PerformCopyInitialization(Entity, SourceLocation(), Owned(Arg), - /*TopLevelOfInitList=*/false, + IsListInitialization, AllowExplicit); if (ArgE.isInvalid()) return true; Arg = ArgE.takeAs<Expr>(); } else { + assert(FDecl && "can't use default arguments without a known callee"); Param = FDecl->getParamDecl(i); ExprResult ArgExpr = @@ -3762,11 +3942,8 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, 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); + QualType paramType; // ignored + ExprResult arg = checkUnknownAnyArg(CallLoc, Args[i], paramType); Invalid |= arg.isInvalid(); AllArgs.push_back(arg.take()); } @@ -3790,9 +3967,9 @@ bool Sema::GatherArgumentsForCall(SourceLocation CallLoc, static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) { TypeLoc TL = PVD->getTypeSourceInfo()->getTypeLoc(); - if (ArrayTypeLoc *ATL = dyn_cast<ArrayTypeLoc>(&TL)) + if (ArrayTypeLoc ATL = TL.getAs<ArrayTypeLoc>()) S.Diag(PVD->getLocation(), diag::note_callee_static_array) - << ATL->getLocalSourceRange(); + << ATL.getLocalSourceRange(); } /// CheckStaticArrayArgument - If the given argument corresponds to a static @@ -4593,10 +4770,15 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, Expr **exprs; unsigned numExprs; Expr *subExpr; + SourceLocation LiteralLParenLoc, LiteralRParenLoc; if (ParenListExpr *PE = dyn_cast<ParenListExpr>(E)) { + LiteralLParenLoc = PE->getLParenLoc(); + LiteralRParenLoc = PE->getRParenLoc(); exprs = PE->getExprs(); numExprs = PE->getNumExprs(); - } else { + } else { // isa<ParenExpr> by assertion at function entrance + LiteralLParenLoc = cast<ParenExpr>(E)->getLParen(); + LiteralRParenLoc = cast<ParenExpr>(E)->getRParen(); subExpr = cast<ParenExpr>(E)->getSubExpr(); exprs = &subExpr; numExprs = 1; @@ -4653,8 +4835,8 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, } // FIXME: This means that pretty-printing the final AST will produce curly // braces instead of the original commas. - InitListExpr *initE = new (Context) InitListExpr(Context, LParenLoc, - initExprs, RParenLoc); + InitListExpr *initE = new (Context) InitListExpr(Context, LiteralLParenLoc, + initExprs, LiteralRParenLoc); initE->setType(Ty); return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE); } @@ -4681,7 +4863,6 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { ExprResult Sema::ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val) { - assert(Val.data() != 0 && "ActOnParenOrParenListExpr() missing expr list"); Expr *expr = new (Context) ParenListExpr(Context, L, Val, R); return Owned(expr); } @@ -4720,7 +4901,7 @@ bool Sema::DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr, return false; } - int DiagType = (NullKind == Expr::NPCK_CXX0X_nullptr); + int DiagType = (NullKind == Expr::NPCK_CXX11_nullptr); Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands_null) << NonPointerExpr->getType() << DiagType << NonPointerExpr->getSourceRange(); @@ -4734,7 +4915,7 @@ static bool checkCondition(Sema &S, Expr *Cond) { // C99 6.5.15p2 if (CondTy->isScalarType()) return false; - // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar. + // OpenCL v1.1 s6.3.i says the condition is allowed to be a vector or scalar. if (S.getLangOpts().OpenCL && CondTy->isVectorType()) return false; @@ -4995,9 +5176,9 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, if (LHSTy->isVectorType() || RHSTy->isVectorType()) return CheckVectorOperands(LHS, RHS, QuestionLoc, /*isCompAssign*/false); - // OpenCL: If the condition is a vector, and both operands are scalar, + // 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. + // built in select. (OpenCL v1.1 s6.3.i) if (getLangOpts().OpenCL && CondTy->isVectorType()) if (checkConditionalConvertScalarsToVectors(*this, LHS, RHS, CondTy)) return QualType(); @@ -5264,7 +5445,8 @@ static bool IsArithmeticBinaryExpr(Expr *E, BinaryOperatorKind *Opcode, // 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) + if (OO < OO_Plus || OO > OO_Arrow || + OO == OO_PlusPlus || OO == OO_MinusMinus) return false; BinaryOperatorKind OpKind = BinaryOperator::getOverloadedOpcode(OO); @@ -5625,7 +5807,6 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, LHSType = Context.getCanonicalType(LHSType).getUnqualifiedType(); RHSType = Context.getCanonicalType(RHSType).getUnqualifiedType(); - // Common case: no conversion required. if (LHSType == RHSType) { Kind = CK_NoOp; @@ -6570,6 +6751,11 @@ static bool isScopedEnumerationType(QualType T) { static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, unsigned Opc, QualType LHSType) { + // OpenCL 6.3j: shift values are effectively % word size of LHS (more defined), + // so skip remaining warnings as we don't want to modify values within Sema. + if (S.getLangOpts().OpenCL) + return; + llvm::APSInt Right; // Check right/shifter operand if (RHS.get()->isValueDependent() || @@ -6689,10 +6875,10 @@ static bool IsWithinTemplateSpecialization(Decl *D) { } /// If two different enums are compared, raise a warning. -static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &LHS, - ExprResult &RHS) { - QualType LHSStrippedType = LHS.get()->IgnoreParenImpCasts()->getType(); - QualType RHSStrippedType = RHS.get()->IgnoreParenImpCasts()->getType(); +static void checkEnumComparison(Sema &S, SourceLocation Loc, Expr *LHS, + Expr *RHS) { + QualType LHSStrippedType = LHS->IgnoreParenImpCasts()->getType(); + QualType RHSStrippedType = RHS->IgnoreParenImpCasts()->getType(); const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>(); if (!LHSEnumType) @@ -6712,7 +6898,7 @@ static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &LHS, S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types) << LHSStrippedType << RHSStrippedType - << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + << LHS->getSourceRange() << RHS->getSourceRange(); } /// \brief Diagnose bad pointer comparisons. @@ -6796,18 +6982,18 @@ static bool isObjCObjectLiteral(ExprResult &E) { } static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { - // Get the LHS object's interface type. - QualType Type = LHS->getType(); - QualType InterfaceType; - if (const ObjCObjectPointerType *PTy = Type->getAs<ObjCObjectPointerType>()) { - InterfaceType = PTy->getPointeeType(); - if (const ObjCObjectType *iQFaceTy = - InterfaceType->getAsObjCQualifiedInterfaceType()) - InterfaceType = iQFaceTy->getBaseType(); - } else { - // If this is not actually an Objective-C object, bail out. + const ObjCObjectPointerType *Type = + LHS->getType()->getAs<ObjCObjectPointerType>(); + + // If this is not actually an Objective-C object, bail out. + if (!Type) return false; - } + + // Get the LHS object's interface type. + QualType InterfaceType = Type->getPointeeType(); + if (const ObjCObjectType *iQFaceTy = + InterfaceType->getAsObjCQualifiedInterfaceType()) + InterfaceType = iQFaceTy->getBaseType(); // If the RHS isn't an Objective-C object, bail out. if (!RHS->getType()->isObjCObjectPointerType()) @@ -6826,8 +7012,7 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { /*warn=*/false); } else { // Check protocols. - Method = S.LookupMethodInQualifiedType(IsEqualSel, - cast<ObjCObjectPointerType>(Type), + Method = S.LookupMethodInQualifiedType(IsEqualSel, Type, /*instance=*/true); } } @@ -6846,6 +7031,48 @@ static bool hasIsEqualMethod(Sema &S, const Expr *LHS, const Expr *RHS) { return true; } +Sema::ObjCLiteralKind Sema::CheckLiteralKind(Expr *FromE) { + FromE = FromE->IgnoreParenImpCasts(); + switch (FromE->getStmtClass()) { + default: + break; + case Stmt::ObjCStringLiteralClass: + // "string literal" + return LK_String; + case Stmt::ObjCArrayLiteralClass: + // "array literal" + return LK_Array; + case Stmt::ObjCDictionaryLiteralClass: + // "dictionary literal" + return LK_Dictionary; + case Stmt::BlockExprClass: + return LK_Block; + case Stmt::ObjCBoxedExprClass: { + Expr *Inner = cast<ObjCBoxedExpr>(FromE)->getSubExpr()->IgnoreParens(); + switch (Inner->getStmtClass()) { + case Stmt::IntegerLiteralClass: + case Stmt::FloatingLiteralClass: + case Stmt::CharacterLiteralClass: + case Stmt::ObjCBoolLiteralExprClass: + case Stmt::CXXBoolLiteralExprClass: + // "numeric literal" + return LK_Numeric; + case Stmt::ImplicitCastExprClass: { + CastKind CK = cast<CastExpr>(Inner)->getCastKind(); + // Boolean literals can be represented by implicit casts. + if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast) + return LK_Numeric; + break; + } + default: + break; + } + return LK_Boxed; + } + } + return LK_None; +} + static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, ExprResult &LHS, ExprResult &RHS, BinaryOperator::Opcode Opc){ @@ -6866,61 +7093,15 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, return; // This should be kept in sync with warn_objc_literal_comparison. - // LK_String should always be last, since it has its own warning flag. - enum { - LK_Array, - LK_Dictionary, - LK_Numeric, - LK_Boxed, - LK_String - } LiteralKind; - - Literal = Literal->IgnoreParenImpCasts(); - switch (Literal->getStmtClass()) { - case Stmt::ObjCStringLiteralClass: - // "string literal" - LiteralKind = LK_String; - break; - case Stmt::ObjCArrayLiteralClass: - // "array literal" - LiteralKind = LK_Array; - break; - case Stmt::ObjCDictionaryLiteralClass: - // "dictionary literal" - LiteralKind = LK_Dictionary; - break; - case Stmt::ObjCBoxedExprClass: { - Expr *Inner = cast<ObjCBoxedExpr>(Literal)->getSubExpr(); - switch (Inner->getStmtClass()) { - case Stmt::IntegerLiteralClass: - case Stmt::FloatingLiteralClass: - case Stmt::CharacterLiteralClass: - case Stmt::ObjCBoolLiteralExprClass: - case Stmt::CXXBoolLiteralExprClass: - // "numeric literal" - LiteralKind = LK_Numeric; - break; - case Stmt::ImplicitCastExprClass: { - CastKind CK = cast<CastExpr>(Inner)->getCastKind(); - // Boolean literals can be represented by implicit casts. - if (CK == CK_IntegralToBoolean || CK == CK_IntegralCast) { - LiteralKind = LK_Numeric; - break; - } - // FALLTHROUGH - } - default: - // "boxed expression" - LiteralKind = LK_Boxed; - break; - } - break; - } - default: + // LK_String should always be after the other literals, since it has its own + // warning flag. + Sema::ObjCLiteralKind LiteralKind = S.CheckLiteralKind(Literal); + assert(LiteralKind != Sema::LK_Block); + if (LiteralKind == Sema::LK_None) { llvm_unreachable("Unknown Objective-C object literal kind"); } - if (LiteralKind == LK_String) + if (LiteralKind == Sema::LK_String) S.Diag(Loc, diag::warn_objc_string_literal_comparison) << Literal->getSourceRange(); else @@ -6931,11 +7112,12 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, hasIsEqualMethod(S, LHS.get(), RHS.get())) { SourceLocation Start = LHS.get()->getLocStart(); SourceLocation End = S.PP.getLocForEndOfToken(RHS.get()->getLocEnd()); - SourceRange OpRange(Loc, S.PP.getLocForEndOfToken(Loc)); + CharSourceRange OpRange = + CharSourceRange::getCharRange(Loc, S.PP.getLocForEndOfToken(Loc)); S.Diag(Loc, diag::note_objc_literal_comparison_isequal) << FixItHint::CreateInsertion(Start, Opc == BO_EQ ? "[" : "![") - << FixItHint::CreateReplacement(OpRange, "isEqual:") + << FixItHint::CreateReplacement(OpRange, " isEqual:") << FixItHint::CreateInsertion(End, "]"); } } @@ -6959,7 +7141,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, Expr *LHSStripped = LHS.get()->IgnoreParenImpCasts(); Expr *RHSStripped = RHS.get()->IgnoreParenImpCasts(); - checkEnumComparison(*this, Loc, LHS, RHS); + checkEnumComparison(*this, Loc, LHS.get(), RHS.get()); if (!LHSType->hasFloatingRepresentation() && !(LHSType->isBlockPointerType() && IsRelational) && @@ -7109,7 +7291,7 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) && !LHSIsNull && !RHSIsNull) { diagnoseFunctionPointerToVoidComparison( - *this, Loc, LHS, RHS, /*isError*/ isSFINAEContext()); + *this, Loc, LHS, RHS, /*isError*/ (bool)isSFINAEContext()); if (isSFINAEContext()) return QualType(); @@ -7396,7 +7578,10 @@ QualType Sema::CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, // Ensure that either both operands are of the same vector type, or // one operand is of a vector type and the other is of its element type. QualType vType = CheckVectorOperands(LHS, RHS, Loc, false); - if (vType.isNull() || vType->isFloatingType()) + if (vType.isNull()) + return InvalidOperands(Loc, LHS, RHS); + if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 && + vType->hasFloatingRepresentation()) return InvalidOperands(Loc, LHS, RHS); return GetSignedVectorType(LHS.get()->getType()); @@ -7472,8 +7657,17 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] RHS.get()->getLocEnd())); } } - + if (!Context.getLangOpts().CPlusPlus) { + // OpenCL v1.1 s6.3.g: The logical operators and (&&), or (||) do + // not operate on the built-in scalar and vector float types. + if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + if (LHS.get()->getType()->isFloatingType() || + RHS.get()->getType()->isFloatingType()) + return InvalidOperands(Loc, LHS, RHS); + } + LHS = UsualUnaryConversions(LHS.take()); if (LHS.isInvalid()) return QualType(); @@ -7999,7 +8193,9 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){ if (PTy->getKind() == BuiltinType::Overload) { if (!isa<OverloadExpr>(OrigOp.get()->IgnoreParens())) { - S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) + assert(cast<UnaryOperator>(OrigOp.get()->IgnoreParens())->getOpcode() + == UO_AddrOf); + S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof_addrof_function) << OrigOp.get()->getSourceRange(); return QualType(); } @@ -8043,10 +8239,10 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, Expr::LValueClassification lval = op->ClassifyLValue(S.Context); unsigned AddressOfError = AO_No_Error; - 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) + if (lval == Expr::LV_ClassTemporary || lval == Expr::LV_ArrayTemporary) { + bool sfinae = (bool)S.isSFINAEContext(); + S.Diag(OpLoc, S.isSFINAEContext() ? diag::err_typecheck_addrof_temporary + : diag::ext_typecheck_addrof_temporary) << op->getType() << op->getSourceRange(); if (sfinae) return QualType(); @@ -8094,9 +8290,8 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, if (isa<PseudoObjectExpr>(op)) { AddressOfError = AO_Property_Expansion; } else { - // FIXME: emit more specific diag... S.Diag(OpLoc, diag::err_typecheck_invalid_lvalue_addrof) - << op->getSourceRange(); + << op->getType() << op->getSourceRange(); return QualType(); } } @@ -8312,7 +8507,7 @@ static void DiagnoseSelfAssignment(Sema &S, Expr *LHSExpr, Expr *RHSExpr, ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr) { - if (getLangOpts().CPlusPlus0x && isa<InitListExpr>(RHSExpr)) { + if (getLangOpts().CPlusPlus11 && isa<InitListExpr>(RHSExpr)) { // The syntax only allows initializer lists on the RHS of assignment, // so we don't need to worry about accepting invalid code for // non-assignment operators. @@ -8445,6 +8640,24 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, CheckArrayAccess(LHS.get()); CheckArrayAccess(RHS.get()); + if (const ObjCIsaExpr *OISA = dyn_cast<ObjCIsaExpr>(LHS.get()->IgnoreParenCasts())) { + NamedDecl *ObjectSetClass = LookupSingleName(TUScope, + &Context.Idents.get("object_setClass"), + SourceLocation(), LookupOrdinaryName); + if (ObjectSetClass && isa<ObjCIsaExpr>(LHS.get())) { + SourceLocation RHSLocEnd = PP.getLocForEndOfToken(RHS.get()->getLocEnd()); + Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign) << + FixItHint::CreateInsertion(LHS.get()->getLocStart(), "object_setClass(") << + FixItHint::CreateReplacement(SourceRange(OISA->getOpLoc(), OpLoc), ",") << + FixItHint::CreateInsertion(RHSLocEnd, ")"); + } + else + Diag(LHS.get()->getExprLoc(), diag::warn_objc_isa_assign); + } + else if (const ObjCIvarRefExpr *OIRE = + dyn_cast<ObjCIvarRefExpr>(LHS.get()->IgnoreParenCasts())) + DiagnoseDirectIsaAccess(*this, OIRE, OpLoc, RHS.get()); + if (CompResultTy.isNull()) return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc, ResultTy, VK, OK, OpLoc, @@ -8467,46 +8680,38 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, SourceLocation OpLoc, Expr *LHSExpr, Expr *RHSExpr) { - typedef BinaryOperator BinOp; - BinOp::Opcode LHSopc = static_cast<BinOp::Opcode>(-1), - RHSopc = static_cast<BinOp::Opcode>(-1); - if (BinOp *BO = dyn_cast<BinOp>(LHSExpr)) - LHSopc = BO->getOpcode(); - if (BinOp *BO = dyn_cast<BinOp>(RHSExpr)) - RHSopc = BO->getOpcode(); - - // Subs are not binary operators. - if (LHSopc == -1 && RHSopc == -1) + BinaryOperator *LHSBO = dyn_cast<BinaryOperator>(LHSExpr); + BinaryOperator *RHSBO = dyn_cast<BinaryOperator>(RHSExpr); + + // Check that one of the sides is a comparison operator. + bool isLeftComp = LHSBO && LHSBO->isComparisonOp(); + bool isRightComp = RHSBO && RHSBO->isComparisonOp(); + if (!isLeftComp && !isRightComp) 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))) + bool isLeftBitwise = LHSBO && LHSBO->isBitwiseOp(); + bool isRightBitwise = RHSBO && RHSBO->isBitwiseOp(); + if ((isLeftComp || isLeftBitwise) && (isRightComp || isRightBitwise)) return; - bool isLeftComp = BinOp::isComparisonOp(LHSopc); - bool isRightComp = BinOp::isComparisonOp(RHSopc); - if (!isLeftComp && !isRightComp) return; - SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(), OpLoc) : SourceRange(OpLoc, RHSExpr->getLocEnd()); - StringRef OpStr = isLeftComp ? BinOp::getOpcodeStr(LHSopc) - : BinOp::getOpcodeStr(RHSopc); + StringRef OpStr = isLeftComp ? LHSBO->getOpcodeStr() : RHSBO->getOpcodeStr(); SourceRange ParensRange = isLeftComp ? - SourceRange(cast<BinOp>(LHSExpr)->getRHS()->getLocStart(), - RHSExpr->getLocEnd()) - : SourceRange(LHSExpr->getLocStart(), - cast<BinOp>(RHSExpr)->getLHS()->getLocStart()); + SourceRange(LHSBO->getRHS()->getLocStart(), RHSExpr->getLocEnd()) + : SourceRange(LHSExpr->getLocStart(), RHSBO->getLHS()->getLocStart()); Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) - << DiagRange << BinOp::getOpcodeStr(Opc) << OpStr; + << DiagRange << BinaryOperator::getOpcodeStr(Opc) << OpStr; SuggestParentheses(Self, OpLoc, Self.PDiag(diag::note_precedence_silence) << OpStr, (isLeftComp ? LHSExpr : RHSExpr)->getSourceRange()); SuggestParentheses(Self, OpLoc, - Self.PDiag(diag::note_precedence_bitwise_first) << BinOp::getOpcodeStr(Opc), + Self.PDiag(diag::note_precedence_bitwise_first) + << BinaryOperator::getOpcodeStr(Opc), ParensRange); } @@ -8806,7 +9011,8 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, case UO_Not: // bitwise complement Input = UsualUnaryConversions(Input.take()); - if (Input.isInvalid()) return ExprError(); + if (Input.isInvalid()) + return ExprError(); resultType = Input.get()->getType(); if (resultType->isDependentType()) break; @@ -8814,12 +9020,22 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, if (resultType->isComplexType() || resultType->isComplexIntegerType()) // C99 does not support '~' for complex conjugation. Diag(OpLoc, diag::ext_integer_complement_complex) - << resultType << Input.get()->getSourceRange(); + << resultType << Input.get()->getSourceRange(); else if (resultType->hasIntegerRepresentation()) break; - else { + else if (resultType->isExtVectorType()) { + if (Context.getLangOpts().OpenCL) { + // OpenCL v1.1 s6.3.f: The bitwise operator not (~) does not operate + // on vector float types. + QualType T = resultType->getAs<ExtVectorType>()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + break; + } else { return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) - << resultType << Input.get()->getSourceRange()); + << resultType << Input.get()->getSourceRange()); } break; @@ -8830,7 +9046,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType = Input.get()->getType(); // Though we still have to promote half FP to float... - if (resultType->isHalfType()) { + if (resultType->isHalfType() && !Context.getLangOpts().NativeHalfType) { Input = ImpCastExprToType(Input.take(), Context.FloatTy, CK_FloatingCast).take(); resultType = Context.FloatTy; } @@ -8844,8 +9060,24 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, // operand contextually converted to bool. Input = ImpCastExprToType(Input.take(), Context.BoolTy, ScalarTypeToBooleanCastKind(resultType)); + } else if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on scalar float types. + if (!resultType->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); } } else if (resultType->isExtVectorType()) { + if (Context.getLangOpts().OpenCL && + Context.getLangOpts().OpenCLVersion < 120) { + // OpenCL v1.1 6.3.h: The logical operator not (!) does not + // operate on vector float types. + QualType T = resultType->getAs<ExtVectorType>()->getElementType(); + if (!T->isIntegerType()) + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } // Vector logical not returns the signed variant of the operand type. resultType = GetSignedVectorType(resultType); break; @@ -9210,9 +9442,9 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, // If type is not a standard-layout class (Clause 9), the results are // undefined. if (CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) { - bool IsSafe = LangOpts.CPlusPlus0x? CRD->isStandardLayout() : CRD->isPOD(); + bool IsSafe = LangOpts.CPlusPlus11? CRD->isStandardLayout() : CRD->isPOD(); unsigned DiagID = - LangOpts.CPlusPlus0x? diag::warn_offsetof_non_standardlayout_type + LangOpts.CPlusPlus11? diag::warn_offsetof_non_standardlayout_type : diag::warn_offsetof_non_pod_type; if (!IsSafe && !DidWarnAboutNonPOD && @@ -9379,8 +9611,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, FunctionProtoType::ExtProtoInfo EPI; EPI.HasTrailingReturn = false; EPI.TypeQuals |= DeclSpec::TQ_const; - T = Context.getFunctionType(Context.DependentTy, /*Args=*/0, /*NumArgs=*/0, - EPI); + T = Context.getFunctionType(Context.DependentTy, ArrayRef<QualType>(), EPI); Sig = Context.getTrivialTypeSourceInfo(T); } @@ -9394,8 +9625,7 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, FunctionProtoTypeLoc ExplicitSignature; TypeLoc tmp = Sig->getTypeLoc().IgnoreParens(); - if (isa<FunctionProtoTypeLoc>(tmp)) { - ExplicitSignature = cast<FunctionProtoTypeLoc>(tmp); + if ((ExplicitSignature = tmp.getAs<FunctionProtoTypeLoc>())) { // Check whether that explicit signature was synthesized by // GetTypeForDeclarator. If so, don't save that as part of the @@ -9560,7 +9790,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (isa<FunctionNoProtoType>(FTy)) { FunctionProtoType::ExtProtoInfo EPI; EPI.ExtInfo = Ext; - BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); + BlockTy = Context.getFunctionType(RetTy, ArrayRef<QualType>(), EPI); // Otherwise, if we don't need to change anything about the function type, // preserve its sugar structure. @@ -9574,17 +9804,18 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.TypeQuals = 0; // FIXME: silently? EPI.ExtInfo = Ext; - BlockTy = Context.getFunctionType(RetTy, - FPT->arg_type_begin(), - FPT->getNumArgs(), - EPI); + BlockTy = + Context.getFunctionType(RetTy, + ArrayRef<QualType>(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().withNoReturn(NoReturn); - BlockTy = Context.getFunctionType(RetTy, 0, 0, EPI); + BlockTy = Context.getFunctionType(RetTy, ArrayRef<QualType>(), EPI); } DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), @@ -9715,11 +9946,11 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, if (TInfo->getType()->isSpecificBuiltinType(BuiltinType::Float)) PromoteType = Context.DoubleTy; if (!PromoteType.isNull()) - Diag(TInfo->getTypeLoc().getBeginLoc(), - diag::warn_second_parameter_to_va_arg_never_compatible) - << TInfo->getType() - << PromoteType - << TInfo->getTypeLoc().getSourceRange(); + DiagRuntimeBehavior(TInfo->getTypeLoc().getBeginLoc(), E, + PDiag(diag::warn_second_parameter_to_va_arg_never_compatible) + << TInfo->getType() + << PromoteType + << TInfo->getTypeLoc().getSourceRange()); } QualType T = TInfo->getType().getNonLValueExprType(Context); @@ -9932,6 +10163,9 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, if (CheckInferredResultType) EmitRelatedResultTypeNote(SrcExpr); + + if (Action == AA_Returning && ConvTy == IncompatiblePointer) + EmitRelatedResultTypeNoteForReturn(DstType); if (Complained) *Complained = true; @@ -9980,7 +10214,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, bool AllowFold) { SourceLocation DiagLoc = E->getLocStart(); - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { // C++11 [expr.const]p5: // If an expression of literal class type is used in a context where an // integral constant expression is required, then that class type shall @@ -10107,14 +10341,14 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, // Circumvent ICE checking in C++11 to avoid evaluating the expression twice // in the non-ICE case. - if (!getLangOpts().CPlusPlus0x && E->isIntegerConstantExpr(Context)) { + if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) { if (Result) *Result = E->EvaluateKnownConstInt(Context); return Owned(E); } Expr::EvalResult EvalResult; - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; EvalResult.Diag = &Notes; // Try to evaluate the expression, and produce diagnostics explaining why it's @@ -10125,7 +10359,7 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, // In C++11, we can rely on diagnostics being produced for any expression // which is not a constant expression. If no diagnostics were produced, then // this is a constant expression. - if (Folded && getLangOpts().CPlusPlus0x && Notes.empty()) { + if (Folded && getLangOpts().CPlusPlus11 && Notes.empty()) { if (Result) *Result = EvalResult.Val.getInt(); return Owned(E); @@ -10211,7 +10445,7 @@ namespace { }; } -ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) { +ExprResult Sema::TransformToPotentiallyEvaluated(Expr *E) { assert(ExprEvalContexts.back().Context == Unevaluated && "Should only transform unevaluated expressions"); ExprEvalContexts.back().Context = @@ -10302,7 +10536,7 @@ void Sema::DiscardCleanupsInEvaluationContext() { ExprResult Sema::HandleExprEvaluationContextForTypeof(Expr *E) { if (!E->getType()->isVariablyModifiedType()) return E; - return TranformToPotentiallyEvaluated(E); + return TransformToPotentiallyEvaluated(E); } static bool IsPotentiallyEvaluatedContext(Sema &SemaRef) { @@ -10395,6 +10629,9 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { if (!Constructor->isUsed(false)) DefineImplicitMoveConstructor(Loc, Constructor); } + } else if (Constructor->getInheritedConstructor()) { + if (!Constructor->isUsed(false)) + DefineInheritingConstructor(Loc, Constructor); } MarkVTableUsed(Loc, Constructor->getParent()); @@ -10488,13 +10725,26 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { } // Keep track of used but undefined functions. - if (!Func->isPure() && !Func->hasBody() && - Func->getLinkage() != ExternalLinkage) { - SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()]; - if (old.isInvalid()) old = Loc; + if (!Func->isDefined()) { + if (mightHaveNonExternalLinkage(Func)) + UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc)); + else if (Func->getMostRecentDecl()->isInlined() && + (LangOpts.CPlusPlus || !LangOpts.GNUInline) && + !Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>()) + UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc)); + } + + // Normally the must current decl is marked used while processing the use and + // any subsequent decls are marked used by decl merging. This fails with + // template instantiation since marking can happen at the end of the file + // and, because of the two phase lookup, this function is called with at + // decl in the middle of a decl chain. We loop to maintain the invariant + // that once a decl is used, all decls after it are also used. + for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) { + F->setUsed(true); + if (F == Func) + break; } - - Func->setUsed(true); } static void @@ -10572,7 +10822,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, // Introduce a new evaluation context for the initialization, so // that temporaries introduced as part of the capture are retained // to be re-"exported" from the lambda expression itself. - S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); + EnterExpressionEvaluationContext scope(S, Sema::PotentiallyEvaluated); // C++ [expr.prim.labda]p12: // An entity captured by a lambda-expression is odr-used (3.2) in @@ -10604,7 +10854,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, IterationVarName, SizeType, S.Context.getTrivialTypeSourceInfo(SizeType, Loc), - SC_None, SC_None); + SC_None); IndexVariables.push_back(IterationVar); LSI->ArrayIndexVars.push_back(IterationVar); @@ -10623,7 +10873,6 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, if (Subscript.isInvalid()) { S.CleanupVarDeclMarking(); S.DiscardCleanupsInEvaluationContext(); - S.PopExpressionEvaluationContext(); return ExprError(); } @@ -10659,7 +10908,6 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, // Exit the expression evaluation context used for the capture. S.CleanupVarDeclMarking(); S.DiscardCleanupsInEvaluationContext(); - S.PopExpressionEvaluationContext(); return Result; } @@ -10748,7 +10996,22 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, } return true; } - + // Prohibit structs with flexible array members too. + // We cannot capture what is in the tail end of the struct. + if (const RecordType *VTTy = Var->getType()->getAs<RecordType>()) { + if (VTTy->getDecl()->hasFlexibleArrayMember()) { + if (BuildAndDiagnose) { + if (IsBlock) + Diag(Loc, diag::err_ref_flexarray_type); + else + Diag(Loc, diag::err_lambda_capture_flexarray_type) + << Var->getDeclName(); + Diag(Var->getLocation(), diag::note_previous_decl) + << Var->getDeclName(); + } + return true; + } + } // Lambdas are not allowed to capture __block variables; they don't // support the expected semantics. if (IsLambda && HasBlocksAttr) { @@ -10830,13 +11093,18 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, // actually requires the destructor. if (isa<ParmVarDecl>(Var)) FinalizeVarWithDestructor(Var, Record); - + + // Enter a new evaluation context to insulate the copy + // full-expression. + EnterExpressionEvaluationContext scope(*this, PotentiallyEvaluated); + // 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. - Expr *DeclRef = new (Context) DeclRefExpr(Var, false, + Expr *DeclRef = new (Context) DeclRefExpr(Var, Nested, DeclRefType.withConst(), VK_LValue, Loc); + ExprResult Result = PerformCopyInitialization( InitializedEntity::InitializeBlock(Var->getLocation(), @@ -10921,7 +11189,7 @@ bool Sema::tryCaptureVariable(VarDecl *Var, SourceLocation Loc, if (BuildAndDiagnose) { ExprResult Result = captureInLambda(*this, LSI, Var, CaptureType, DeclRefType, Loc, - I == N-1); + Nested); if (!Result.isInvalid()) CopyExpr = Result.take(); } @@ -10978,7 +11246,7 @@ static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var, if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly && Var->getLinkage() != ExternalLinkage && !(Var->isStaticDataMember() && Var->hasInit())) { - SourceLocation &old = SemaRef.UndefinedInternals[Var->getCanonicalDecl()]; + SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()]; if (old.isInvalid()) old = Loc; } @@ -11090,13 +11358,13 @@ void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { } static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, - Decl *D, Expr *E) { + Decl *D, Expr *E, bool OdrUse) { if (VarDecl *Var = dyn_cast<VarDecl>(D)) { DoMarkVarDeclReferenced(SemaRef, Loc, Var, E); return; } - SemaRef.MarkAnyDeclReferenced(Loc, D); + SemaRef.MarkAnyDeclReferenced(Loc, D, OdrUse); // If this is a call to a method via a cast, also mark the method in the // derived class used in case codegen can devirtualize the call. @@ -11111,32 +11379,58 @@ static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, if (!MostDerivedClassDecl) return; CXXMethodDecl *DM = MD->getCorrespondingMethodInClass(MostDerivedClassDecl); - if (!DM) + if (!DM || DM->isPure()) return; - SemaRef.MarkAnyDeclReferenced(Loc, DM); + SemaRef.MarkAnyDeclReferenced(Loc, DM, OdrUse); } /// \brief Perform reference-marking and odr-use handling for a DeclRefExpr. void Sema::MarkDeclRefReferenced(DeclRefExpr *E) { - MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E); + // TODO: update this with DR# once a defect report is filed. + // C++11 defect. The address of a pure member should not be an ODR use, even + // if it's a qualified reference. + bool OdrUse = true; + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getDecl())) + if (Method->isVirtual()) + OdrUse = false; + MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse); } /// \brief Perform reference-marking and odr-use handling for a MemberExpr. void Sema::MarkMemberReferenced(MemberExpr *E) { - MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E); + // C++11 [basic.def.odr]p2: + // A non-overloaded function whose name appears as a potentially-evaluated + // expression or a member of a set of candidate functions, if selected by + // overload resolution when referred to from a potentially-evaluated + // expression, is odr-used, unless it is a pure virtual function and its + // name is not explicitly qualified. + bool OdrUse = true; + if (!E->hasQualifier()) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) + if (Method->isPure()) + OdrUse = false; + } + SourceLocation Loc = E->getMemberLoc().isValid() ? + E->getMemberLoc() : E->getLocStart(); + MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, OdrUse); } /// \brief Perform marking for a reference to an arbitrary declaration. It /// marks the declaration referenced, and performs odr-use checking for functions /// and variables. This method should not be used when building an normal /// expression which refers to a variable. -void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) { - if (VarDecl *VD = dyn_cast<VarDecl>(D)) - MarkVariableReferenced(Loc, VD); - else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - MarkFunctionReferenced(Loc, FD); - else - D->setReferenced(); +void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse) { + if (OdrUse) { + if (VarDecl *VD = dyn_cast<VarDecl>(D)) { + MarkVariableReferenced(Loc, VD); + return; + } + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + MarkFunctionReferenced(Loc, FD); + return; + } + } + D->setReferenced(); } namespace { @@ -11161,7 +11455,7 @@ bool MarkReferencedDecls::TraverseTemplateArgument( const TemplateArgument &Arg) { if (Arg.getKind() == TemplateArgument::Declaration) { if (Decl *D = Arg.getAsDecl()) - S.MarkAnyDeclReferenced(Loc, D); + S.MarkAnyDeclReferenced(Loc, D, true); } return Inherited::TraverseTemplateArgument(Arg); @@ -11685,10 +11979,11 @@ ExprResult RebuildUnknownAnyExpr::VisitCallExpr(CallExpr *E) { // 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()); + DestType = + S.Context.getFunctionType(DestType, + ArrayRef<QualType>(Proto->arg_type_begin(), + Proto->getNumArgs()), + Proto->getExtProtoInfo()); else DestType = S.Context.getFunctionNoProtoType(DestType, FnType->getExtInfo()); @@ -11850,6 +12145,29 @@ ExprResult Sema::forceUnknownAnyToType(Expr *E, QualType ToType) { return RebuildUnknownAnyExpr(*this, ToType).Visit(E); } +ExprResult Sema::checkUnknownAnyArg(SourceLocation callLoc, + Expr *arg, QualType ¶mType) { + // If the syntactic form of the argument is not an explicit cast of + // any sort, just do default argument promotion. + ExplicitCastExpr *castArg = dyn_cast<ExplicitCastExpr>(arg->IgnoreParens()); + if (!castArg) { + ExprResult result = DefaultArgumentPromotion(arg); + if (result.isInvalid()) return ExprError(); + paramType = result.get()->getType(); + return result; + } + + // Otherwise, use the type that was written in the explicit cast. + assert(!arg->hasPlaceholderType()); + paramType = castArg->getTypeAsWritten(); + + // Copy-initialize a parameter of that type. + InitializedEntity entity = + InitializedEntity::InitializeParameter(Context, paramType, + /*consumed*/ false); + return PerformCopyInitialization(entity, callLoc, Owned(arg)); +} + static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { Expr *orig = E; unsigned diagID = diag::err_uncasted_use_of_unknown_any; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 0919bc5..3f2cb02 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -13,30 +13,68 @@ //===----------------------------------------------------------------------===// #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 "TypeLocBuilder.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/EvaluatedExprVisitor.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 "TypeLocBuilder.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; using namespace sema; +/// \brief Handle the result of the special case name lookup for inheriting +/// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as +/// constructor names in member using declarations, even if 'X' is not the +/// name of the corresponding type. +ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, + SourceLocation NameLoc, + IdentifierInfo &Name) { + NestedNameSpecifier *NNS = SS.getScopeRep(); + + // Convert the nested-name-specifier into a type. + QualType Type; + switch (NNS->getKind()) { + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: + Type = QualType(NNS->getAsType(), 0); + break; + + case NestedNameSpecifier::Identifier: + // Strip off the last layer of the nested-name-specifier and build a + // typename type for it. + assert(NNS->getAsIdentifier() == &Name && "not a constructor name"); + Type = Context.getDependentNameType(ETK_None, NNS->getPrefix(), + NNS->getAsIdentifier()); + break; + + case NestedNameSpecifier::Global: + case NestedNameSpecifier::Namespace: + case NestedNameSpecifier::NamespaceAlias: + llvm_unreachable("Nested name specifier is not a type for inheriting ctor"); + } + + // This reference to the type is located entirely at the location of the + // final identifier in the qualified-id. + return CreateParsedType(Type, + Context.getTrivialTypeSourceInfo(Type, NameLoc)); +} + ParsedType Sema::getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, @@ -263,8 +301,16 @@ ParsedType Sema::getDestructorName(SourceLocation TildeLoc, } else if (ObjectTypePtr) Diag(NameLoc, diag::err_ident_in_dtor_not_a_type) << &II; - else - Diag(NameLoc, diag::err_destructor_class_name); + else { + SemaDiagnosticBuilder DtorDiag = Diag(NameLoc, + diag::err_destructor_class_name); + if (S) { + const DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity()); + if (const CXXRecordDecl *Class = dyn_cast_or_null<CXXRecordDecl>(Ctx)) + DtorDiag << FixItHint::CreateReplacement(SourceRange(NameLoc), + Class->getNameAsString()); + } + } return ParsedType(); } @@ -336,7 +382,7 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, if (RecordD->isPolymorphic() && E->isGLValue()) { // The subexpression is potentially evaluated; switch the context // and recheck the subexpression. - ExprResult Result = TranformToPotentiallyEvaluated(E); + ExprResult Result = TransformToPotentiallyEvaluated(E); if (Result.isInvalid()) return ExprError(); E = Result.take(); @@ -1041,13 +1087,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } else if (Initializer && isa<InitListExpr>(Initializer)) initStyle = CXXNewExpr::ListInit; else { - // In template instantiation, the initializer could be a CXXDefaultArgExpr - // unwrapped from a CXXConstructExpr that was implicitly built. There is no - // particularly sane way we can handle this (especially since it can even - // occur for array new), so we throw the initializer away and have it be - // rebuilt. - if (Initializer && isa<CXXDefaultArgExpr>(Initializer)) - Initializer = 0; assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) || isa<CXXConstructExpr>(Initializer)) && "Initializer expression that cannot have been implicitly created."); @@ -1056,20 +1095,20 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, Expr **Inits = &Initializer; unsigned NumInits = Initializer ? 1 : 0; - if (initStyle == CXXNewExpr::CallInit) { - if (ParenListExpr *List = dyn_cast<ParenListExpr>(Initializer)) { - Inits = List->getExprs(); - NumInits = List->getNumExprs(); - } else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Initializer)){ - if (!isa<CXXTemporaryObjectExpr>(CCE)) { - // Can happen in template instantiation. Since this is just an implicit - // construction, we just take it apart and rebuild it. - Inits = CCE->getArgs(); - NumInits = CCE->getNumArgs(); - } - } + if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) { + assert(initStyle == CXXNewExpr::CallInit && "paren init for non-call init"); + Inits = List->getExprs(); + NumInits = List->getNumExprs(); } + // Determine whether we've already built the initializer. + bool HaveCompleteInit = false; + if (Initializer && isa<CXXConstructExpr>(Initializer) && + !isa<CXXTemporaryObjectExpr>(Initializer)) + HaveCompleteInit = true; + else if (Initializer && isa<ImplicitValueInitExpr>(Initializer)) + HaveCompleteInit = true; + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. AutoType *AT = 0; if (TypeMayContainAuto && @@ -1147,7 +1186,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, virtual DiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) { return S.Diag(Loc, diag::err_array_size_not_integral) - << S.getLangOpts().CPlusPlus0x << T; + << S.getLangOpts().CPlusPlus11 << T; } virtual DiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, @@ -1185,7 +1224,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, QualType T, QualType ConvTy) { return S.Diag(Loc, - S.getLangOpts().CPlusPlus0x + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_array_size_conversion : diag::ext_array_size_conversion) << T << ConvTy->isEnumeralType() << ConvTy; @@ -1221,7 +1260,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, if (Value < llvm::APSInt( llvm::APInt::getNullValue(Value.getBitWidth()), Value.isUnsigned())) { - if (getLangOpts().CPlusPlus0x) + if (getLangOpts().CPlusPlus11) Diag(ArraySize->getLocStart(), diag::warn_typecheck_negative_array_new_size) << ArraySize->getSourceRange(); @@ -1233,7 +1272,7 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) { - if (getLangOpts().CPlusPlus0x) + if (getLangOpts().CPlusPlus11) Diag(ArraySize->getLocStart(), diag::warn_array_new_too_large) << Value.toString(10) @@ -1341,9 +1380,12 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } } + // If we can perform the initialization, and we've not already done so, + // do it now. if (!AllocType->isDependentType() && !Expr::hasAnyTypeDependentArguments( - llvm::makeArrayRef(Inits, NumInits))) { + llvm::makeArrayRef(Inits, NumInits)) && + !HaveCompleteInit) { // C++11 [expr.new]p15: // A new-expression that creates an object of type T initializes that // object as follows: @@ -1379,10 +1421,14 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, } // Mark the new and delete operators as referenced. - if (OperatorNew) + if (OperatorNew) { + DiagnoseUseOfDecl(OperatorNew, StartLoc); MarkFunctionReferenced(StartLoc, OperatorNew); - if (OperatorDelete) + } + if (OperatorDelete) { + DiagnoseUseOfDecl(OperatorDelete, StartLoc); MarkFunctionReferenced(StartLoc, OperatorDelete); + } // C++0x [expr.new]p17: // If the new expression creates an array of objects of class type, @@ -1594,8 +1640,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, EPI.Variadic = Proto->isVariadic(); ExpectedFunctionType - = Context.getFunctionType(Context.VoidTy, ArgTypes.data(), - ArgTypes.size(), EPI); + = Context.getFunctionType(Context.VoidTy, ArgTypes, EPI); } for (LookupResult::iterator D = FoundDelete.begin(), @@ -1641,7 +1686,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // as a placement deallocation function, would have been // selected as a match for the allocation function, the program // is ill-formed. - if (NumPlaceArgs && getLangOpts().CPlusPlus0x && + if (NumPlaceArgs && getLangOpts().CPlusPlus11 && isNonPlacementDeallocationFunction(OperatorDelete)) { Diag(StartLoc, diag::err_placement_new_non_placement_delete) << SourceRange(PlaceArgs[0]->getLocStart(), @@ -1817,7 +1862,7 @@ void Sema::DeclareGlobalNewDelete() { // lookup. // Note that the C++0x versions of operator delete are deallocation functions, // and thus are implicitly noexcept. - if (!StdBadAlloc && !getLangOpts().CPlusPlus0x) { + if (!StdBadAlloc && !getLangOpts().CPlusPlus11) { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, @@ -1857,8 +1902,8 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // Check if this function is already declared. { - DeclContext::lookup_iterator Alloc, AllocEnd; - for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name); + DeclContext::lookup_result R = GlobalCtx->lookup(Name); + for (DeclContext::lookup_iterator Alloc = R.begin(), AllocEnd = R.end(); Alloc != AllocEnd; ++Alloc) { // Only look at non-template functions, as it is the predefined, // non-templated allocation function we are trying to declare here. @@ -1880,29 +1925,28 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, bool HasBadAllocExceptionSpec = (Name.getCXXOverloadedOperator() == OO_New || Name.getCXXOverloadedOperator() == OO_Array_New); - if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus0x) { + if (HasBadAllocExceptionSpec && !getLangOpts().CPlusPlus11) { assert(StdBadAlloc && "Must have std::bad_alloc declared"); BadAllocType = Context.getTypeDeclType(getStdBadAlloc()); } FunctionProtoType::ExtProtoInfo EPI; if (HasBadAllocExceptionSpec) { - if (!getLangOpts().CPlusPlus0x) { + if (!getLangOpts().CPlusPlus11) { EPI.ExceptionSpecType = EST_Dynamic; EPI.NumExceptions = 1; EPI.Exceptions = &BadAllocType; } } else { - EPI.ExceptionSpecType = getLangOpts().CPlusPlus0x ? + EPI.ExceptionSpecType = getLangOpts().CPlusPlus11 ? EST_BasicNoexcept : EST_DynamicNone; } - QualType FnType = Context.getFunctionType(Return, &Argument, 1, EPI); + QualType FnType = Context.getFunctionType(Return, Argument, EPI); FunctionDecl *Alloc = FunctionDecl::Create(Context, GlobalCtx, SourceLocation(), SourceLocation(), Name, - FnType, /*TInfo=*/0, SC_None, - SC_None, false, true); + FnType, /*TInfo=*/0, SC_None, false, true); Alloc->setImplicit(); if (AddMallocAttr) @@ -1911,7 +1955,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), SourceLocation(), 0, Argument, /*TInfo=*/0, - SC_None, SC_None, 0); + SC_None, 0); Alloc->setParams(Param); // FIXME: Also add this declaration to the IdentifierResolver, but @@ -2030,6 +2074,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, if (!Ex.get()->isTypeDependent()) { // Perform lvalue-to-rvalue cast, if needed. Ex = DefaultLvalueConversion(Ex.take()); + if (Ex.isInvalid()) + return ExprError(); QualType Type = Ex.get()->getType(); @@ -2041,9 +2087,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, 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) { + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = RD->getVisibleConversionFunctions(); + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = I.getDecl(); if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); @@ -2323,11 +2371,11 @@ static ExprResult BuildCXXCastArgument(Sema &S, S.CheckConstructorAccess(CastLoc, Constructor, InitializedEntity::InitializeTemporary(Ty), Constructor->getAccess()); - + ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method), - ConstructorArgs, - HadMultipleCandidates, /*ZeroInit*/ false, + ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); if (Result.isInvalid()) return ExprError(); @@ -2479,14 +2527,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, ToType, SCS.CopyConstructor, ConstructorArgs, /*HadMultipleCandidates*/ false, - /*ZeroInit*/ false, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, From, /*HadMultipleCandidates*/ false, - /*ZeroInit*/ false, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); } @@ -2782,6 +2830,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; } + case ICK_Zero_Event_Conversion: + From = ImpCastExprToType(From, ToType, + CK_ZeroToOCLEvent, + From->getValueKind()).take(); + break; + case ICK_Lvalue_To_Rvalue: case ICK_Array_To_Pointer: case ICK_Function_To_Pointer: @@ -2920,10 +2974,13 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, // type due to the overarching C++0x type predicates being implemented // requiring the complete type. case UTT_HasNothrowAssign: + case UTT_HasNothrowMoveAssign: case UTT_HasNothrowConstructor: case UTT_HasNothrowCopy: case UTT_HasTrivialAssign: + case UTT_HasTrivialMoveAssign: case UTT_HasTrivialDefaultConstructor: + case UTT_HasTrivialMoveConstructor: case UTT_HasTrivialCopy: case UTT_HasTrivialDestructor: case UTT_HasVirtualDestructor: @@ -2942,6 +2999,42 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, llvm_unreachable("Type trait not handled by switch"); } +static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op, + Sema &Self, SourceLocation KeyLoc, ASTContext &C, + bool (CXXRecordDecl::*HasTrivial)() const, + bool (CXXRecordDecl::*HasNonTrivial)() const, + bool (CXXMethodDecl::*IsDesiredOp)() const) +{ + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)()) + return true; + + DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op); + DeclarationNameInfo NameInfo(Name, KeyLoc); + LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName); + if (Self.LookupQualifiedName(Res, RD)) { + bool FoundOperator = false; + Res.suppressDiagnostics(); + for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end(); + Op != OpEnd; ++Op) { + if (isa<FunctionTemplateDecl>(*Op)) + continue; + + CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op); + if((Operator->*IsDesiredOp)()) { + FoundOperator = true; + const FunctionProtoType *CPT = + Operator->getType()->getAs<FunctionProtoType>(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT || !CPT->isNothrow(Self.Context)) + return false; + } + } + return FoundOperator; + } + return false; +} + static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, SourceLocation KeyLoc, QualType T) { assert(!T->isDependentType() && "Cannot evaluate traits of dependent type"); @@ -3060,6 +3153,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // // 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 + // + // Note that these builtins do not behave as documented in g++: if a class + // has both a trivial and a non-trivial special member of a particular kind, + // they return false! For now, we emulate this behavior. + // FIXME: This appears to be a g++ bug: more complex cases reveal that it + // does not correctly compute triviality in the presence of multiple special + // members of the same kind. Revisit this once the g++ bug is fixed. 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 @@ -3067,9 +3167,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // constructor ([class.ctor]) then the trait is true, else it is false. if (T.isPODType(Self.Context)) return true; - if (const RecordType *RT = - C.getBaseElementType(T)->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDefaultConstructor(); + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialDefaultConstructor() && + !RD->hasNonTrivialDefaultConstructor(); + return false; + case UTT_HasTrivialMoveConstructor: + // This trait is implemented by MSVC 2012 and needed to parse the + // standard library headers. Specifically this is used as the logic + // behind std::is_trivially_move_constructible (20.9.4.3). + if (T.isPODType(Self.Context)) + return true; + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialMoveConstructor() && !RD->hasNonTrivialMoveConstructor(); return false; case UTT_HasTrivialCopy: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3079,8 +3188,18 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // is true, else it is false. if (T.isPODType(Self.Context) || T->isReferenceType()) return true; - if (const RecordType *RT = T->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyConstructor(); + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->hasTrivialCopyConstructor() && + !RD->hasNonTrivialCopyConstructor(); + return false; + case UTT_HasTrivialMoveAssign: + // This trait is implemented by MSVC 2012 and needed to parse the + // standard library headers. Specifically it is used as the logic + // behind std::is_trivially_move_assignable (20.9.4.3) + if (T.isPODType(Self.Context)) + return true; + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialMoveAssignment() && !RD->hasNonTrivialMoveAssignment(); return false; case UTT_HasTrivialAssign: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3095,12 +3214,13 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // errors if the copy assignment operator is actually used, q.v. // [class.copy]p12). - if (C.getBaseElementType(T).isConstQualified()) + if (T.isConstQualified()) return false; if (T.isPODType(Self.Context)) return true; - if (const RecordType *RT = T->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialCopyAssignment(); + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->hasTrivialCopyAssignment() && + !RD->hasNonTrivialCopyAssignment(); return false; case UTT_HasTrivialDestructor: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3117,9 +3237,8 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, T.getObjCLifetime() == Qualifiers::OCL_Autoreleasing) return true; - if (const RecordType *RT = - C.getBaseElementType(T)->getAs<RecordType>()) - return cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor(); + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) + return RD->hasTrivialDestructor(); return false; // TODO: Propagate nothrowness for implicitly declared special members. case UTT_HasNothrowAssign: @@ -3135,39 +3254,26 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, if (T->isReferenceType()) return false; if (T.isPODType(Self.Context) || T->isObjCLifetimeType()) - return true; - if (const RecordType *RT = T->getAs<RecordType>()) { - CXXRecordDecl* RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialCopyAssignment()) - return true; + 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)) { - Res.suppressDiagnostics(); - for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end(); - Op != OpEnd; ++Op) { - if (isa<FunctionTemplateDecl>(*Op)) - continue; - - CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op); - if (Operator->isCopyAssignmentOperator()) { - FoundAssign = true; - const FunctionProtoType *CPT - = Operator->getType()->getAs<FunctionProtoType>(); - CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); - if (!CPT) - return false; - if (!CPT->isNothrow(Self.Context)) - return false; - } - } - } - - return FoundAssign; - } + if (const RecordType *RT = T->getAs<RecordType>()) + return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + &CXXRecordDecl::hasTrivialCopyAssignment, + &CXXRecordDecl::hasNonTrivialCopyAssignment, + &CXXMethodDecl::isCopyAssignmentOperator); + return false; + case UTT_HasNothrowMoveAssign: + // This trait is implemented by MSVC 2012 and needed to parse the + // standard library headers. Specifically this is used as the logic + // behind std::is_nothrow_move_assignable (20.9.4.3). + if (T.isPODType(Self.Context)) + return true; + + if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) + return HasNoThrowOperator(RT, OO_Equal, Self, KeyLoc, C, + &CXXRecordDecl::hasTrivialMoveAssignment, + &CXXRecordDecl::hasNonTrivialMoveAssignment, + &CXXMethodDecl::isMoveAssignmentOperator); return false; case UTT_HasNothrowCopy: // http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html: @@ -3177,16 +3283,16 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // false. if (T.isPODType(C) || T->isReferenceType() || T->isObjCLifetimeType()) return true; - if (const RecordType *RT = T->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialCopyConstructor()) + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) { + if (RD->hasTrivialCopyConstructor() && + !RD->hasNonTrivialCopyConstructor()) return true; bool FoundConstructor = false; unsigned FoundTQs; - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); - Con != ConEnd; ++Con) { + DeclContext::lookup_const_result R = Self.LookupConstructors(RD); + for (DeclContext::lookup_const_iterator Con = R.begin(), + ConEnd = R.end(); Con != ConEnd; ++Con) { // A template constructor is never a copy constructor. // FIXME: However, it may actually be selected at the actual overload // resolution point. @@ -3218,14 +3324,14 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // throw an exception then the trait is true, else it is false. if (T.isPODType(C) || T->isObjCLifetimeType()) return true; - if (const RecordType *RT = C.getBaseElementType(T)->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialDefaultConstructor()) + if (CXXRecordDecl *RD = C.getBaseElementType(T)->getAsCXXRecordDecl()) { + if (RD->hasTrivialDefaultConstructor() && + !RD->hasNonTrivialDefaultConstructor()) return true; - DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = Self.LookupConstructors(RD); - Con != ConEnd; ++Con) { + DeclContext::lookup_const_result R = Self.LookupConstructors(RD); + for (DeclContext::lookup_const_iterator Con = R.begin(), + ConEnd = R.end(); Con != ConEnd; ++Con) { // FIXME: In C++0x, a constructor template can be a default constructor. if (isa<FunctionTemplateDecl>(*Con)) continue; @@ -3247,11 +3353,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, // 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 (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) if (CXXDestructorDecl *Destructor = Self.LookupDestructor(RD)) return Destructor->isVirtual(); - } return false; // These type trait expressions are modeled on the specifications for the @@ -3360,8 +3464,8 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, if (SawVoid) return false; - llvm::SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs; - llvm::SmallVector<Expr *, 2> ArgExprs; + SmallVector<OpaqueValueExpr, 2> OpaqueArgExprs; + SmallVector<Expr *, 2> ArgExprs; ArgExprs.reserve(Args.size() - 1); for (unsigned I = 1, N = Args.size(); I != N; ++I) { QualType T = Args[I]->getType(); @@ -3428,7 +3532,7 @@ ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ExprResult Sema::ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef<ParsedType> Args, SourceLocation RParenLoc) { - llvm::SmallVector<TypeSourceInfo *, 4> ConvertedArgs; + SmallVector<TypeSourceInfo *, 4> ConvertedArgs; ConvertedArgs.reserve(Args.size()); for (unsigned I = 0, N = Args.size(); I != N; ++I) { @@ -4769,7 +4873,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { // 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, + CompoundStmt *CompStmt = new (Context) CompoundStmt(Context, SubStmt, SourceLocation(), SourceLocation()); Expr *E = new (Context) StmtExpr(CompStmt, Context.VoidTy, SourceLocation(), @@ -4782,8 +4886,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { /// are omitted for the 'topmost' call in the decltype expression. If the /// topmost call bound a temporary, strip that temporary off the expression. ExprResult Sema::ActOnDecltypeExpression(Expr *E) { - ExpressionEvaluationContextRecord &Rec = ExprEvalContexts.back(); - assert(Rec.IsDecltype && "not in a decltype expression"); + assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression"); // C++11 [expr.call]p11: // If a function call is a prvalue of object type, @@ -4824,7 +4927,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { E = TopBind->getSubExpr(); // Disable the special decltype handling now. - Rec.IsDecltype = false; + ExprEvalContexts.back().IsDecltype = false; // In MS mode, don't perform any extra checking of call return types within a // decltype expression. @@ -4833,8 +4936,9 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { // Perform the semantic checks we delayed until this point. CallExpr *TopCall = dyn_cast<CallExpr>(E); - for (unsigned I = 0, N = Rec.DelayedDecltypeCalls.size(); I != N; ++I) { - CallExpr *Call = Rec.DelayedDecltypeCalls[I]; + for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeCalls.size(); + I != N; ++I) { + CallExpr *Call = ExprEvalContexts.back().DelayedDecltypeCalls[I]; if (Call == TopCall) continue; @@ -4846,8 +4950,10 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { // Now all relevant types are complete, check the destructors are accessible // and non-deleted, and annotate them on the temporaries. - for (unsigned I = 0, N = Rec.DelayedDecltypeBinds.size(); I != N; ++I) { - CXXBindTemporaryExpr *Bind = Rec.DelayedDecltypeBinds[I]; + for (unsigned I = 0, N = ExprEvalContexts.back().DelayedDecltypeBinds.size(); + I != N; ++I) { + CXXBindTemporaryExpr *Bind = + ExprEvalContexts.back().DelayedDecltypeBinds[I]; if (Bind == TopBind) continue; @@ -5321,12 +5427,12 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, VK_RValue, OK_Ordinary); if (HadMultipleCandidates) ME->setHadMultipleCandidates(true); + MarkMemberReferenced(ME); QualType ResultType = Method->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultType); ResultType = ResultType.getNonLValueExprType(Context); - MarkFunctionReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, MultiExprArg(), ResultType, VK, Exp.get()->getLocEnd()); @@ -5429,7 +5535,7 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { // normally, we don't need to do anything to handle it, but if it is a // volatile lvalue with a special form, we perform an lvalue-to-rvalue // conversion. - if (getLangOpts().CPlusPlus0x && E->isGLValue() && + if (getLangOpts().CPlusPlus11 && E->isGLValue() && E->getType().isVolatileQualified() && IsSpecialDiscardedValue(E)) { ExprResult Res = DefaultLvalueConversion(E); @@ -5460,7 +5566,9 @@ ExprResult Sema::IgnoredValueConversions(Expr *E) { return Owned(E); } -ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) { +ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, + bool DiscardedValue, + bool IsConstexpr) { ExprResult FullExpr = Owned(FE); if (!FullExpr.get()) @@ -5469,24 +5577,25 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC) { if (DiagnoseUnexpandedParameterPack(FullExpr.get())) return ExprError(); - // Top-level message sends default to 'id' when we're in a debugger. - if (getLangOpts().DebuggerCastResultToId && - FullExpr.get()->getType() == Context.UnknownAnyTy && - isa<ObjCMessageExpr>(FullExpr.get())) { + // Top-level expressions default to 'id' when we're in a debugger. + if (DiscardedValue && getLangOpts().DebuggerCastResultToId && + FullExpr.get()->getType() == Context.UnknownAnyTy) { FullExpr = forceUnknownAnyToType(FullExpr.take(), Context.getObjCIdType()); if (FullExpr.isInvalid()) return ExprError(); } - - FullExpr = CheckPlaceholderExpr(FullExpr.take()); - if (FullExpr.isInvalid()) - return ExprError(); - FullExpr = IgnoredValueConversions(FullExpr.take()); - if (FullExpr.isInvalid()) - return ExprError(); + if (DiscardedValue) { + FullExpr = CheckPlaceholderExpr(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + + FullExpr = IgnoredValueConversions(FullExpr.take()); + if (FullExpr.isInvalid()) + return ExprError(); + } - CheckImplicitConversions(FullExpr.get(), CC); + CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr); return MaybeCreateExprWithCleanups(FullExpr); } diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index a7fd471..847db24 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -11,43 +11,32 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/Scope.h" -#include "clang/Sema/ScopeInfo.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" using namespace clang; using namespace sema; +typedef llvm::SmallPtrSet<const CXXRecordDecl*, 4> BaseSet; +static bool BaseIsNotInSet(const CXXRecordDecl *Base, void *BasesPtr) { + const BaseSet &Bases = *reinterpret_cast<const BaseSet*>(BasesPtr); + return !Bases.count(Base->getCanonicalDecl()); +} + /// 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; +static bool isProvablyNotDerivedFrom(Sema &SemaRef, CXXRecordDecl *Record, + const BaseSet &Bases) { + void *BasesPtr = const_cast<void*>(reinterpret_cast<const void*>(&Bases)); + return BaseIsNotInSet(Record, BasesPtr) && + Record->forallBases(BaseIsNotInSet, BasesPtr); } enum IMAKind { @@ -111,7 +100,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // Collect all the declaring classes of instance members we find. bool hasNonInstance = false; bool isField = false; - llvm::SmallPtrSet<CXXRecordDecl*, 4> Classes; + BaseSet Classes; for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { NamedDecl *D = *I; @@ -132,7 +121,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, return IMA_Static; bool IsCXX11UnevaluatedField = false; - if (SemaRef.getLangOpts().CPlusPlus0x && isField) { + if (SemaRef.getLangOpts().CPlusPlus11 && isField) { // C++11 [expr.prim.general]p12: // An id-expression that denotes a non-static data member or non-static // member function of a class can only be used: @@ -169,16 +158,18 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef, // is ill-formed. if (R.getNamingClass() && contextClass->getCanonicalDecl() != - R.getNamingClass()->getCanonicalDecl() && - contextClass->isProvablyNotDerivedFrom(R.getNamingClass())) - return hasNonInstance ? IMA_Mixed_Unrelated : - IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : - IMA_Error_Unrelated; + R.getNamingClass()->getCanonicalDecl()) { + // If the naming class is not the current context, this was a qualified + // member name lookup, and it's sufficient to check that we have the naming + // class as a base class. + Classes.clear(); + Classes.insert(R.getNamingClass()->getCanonicalDecl()); + } // 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)) + if (isProvablyNotDerivedFrom(SemaRef, contextClass, Classes)) return hasNonInstance ? IMA_Mixed_Unrelated : IsCXX11UnevaluatedField ? IMA_Field_Uneval_Context : IMA_Error_Unrelated; @@ -491,14 +482,14 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, const CXXScopeSpec &SS, const LookupResult &R) { - const RecordType *BaseRT = BaseType->getAs<RecordType>(); - if (!BaseRT) { + CXXRecordDecl *BaseRecord = + cast_or_null<CXXRecordDecl>(computeDeclContext(BaseType)); + if (!BaseRecord) { // 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 @@ -513,11 +504,10 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, if (!DC->isRecord()) continue; - - llvm::SmallPtrSet<CXXRecordDecl*,4> MemberRecord; - MemberRecord.insert(cast<CXXRecordDecl>(DC)->getCanonicalDecl()); - if (!IsProvablyNotDerivedFrom(*this, BaseRecord, MemberRecord)) + CXXRecordDecl *MemberRecord = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); + if (BaseRecord->getCanonicalDecl() == MemberRecord || + !BaseRecord->isProvablyNotDerivedFrom(MemberRecord)) return false; } @@ -1140,30 +1130,15 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // 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")) { - Diag(MemberLoc, diag::warn_objc_isa_use); + if (OTy->isObjCId() && Member->isStr("isa")) return Owned(new (Context) ObjCIsaExpr(BaseExpr.take(), IsArrow, MemberLoc, + OpLoc, Context.getObjCClassType())); - } - if (ShouldTryAgainWithRedefinitionType(*this, BaseExpr)) return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, ObjCImpDecl, HasTemplateArgs); goto fail; } - else if (Member && Member->isStr("isa")) { - // If an ivar is (1) the first ivar in a root class and (2) named `isa`, - // then issue the same deprecated warning that id->isa gets. - ObjCInterfaceDecl *ClassDeclared = 0; - if (ObjCIvarDecl *IV = - IDecl->lookupInstanceVariable(Member, ClassDeclared)) { - if (!ClassDeclared->getSuperClass() - && (*ClassDeclared->ivar_begin()) == IV) { - Diag(MemberLoc, diag::warn_objc_isa_use); - Diag(IV->getLocation(), diag::note_ivar_decl); - } - } - } if (RequireCompleteType(OpLoc, BaseType, diag::err_typecheck_incomplete_tag, BaseExpr.get())) @@ -1269,14 +1244,15 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (ObjCMethodDecl *MD = getCurMethodDecl()) { ObjCMethodFamily MF = MD->getMethodFamily(); warn = (MF != OMF_init && MF != OMF_dealloc && - MF != OMF_finalize); + MF != OMF_finalize && + !IvarBacksCurrentMethodAccessor(IDecl, MD, IV)); } if (warn) Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName(); } ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(), - MemberLoc, + MemberLoc, OpLoc, BaseExpr.take(), IsArrow); @@ -1607,27 +1583,27 @@ BuildFieldReferenceExpr(Sema &S, Expr *BaseExpr, bool IsArrow, } 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.UnusedPrivateFields.remove(Field); ExprResult Base = diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index e43b6bf..e7b5ec9 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -12,20 +12,20 @@ //===----------------------------------------------------------------------===// #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/Analysis/DomainSpecific/CocoaConventions.h" -#include "clang/Edit/Rewriters.h" -#include "clang/Edit/Commit.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeLoc.h" -#include "llvm/ADT/SmallString.h" +#include "clang/Analysis/DomainSpecific/CocoaConventions.h" +#include "clang/Edit/Commit.h" +#include "clang/Edit/Rewriters.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "llvm/ADT/SmallString.h" using namespace clang; using namespace sema; @@ -170,9 +170,9 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, QualType NumberType, bool isLiteral = false, SourceRange R = SourceRange()) { - llvm::Optional<NSAPI::NSNumberLiteralMethodKind> Kind - = S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType); - + Optional<NSAPI::NSNumberLiteralMethodKind> Kind = + S.NSAPIObj->getNSNumberFactoryMethodKind(NumberType); + if (!Kind) { if (isLiteral) { S.Diag(Loc, diag::err_invalid_nsnumber_type) @@ -238,7 +238,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, SourceLocation(), SourceLocation(), &CX.Idents.get("value"), NumberType, /*TInfo=*/0, SC_None, - SC_None, 0); + 0); Method->setMethodParams(S.Context, value, ArrayRef<SourceLocation>()); } @@ -489,7 +489,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { &Context.Idents.get("value"), Context.getPointerType(ConstCharType), /*TInfo=*/0, - SC_None, SC_None, 0); + SC_None, 0); M->setMethodParams(Context, value, ArrayRef<SourceLocation>()); BoxingMethod = M; } @@ -656,16 +656,14 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { SourceLocation(), &Context.Idents.get("objects"), Context.getPointerType(IdT), - /*TInfo=*/0, SC_None, SC_None, - 0); + /*TInfo=*/0, SC_None, 0); Params.push_back(objects); ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, SourceLocation(), SourceLocation(), &Context.Idents.get("cnt"), Context.UnsignedLongTy, - /*TInfo=*/0, SC_None, SC_None, - 0); + /*TInfo=*/0, SC_None, 0); Params.push_back(cnt); Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>()); } @@ -774,24 +772,21 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, SourceLocation(), &Context.Idents.get("objects"), Context.getPointerType(IdT), - /*TInfo=*/0, SC_None, SC_None, - 0); + /*TInfo=*/0, SC_None, 0); Params.push_back(objects); ParmVarDecl *keys = ParmVarDecl::Create(Context, Method, SourceLocation(), SourceLocation(), &Context.Idents.get("keys"), Context.getPointerType(IdT), - /*TInfo=*/0, SC_None, SC_None, - 0); + /*TInfo=*/0, SC_None, 0); Params.push_back(keys); ParmVarDecl *cnt = ParmVarDecl::Create(Context, Method, SourceLocation(), SourceLocation(), &Context.Idents.get("cnt"), Context.UnsignedLongTy, - /*TInfo=*/0, SC_None, SC_None, - 0); + /*TInfo=*/0, SC_None, 0); Params.push_back(cnt); Method->setMethodParams(Context, Params, ArrayRef<SourceLocation>()); } @@ -981,7 +976,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, llvm::DenseMap<Selector, SourceLocation>::iterator Pos = ReferencedSelectors.find(Sel); if (Pos == ReferencedSelectors.end()) - ReferencedSelectors.insert(std::make_pair(Sel, SelLoc)); + ReferencedSelectors.insert(std::make_pair(Sel, AtLoc)); } // In ARC, forbid the user from using @selector for @@ -1094,6 +1089,73 @@ QualType Sema::getMessageSendResultType(QualType ReceiverType, return ReceiverType; } +/// Look for an ObjC method whose result type exactly matches the given type. +static const ObjCMethodDecl * +findExplicitInstancetypeDeclarer(const ObjCMethodDecl *MD, + QualType instancetype) { + if (MD->getResultType() == instancetype) return MD; + + // For these purposes, a method in an @implementation overrides a + // declaration in the @interface. + if (const ObjCImplDecl *impl = + dyn_cast<ObjCImplDecl>(MD->getDeclContext())) { + const ObjCContainerDecl *iface; + if (const ObjCCategoryImplDecl *catImpl = + dyn_cast<ObjCCategoryImplDecl>(impl)) { + iface = catImpl->getCategoryDecl(); + } else { + iface = impl->getClassInterface(); + } + + const ObjCMethodDecl *ifaceMD = + iface->getMethod(MD->getSelector(), MD->isInstanceMethod()); + if (ifaceMD) return findExplicitInstancetypeDeclarer(ifaceMD, instancetype); + } + + SmallVector<const ObjCMethodDecl *, 4> overrides; + MD->getOverriddenMethods(overrides); + for (unsigned i = 0, e = overrides.size(); i != e; ++i) { + if (const ObjCMethodDecl *result = + findExplicitInstancetypeDeclarer(overrides[i], instancetype)) + return result; + } + + return 0; +} + +void Sema::EmitRelatedResultTypeNoteForReturn(QualType destType) { + // Only complain if we're in an ObjC method and the required return + // type doesn't match the method's declared return type. + ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CurContext); + if (!MD || !MD->hasRelatedResultType() || + Context.hasSameUnqualifiedType(destType, MD->getResultType())) + return; + + // Look for a method overridden by this method which explicitly uses + // 'instancetype'. + if (const ObjCMethodDecl *overridden = + findExplicitInstancetypeDeclarer(MD, Context.getObjCInstanceType())) { + SourceLocation loc; + SourceRange range; + if (TypeSourceInfo *TSI = overridden->getResultTypeSourceInfo()) { + range = TSI->getTypeLoc().getSourceRange(); + loc = range.getBegin(); + } + if (loc.isInvalid()) + loc = overridden->getLocation(); + Diag(loc, diag::note_related_result_type_explicit) + << /*current method*/ 1 << range; + return; + } + + // Otherwise, if we have an interesting method family, note that. + // This should always trigger if the above didn't. + if (ObjCMethodFamily family = MD->getMethodFamily()) + Diag(MD->getLocation(), diag::note_related_result_type_family) + << /*current method*/ 1 + << family; +} + void Sema::EmitRelatedResultTypeNote(const Expr *E) { E = E->IgnoreParenImpCasts(); const ObjCMessageExpr *MsgSend = dyn_cast<ObjCMessageExpr>(E); @@ -1135,10 +1197,16 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, if (Args[i]->isTypeDependent()) continue; - ExprResult Result = DefaultArgumentPromotion(Args[i]); - if (Result.isInvalid()) + ExprResult result; + if (getLangOpts().DebuggerSupport) { + QualType paramTy; // ignored + result = checkUnknownAnyArg(lbrac, Args[i], paramTy); + } else { + result = DefaultArgumentPromotion(Args[i]); + } + if (result.isInvalid()) return true; - Args[i] = Result.take(); + Args[i] = result.take(); } unsigned DiagID; @@ -1196,6 +1264,22 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, !param->hasAttr<CFConsumedAttr>()) argExpr = stripARCUnbridgedCast(argExpr); + // If the parameter is __unknown_anytype, infer its type + // from the argument. + if (param->getType() == Context.UnknownAnyTy) { + QualType paramType; + ExprResult argE = checkUnknownAnyArg(lbrac, argExpr, paramType); + if (argE.isInvalid()) { + IsError = true; + } else { + Args[i] = argE.take(); + + // Update the parameter type in-place. + param->setType(paramType); + } + continue; + } + if (RequireCompleteType(argExpr->getSourceRange().getBegin(), param->getType(), diag::err_call_incomplete_argument, argExpr)) @@ -1539,8 +1623,15 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, if (ObjCMethodDecl *CurMethod = tryCaptureObjCSelf(receiverNameLoc)) { if (CurMethod->isInstanceMethod()) { - QualType T = - Context.getObjCInterfaceType(CurMethod->getClassInterface()); + ObjCInterfaceDecl *Super = + CurMethod->getClassInterface()->getSuperClass(); + if (!Super) { + // The current class does not have a superclass. + Diag(receiverNameLoc, diag::error_root_class_cannot_use_super) + << CurMethod->getClassInterface()->getIdentifier(); + return ExprError(); + } + QualType T = Context.getObjCInterfaceType(Super); T = Context.getObjCObjectPointerType(T); return HandleExprPropertyRefExpr(T->getAsObjCInterfacePointerType(), @@ -1695,9 +1786,11 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, QualType T; if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) T = Context.getObjCInterfaceType(Class); - else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + else if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) { T = Context.getTypeDeclType(Type); - else + DiagnoseUseOfDecl(Type, NameLoc); + } + else return ObjCInstanceMessage; // We have a class message, and T is the type we're @@ -2106,8 +2199,46 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, return ExprError(); Receiver = Result.take(); ReceiverType = Receiver->getType(); + + // If the receiver is an ObjC pointer, a block pointer, or an + // __attribute__((NSObject)) pointer, we don't need to do any + // special conversion in order to look up a receiver. + if (ReceiverType->isObjCRetainableType()) { + // do nothing + } else if (!getLangOpts().ObjCAutoRefCount && + !Context.getObjCIdType().isNull() && + (ReceiverType->isPointerType() || + ReceiverType->isIntegerType())) { + // Implicitly convert integers and pointers to 'id' but emit a warning. + // But not in ARC. + Diag(Loc, diag::warn_bad_receiver_type) + << ReceiverType + << Receiver->getSourceRange(); + if (ReceiverType->isPointerType()) { + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + CK_CPointerToObjCPointerCast).take(); + } else { + // TODO: specialized warning on null receivers? + bool IsNull = Receiver->isNullPointerConstant(Context, + Expr::NPC_ValueDependentIsNull); + CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer; + Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), + Kind).take(); + } + ReceiverType = Receiver->getType(); + } else if (getLangOpts().CPlusPlus) { + ExprResult result = PerformContextuallyConvertToObjCPointer(Receiver); + if (result.isUsable()) { + Receiver = result.take(); + ReceiverType = Receiver->getType(); + } + } } + // There's a somewhat weird interaction here where we assume that we + // won't actually have a method unless we also don't need to do some + // of the more detailed type-checking on the receiver. + if (!Method) { // Handle messages to id. bool receiverIsId = ReceiverType->isObjCIdType(); @@ -2223,7 +2354,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (!Method && getLangOpts().ObjCAutoRefCount) { Diag(Loc, diag::err_arc_may_not_respond) - << OCIType->getPointeeType() << Sel; + << OCIType->getPointeeType() << Sel + << SourceRange(SelectorLocs.front(), SelectorLocs.back()); return ExprError(); } @@ -2242,48 +2374,11 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass)) return ExprError(); - } else if (!getLangOpts().ObjCAutoRefCount && - !Context.getObjCIdType().isNull() && - (ReceiverType->isPointerType() || - ReceiverType->isIntegerType())) { - // Implicitly convert integers and pointers to 'id' but emit a warning. - // But not in ARC. - Diag(Loc, diag::warn_bad_receiver_type) - << ReceiverType - << Receiver->getSourceRange(); - if (ReceiverType->isPointerType()) - Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), - CK_CPointerToObjCPointerCast).take(); - else { - // TODO: specialized warning on null receivers? - bool IsNull = Receiver->isNullPointerConstant(Context, - Expr::NPC_ValueDependentIsNull); - CastKind Kind = IsNull ? CK_NullToPointer : CK_IntegralToPointer; - Receiver = ImpCastExprToType(Receiver, Context.getObjCIdType(), - Kind).take(); - } - ReceiverType = Receiver->getType(); } else { - ExprResult ReceiverRes; - if (getLangOpts().CPlusPlus) - ReceiverRes = PerformContextuallyConvertToObjCPointer(Receiver); - if (ReceiverRes.isUsable()) { - Receiver = ReceiverRes.take(); - return BuildInstanceMessage(Receiver, - ReceiverType, - SuperLoc, - Sel, - Method, - LBracLoc, - SelectorLocs, - RBracLoc, - ArgsIn); - } else { - // Reject other random receiver types (e.g. structs). - Diag(Loc, diag::err_bad_receiver_type) - << ReceiverType << Receiver->getSourceRange(); - return ExprError(); - } + // Reject other random receiver types (e.g. structs). + Diag(Loc, diag::err_bad_receiver_type) + << ReceiverType << Receiver->getSourceRange(); + return ExprError(); } } } @@ -2447,6 +2542,18 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, return MaybeBindToTemporary(Result); } +static void RemoveSelectorFromWarningCache(Sema &S, Expr* Arg) { + if (ObjCSelectorExpr *OSE = + dyn_cast<ObjCSelectorExpr>(Arg->IgnoreParenCasts())) { + Selector Sel = OSE->getSelector(); + SourceLocation Loc = OSE->getAtLoc(); + llvm::DenseMap<Selector, SourceLocation>::iterator Pos + = S.ReferencedSelectors.find(Sel); + if (Pos != S.ReferencedSelectors.end() && Pos->second == Loc) + S.ReferencedSelectors.erase(Pos); + } +} + // ActOnInstanceMessage - used for both unary and keyword messages. // ArgExprs is optional - if it is present, the number of expressions // is obtained from Sel.getNumArgs(). @@ -2460,6 +2567,20 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S, if (!Receiver) return ExprError(); + // A ParenListExpr can show up while doing error recovery with invalid code. + if (isa<ParenListExpr>(Receiver)) { + ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Receiver); + if (Result.isInvalid()) return ExprError(); + Receiver = Result.take(); + } + + if (RespondsToSelectorSel.isNull()) { + IdentifierInfo *SelectorId = &Context.Idents.get("respondsToSelector"); + RespondsToSelectorSel = Context.Selectors.getUnarySelector(SelectorId); + } + if (Sel == RespondsToSelectorSel) + RemoveSelectorFromWarningCache(*this, Args[0]); + return BuildInstanceMessage(Receiver, Receiver->getType(), /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, LBracLoc, SelectorLocs, RBracLoc, Args); @@ -2770,19 +2891,36 @@ static void addFixitForObjCARCConversion(Sema &S, SourceLocation afterLParen, QualType castType, Expr *castExpr, + Expr *realCast, const char *bridgeKeyword, const char *CFBridgeName) { // We handle C-style and implicit casts here. switch (CCK) { case Sema::CCK_ImplicitConversion: case Sema::CCK_CStyleCast: + case Sema::CCK_OtherCast: break; case Sema::CCK_FunctionalCast: - case Sema::CCK_OtherCast: return; } if (CFBridgeName) { + if (CCK == Sema::CCK_OtherCast) { + if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) { + SourceRange range(NCE->getOperatorLoc(), + NCE->getAngleBrackets().getEnd()); + SmallString<32> BridgeCall; + + SourceManager &SM = S.getSourceManager(); + char PrevChar = *SM.getCharacterData(range.getBegin().getLocWithOffset(-1)); + if (Lexer::isIdentifierBodyChar(PrevChar, S.getLangOpts())) + BridgeCall += ' '; + + BridgeCall += CFBridgeName; + DiagB.AddFixItHint(FixItHint::CreateReplacement(range, BridgeCall)); + } + return; + } Expr *castedE = castExpr; if (CStyleCastExpr *CCE = dyn_cast<CStyleCastExpr>(castedE)) castedE = CCE->getSubExpr(); @@ -2814,6 +2952,16 @@ static void addFixitForObjCARCConversion(Sema &S, if (CCK == Sema::CCK_CStyleCast) { DiagB.AddFixItHint(FixItHint::CreateInsertion(afterLParen, bridgeKeyword)); + } else if (CCK == Sema::CCK_OtherCast) { + if (const CXXNamedCastExpr *NCE = dyn_cast<CXXNamedCastExpr>(realCast)) { + std::string castCode = "("; + castCode += bridgeKeyword; + castCode += castType.getAsString(); + castCode += ")"; + SourceRange Range(NCE->getOperatorLoc(), + NCE->getAngleBrackets().getEnd()); + DiagB.AddFixItHint(FixItHint::CreateReplacement(Range, castCode)); + } } else { std::string castCode = "("; castCode += bridgeKeyword; @@ -2838,7 +2986,8 @@ static void addFixitForObjCARCConversion(Sema &S, static void diagnoseObjCARCConversion(Sema &S, SourceRange castRange, QualType castType, ARCConversionTypeClass castACTC, - Expr *castExpr, ARCConversionTypeClass exprACTC, + Expr *castExpr, Expr *realCast, + ARCConversionTypeClass exprACTC, Sema::CheckedConversionKind CCK) { SourceLocation loc = (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc()); @@ -2885,17 +3034,24 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, assert(CreateRule != ACC_bottom && "This cast should already be accepted."); if (CreateRule != ACC_plusOne) { - DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + DiagnosticBuilder DiagB = + (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) + : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, - castType, castExpr, "__bridge ", 0); + castType, castExpr, realCast, "__bridge ", 0); } if (CreateRule != ACC_plusZero) { - DiagnosticBuilder DiagB = S.Diag(br ? castExpr->getExprLoc() : noteLoc, - diag::note_arc_bridge_transfer) - << castExprType << br; + DiagnosticBuilder DiagB = + (CCK == Sema::CCK_OtherCast && !br) ? + S.Diag(noteLoc, diag::note_arc_cstyle_bridge_transfer) << castExprType : + S.Diag(br ? castExpr->getExprLoc() : noteLoc, + diag::note_arc_bridge_transfer) + << castExprType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, - castType, castExpr, "__bridge_transfer ", + castType, castExpr, realCast, "__bridge_transfer ", br ? "CFBridgingRelease" : 0); } @@ -2918,17 +3074,23 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, assert(CreateRule != ACC_bottom && "This cast should already be accepted."); if (CreateRule != ACC_plusOne) { - DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); + DiagnosticBuilder DiagB = + (CCK != Sema::CCK_OtherCast) ? S.Diag(noteLoc, diag::note_arc_bridge) + : S.Diag(noteLoc, diag::note_arc_cstyle_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, - castType, castExpr, "__bridge ", 0); + castType, castExpr, realCast, "__bridge ", 0); } if (CreateRule != ACC_plusZero) { - DiagnosticBuilder DiagB = S.Diag(br ? castExpr->getExprLoc() : noteLoc, - diag::note_arc_bridge_retained) - << castType << br; + DiagnosticBuilder DiagB = + (CCK == Sema::CCK_OtherCast && !br) ? + S.Diag(noteLoc, diag::note_arc_cstyle_bridge_retained) << castType : + S.Diag(br ? castExpr->getExprLoc() : noteLoc, + diag::note_arc_bridge_retained) + << castType << br; + addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, - castType, castExpr, "__bridge_retained ", + castType, castExpr, realCast, "__bridge_retained ", br ? "CFBridgingRetain" : 0); } @@ -3025,7 +3187,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, return ACR_unbridged; diagnoseObjCARCConversion(*this, castRange, castType, castACTC, - castExpr, exprACTC, CCK); + castExpr, castExpr, exprACTC, CCK); return ACR_okay; } @@ -3060,7 +3222,7 @@ void Sema::diagnoseARCUnbridgedCast(Expr *e) { assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable); diagnoseObjCARCConversion(*this, castRange, castType, castACTC, - castExpr, ACTC_retainable, CCK); + castExpr, realCast, ACTC_retainable, CCK); } /// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast diff --git a/lib/Sema/SemaFixItUtils.cpp b/lib/Sema/SemaFixItUtils.cpp index b61b930..2a845ba 100644 --- a/lib/Sema/SemaFixItUtils.cpp +++ b/lib/Sema/SemaFixItUtils.cpp @@ -178,7 +178,7 @@ static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S) if (T.isBooleanType() && S.LangOpts.CPlusPlus) return "false"; if (T.isPointerType() || T.isMemberPointerType()) { - if (S.LangOpts.CPlusPlus0x) + if (S.LangOpts.CPlusPlus11) return "nullptr"; if (isMacroDefined(S, "NULL")) return "NULL"; @@ -205,7 +205,7 @@ std::string Sema::getFixItZeroInitializerForType(QualType T) const { const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); if (!RD || !RD->hasDefinition()) return std::string(); - if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor()) + if (LangOpts.CPlusPlus11 && !RD->hasUserProvidedDefaultConstructor()) return "{}"; if (RD->isAggregate()) return " = {}"; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 3596bbf..63309e3 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -11,16 +11,16 @@ // //===----------------------------------------------------------------------===// -#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 "clang/Lex/Preprocessor.h" +#include "clang/Sema/Designator.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" @@ -901,11 +901,11 @@ void InitListChecker::CheckScalarType(const InitializedEntity &Entity, if (Index >= IList->getNumInits()) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), - SemaRef.getLangOpts().CPlusPlus0x ? + SemaRef.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_empty_scalar_initializer : diag::err_empty_scalar_initializer) << IList->getSourceRange(); - hadError = !SemaRef.getLangOpts().CPlusPlus0x; + hadError = !SemaRef.getLangOpts().CPlusPlus11; ++Index; ++StructuredIndex; return; @@ -985,7 +985,7 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, } Expr *expr = IList->getInit(Index); - if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus0x) { + if (isa<InitListExpr>(expr) && !SemaRef.getLangOpts().CPlusPlus11) { if (!VerifyOnly) SemaRef.Diag(IList->getLocStart(), diag::err_init_non_aggr_init_list) << DeclType << IList->getSourceRange(); @@ -1632,8 +1632,8 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, StructuredList = IsFirstDesignator? SyntacticToSemantic.lookup(IList) : getStructuredSubobjectInit(IList, Index, CurrentObjectType, StructuredList, StructuredIndex, - SourceRange(D->getStartLocation(), - DIE->getSourceRange().getEnd())); + SourceRange(D->getLocStart(), + DIE->getLocEnd())); assert(StructuredList && "Expected a structured initializer list"); } @@ -1706,7 +1706,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // struct/union. DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); FieldDecl *ReplacementField = 0; - if (Lookup.first == Lookup.second) { + if (Lookup.empty()) { // Name lookup didn't find anything. Determine whether this // was a typo for another field name. FieldInitializerValidatorCCC Validator(RT->getDecl()); @@ -1739,7 +1739,7 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // 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(), + SemaRef.Diag(Lookup.front()->getLocation(), diag::note_field_designator_found); ++Index; return true; @@ -1801,10 +1801,10 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, if (!VerifyOnly) { DesignatedInitExpr::Designator *NextD = DIE->getDesignator(DesigIdx + 1); - SemaRef.Diag(NextD->getStartLocation(), + SemaRef.Diag(NextD->getLocStart(), diag::err_designator_into_flexible_array_member) - << SourceRange(NextD->getStartLocation(), - DIE->getSourceRange().getEnd()); + << SourceRange(NextD->getLocStart(), + DIE->getLocEnd()); SemaRef.Diag(Field->getLocation(), diag::note_flexible_array_member) << *Field; } @@ -2424,6 +2424,8 @@ void InitializationSequence::Step::Destroy() { case SK_PassByIndirectRestore: case SK_ProduceObjCObject: case SK_StdInitializerList: + case SK_OCLSamplerInit: + case SK_OCLZeroEvent: break; case SK_ConversionSequence: @@ -2652,6 +2654,20 @@ void InitializationSequence::AddStdInitializerListConstructionStep(QualType T) { Steps.push_back(S); } +void InitializationSequence::AddOCLSamplerInitStep(QualType T) { + Step S; + S.Kind = SK_OCLSamplerInit; + S.Type = T; + Steps.push_back(S); +} + +void InitializationSequence::AddOCLZeroEventStep(QualType T) { + Step S; + S.Kind = SK_OCLZeroEvent; + S.Type = T; + Steps.push_back(S); +} + void InitializationSequence::RewrapReferenceInitList(QualType T, InitListExpr *Syntactic) { assert(Syntactic->getNumInits() == 1 && @@ -2744,14 +2760,14 @@ static OverloadingResult ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, - DeclContext::lookup_iterator Con, - DeclContext::lookup_iterator ConEnd, + ArrayRef<NamedDecl *> Ctors, OverloadCandidateSet::iterator &Best, bool CopyInitializing, bool AllowExplicit, bool OnlyListConstructors, bool InitListSyntax) { CandidateSet.clear(); - for (; Con != ConEnd; ++Con) { + for (ArrayRef<NamedDecl *>::iterator + Con = Ctors.begin(), ConEnd = Ctors.end(); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); bool SuppressUserConversions = false; @@ -2842,8 +2858,11 @@ static void TryConstructorInitialization(Sema &S, // - Otherwise, if T is a class type, constructors are considered. The // applicable constructors are enumerated, and the best one is chosen // through overload resolution. - DeclContext::lookup_iterator ConStart, ConEnd; - llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl); + DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl); + // The container holding the constructors can under certain conditions + // be changed while iterating (e.g. because of deserialization). + // To be safe we copy the lookup results to a new container. + SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); OverloadingResult Result = OR_No_Viable_Function; OverloadCandidateSet::iterator Best; @@ -2861,11 +2880,9 @@ static void TryConstructorInitialization(Sema &S, // If the initializer list has no elements and T has a default constructor, // the first phase is omitted. - if (ILE->getNumInits() != 0 || - (!DestRecordDecl->hasDeclaredDefaultConstructor() && - !DestRecordDecl->needsImplicitDefaultConstructor())) + if (ILE->getNumInits() != 0 || !DestRecordDecl->hasDefaultConstructor()) Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, - CandidateSet, ConStart, ConEnd, Best, + CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructor=*/true, InitListSyntax); @@ -2883,7 +2900,7 @@ static void TryConstructorInitialization(Sema &S, if (Result == OR_No_Viable_Function) { AsInitializerList = false; Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs, - CandidateSet, ConStart, ConEnd, Best, + CandidateSet, Ctors, Best, CopyInitialization, AllowExplicit, /*OnlyListConstructors=*/false, InitListSyntax); @@ -2983,7 +3000,7 @@ static void TryReferenceListInitialization(Sema &S, InitializationSequence &Sequence) { // First, catch C++03 where this isn't possible. - if (!S.getLangOpts().CPlusPlus0x) { + if (!S.getLangOpts().CPlusPlus11) { Sequence.SetFailed(InitializationSequence::FK_ReferenceBindingToInitList); return; } @@ -3023,6 +3040,10 @@ static void TryReferenceListInitialization(Sema &S, Sequence.RewrapReferenceInitList(cv1T1, InitList); return; } + + // Update the initializer if we've resolved an overloaded function. + if (Sequence.step_begin() != Sequence.step_end()) + Sequence.RewrapReferenceInitList(cv1T1, InitList); } // Not reference-related. Create a temporary and bind to that. @@ -3067,14 +3088,13 @@ static void TryListInitialization(Sema &S, // C++11 [dcl.init.list]p3: // - If T is an aggregate, aggregate initialization is performed. if (!DestType->isAggregateType()) { - if (S.getLangOpts().CPlusPlus0x) { + if (S.getLangOpts().CPlusPlus11) { // - Otherwise, if the initializer list has no elements and T is a // class type with a default constructor, the object is // value-initialized. if (InitList->getNumInits() == 0) { CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); - if (RD->hasDeclaredDefaultConstructor() || - RD->needsImplicitDefaultConstructor()) { + if (RD->hasDefaultConstructor()) { TryValueInitialization(S, Entity, Kind, Sequence, InitList); return; } @@ -3099,7 +3119,7 @@ static void TryListInitialization(Sema &S, InitListChecker CheckInitList(S, Entity, InitList, DestType, /*VerifyOnly=*/true, Kind.getKind() != InitializationKind::IK_DirectList || - !S.getLangOpts().CPlusPlus0x); + !S.getLangOpts().CPlusPlus11); if (CheckInitList.HadError()) { Sequence.SetFailed(InitializationSequence::FK_ListInitializationFailed); return; @@ -3152,10 +3172,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // 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; + DeclContext::lookup_result R = S.LookupConstructors(T1RecordDecl); + // The container holding the constructors can under certain conditions + // be changed while iterating (e.g. because of deserialization). + // To be safe we copy the lookup results to a new container. + SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); + for (SmallVector<NamedDecl*, 16>::iterator + CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { + NamedDecl *D = *CI; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); // Find the constructor (which may be a template). @@ -3191,10 +3215,11 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // 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) { + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = T2RecordDecl->getVisibleConversionFunctions(); + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -3237,10 +3262,9 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, return Result; FunctionDecl *Function = Best->Function; - - // This is the overload that will actually be used for the initialization, so - // mark it as used. - S.MarkFunctionReferenced(DeclLoc, Function); + // This is the overload that will be used for this initialization step if we + // use this initialization. Mark it as referenced. + Function->setReferenced(); // Compute the returned type of the conversion. if (isa<CXXConversionDecl>(Function)) @@ -3456,9 +3480,9 @@ static void TryReferenceInitializationCore(Sema &S, // // The constructor that would be used to make the copy shall // be callable whether or not the copy is actually done. - if (!S.getLangOpts().CPlusPlus0x && !S.getLangOpts().MicrosoftExt) + if (!S.getLangOpts().CPlusPlus11 && !S.getLangOpts().MicrosoftExt) Sequence.AddExtraneousCopyToTemporary(cv2T2); - else if (S.getLangOpts().CPlusPlus0x) + else if (S.getLangOpts().CPlusPlus11) CheckCXX98CompatAccessibleCopy(S, Entity, Initializer); } @@ -3494,6 +3518,14 @@ static void TryReferenceInitializationCore(Sema &S, return; } + if ((RefRelationship == Sema::Ref_Compatible || + RefRelationship == Sema::Ref_Compatible_With_Added_Qualification) && + isRValueRef && InitCategory.isLValue()) { + Sequence.SetFailed( + InitializationSequence::FK_RValueReferenceBindingToLValue); + return; + } + Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers); return; } @@ -3589,7 +3621,7 @@ static void TryValueInitialization(Sema &S, if (const RecordType *RT = T->getAs<RecordType>()) { if (CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(RT->getDecl())) { bool NeedZeroInitialization = true; - if (!S.getLangOpts().CPlusPlus0x) { + if (!S.getLangOpts().CPlusPlus11) { // C++98: // -- 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 @@ -3616,6 +3648,22 @@ static void TryValueInitialization(Sema &S, if (NeedZeroInitialization) Sequence.AddZeroInitializationStep(Entity.getType()); + // C++03: + // -- if T is a non-union class type without a user-declared constructor, + // then every non-static data member and base class component of T is + // value-initialized; + // [...] A program that calls for [...] value-initialization of an + // entity of reference type is ill-formed. + // + // C++11 doesn't need this handling, because value-initialization does not + // occur recursively there, and the implicit default constructor is + // defined as deleted in the problematic cases. + if (!S.getLangOpts().CPlusPlus11 && + ClassDecl->hasUninitializedReferenceMember()) { + Sequence.SetFailed(InitializationSequence::FK_TooManyInitsForReference); + return; + } + // If this is list-value-initialization, pass the empty init list on when // building the constructor call. This affects the semantics of a few // things (such as whether an explicit default constructor can be called). @@ -3700,12 +3748,11 @@ static void TryUserDefinedConversion(Sema &S, // Try to complete the type we're converting to. if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { - DeclContext::lookup_iterator ConOrig, ConEndOrig; - llvm::tie(ConOrig, ConEndOrig) = S.LookupConstructors(DestRecordDecl); + DeclContext::lookup_result R = S.LookupConstructors(DestRecordDecl); // The container holding the constructors can under certain conditions // be changed while iterating. To be safe we copy the lookup results // to a new container. - SmallVector<NamedDecl*, 8> CopyOfCon(ConOrig, ConEndOrig); + SmallVector<NamedDecl*, 8> CopyOfCon(R.begin(), R.end()); for (SmallVector<NamedDecl*, 8>::iterator Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end(); Con != ConEnd; ++Con) { @@ -3750,11 +3797,11 @@ static void TryUserDefinedConversion(Sema &S, CXXRecordDecl *SourceRecordDecl = cast<CXXRecordDecl>(SourceRecordType->getDecl()); - const UnresolvedSetImpl *Conversions - = SourceRecordDecl->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::const_iterator I = Conversions->begin(), - E = Conversions->end(); - I != E; ++I) { + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = SourceRecordDecl->getVisibleConversionFunctions(); + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -3791,7 +3838,7 @@ static void TryUserDefinedConversion(Sema &S, } FunctionDecl *Function = Best->Function; - S.MarkFunctionReferenced(DeclLoc, Function); + Function->setReferenced(); bool HadMultipleCandidates = (CandidateSet.size() > 1); if (isa<CXXConstructorDecl>(Function)) { @@ -3837,14 +3884,15 @@ enum InvalidICRKind { IIK_okay, IIK_nonlocal, IIK_nonscalar }; /// Determines whether this expression is an acceptable ICR source. static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, - bool isAddressOf) { + bool isAddressOf, bool &isWeakAccess) { // Skip parens. e = e->IgnoreParens(); // Skip address-of nodes. if (UnaryOperator *op = dyn_cast<UnaryOperator>(e)) { if (op->getOpcode() == UO_AddrOf) - return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true); + return isInvalidICRSource(C, op->getSubExpr(), /*addressof*/ true, + isWeakAccess); // Skip certain casts. } else if (CastExpr *ce = dyn_cast<CastExpr>(e)) { @@ -3853,7 +3901,7 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, case CK_BitCast: case CK_LValueBitCast: case CK_NoOp: - return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf); + return isInvalidICRSource(C, ce->getSubExpr(), isAddressOf, isWeakAccess); case CK_ArrayToPointerDecay: return IIK_nonscalar; @@ -3867,6 +3915,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, // If we have a declaration reference, it had better be a local variable. } else if (isa<DeclRefExpr>(e)) { + // set isWeakAccess to true, to mean that there will be an implicit + // load which requires a cleanup. + if (e->getType().getObjCLifetime() == Qualifiers::OCL_Weak) + isWeakAccess = true; + if (!isAddressOf) return IIK_nonlocal; VarDecl *var = dyn_cast<VarDecl>(cast<DeclRefExpr>(e)->getDecl()); @@ -3876,10 +3929,11 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, // If we have a conditional operator, check both sides. } else if (ConditionalOperator *cond = dyn_cast<ConditionalOperator>(e)) { - if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf)) + if (InvalidICRKind iik = isInvalidICRSource(C, cond->getLHS(), isAddressOf, + isWeakAccess)) return iik; - return isInvalidICRSource(C, cond->getRHS(), isAddressOf); + return isInvalidICRSource(C, cond->getRHS(), isAddressOf, isWeakAccess); // These are never scalar. } else if (isa<ArraySubscriptExpr>(e)) { @@ -3898,8 +3952,13 @@ static InvalidICRKind isInvalidICRSource(ASTContext &C, Expr *e, /// indirect copy/restore. static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { assert(src->isRValue()); - - InvalidICRKind iik = isInvalidICRSource(S.Context, src, false); + bool isWeakAccess = false; + InvalidICRKind iik = isInvalidICRSource(S.Context, src, false, isWeakAccess); + // If isWeakAccess to true, there will be an implicit + // load which requires a cleanup. + if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess) + S.ExprNeedsCleanups = true; + if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) @@ -3973,6 +4032,39 @@ static bool tryObjCWritebackConversion(Sema &S, return true; } +static bool TryOCLSamplerInitialization(Sema &S, + InitializationSequence &Sequence, + QualType DestType, + Expr *Initializer) { + if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() || + !Initializer->isIntegerConstantExpr(S.getASTContext())) + return false; + + Sequence.AddOCLSamplerInitStep(DestType); + return true; +} + +// +// OpenCL 1.2 spec, s6.12.10 +// +// The event argument can also be used to associate the +// async_work_group_copy with a previous async copy allowing +// an event to be shared by multiple async copies; otherwise +// event should be zero. +// +static bool TryOCLZeroEventInitialization(Sema &S, + InitializationSequence &Sequence, + QualType DestType, + Expr *Initializer) { + if (!S.getLangOpts().OpenCL || !DestType->isEventT() || + !Initializer->isIntegerConstantExpr(S.getASTContext()) || + (Initializer->EvaluateKnownConstInt(S.getASTContext()) != 0)) + return false; + + Sequence.AddOCLZeroEventStep(DestType); + return true; +} + InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -4115,7 +4207,13 @@ InitializationSequence::InitializationSequence(Sema &S, tryObjCWritebackConversion(S, *this, Entity, Initializer)) { return; } - + + if (TryOCLSamplerInitialization(S, *this, DestType, Initializer)) + return; + + if (TryOCLZeroEventInitialization(S, *this, DestType, Initializer)) + return; + // Handle initialization in C AddCAssignmentStep(DestType); MaybeProduceObjCObject(S, *this, Entity); @@ -4258,7 +4356,7 @@ getAssignmentAction(const InitializedEntity &Entity) { llvm_unreachable("Invalid EntityKind!"); } -/// \brief Whether we should binding a created object as a temporary when +/// \brief Whether we should bind a created object as a temporary when /// initializing the given entity. static bool shouldBindAsTemporary(const InitializedEntity &Entity) { switch (Entity.getKind()) { @@ -4288,7 +4386,6 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { /// 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: @@ -4299,6 +4396,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_LambdaCapture: return false; + case InitializedEntity::EK_Member: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Parameter: case InitializedEntity::EK_Temporary: @@ -4316,12 +4414,17 @@ static void LookupCopyAndMoveConstructors(Sema &S, OverloadCandidateSet &CandidateSet, CXXRecordDecl *Class, Expr *CurInitExpr) { - DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class); - Con != ConEnd; ++Con) { + DeclContext::lookup_result R = S.LookupConstructors(Class); + // The container holding the constructors can under certain conditions + // be changed while iterating (e.g. because of deserialization). + // To be safe we copy the lookup results to a new container. + SmallVector<NamedDecl*, 16> Ctors(R.begin(), R.end()); + for (SmallVector<NamedDecl*, 16>::iterator + CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) { + NamedDecl *D = *CI; CXXConstructorDecl *Constructor = 0; - if ((Constructor = dyn_cast<CXXConstructorDecl>(*Con))) { + if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) { // Handle copy/moveconstructors, only. if (!Constructor || Constructor->isInvalidDecl() || !Constructor->isCopyOrMoveConstructor() || @@ -4336,7 +4439,7 @@ static void LookupCopyAndMoveConstructors(Sema &S, } // Handle constructor templates. - FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(*Con); + FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(D); if (ConstructorTmpl->isInvalidDecl()) continue; @@ -4513,8 +4616,6 @@ static ExprResult CopyObject(Sema &S, return S.Owned(CurInitExpr); } - S.MarkFunctionReferenced(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). @@ -4526,6 +4627,7 @@ static ExprResult CopyObject(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -4542,7 +4644,7 @@ static ExprResult CopyObject(Sema &S, static void CheckCXX98CompatAccessibleCopy(Sema &S, const InitializedEntity &Entity, Expr *CurInitExpr) { - assert(S.getLangOpts().CPlusPlus0x); + assert(S.getLangOpts().CPlusPlus11); const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>(); if (!Record) @@ -4615,7 +4717,8 @@ PerformConstructorInitialization(Sema &S, const InitializationKind &Kind, MultiExprArg Args, const InitializationSequence::Step& Step, - bool &ConstructorInitRequiresZeroInit) { + bool &ConstructorInitRequiresZeroInit, + bool IsListInitialization) { unsigned NumArgs = Args.size(); CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Step.Function.Function); @@ -4653,7 +4756,8 @@ PerformConstructorInitialization(Sema &S, // call. if (S.CompleteConstructorCall(Constructor, Args, Loc, ConstructorArgs, - AllowExplicitConv)) + AllowExplicitConv, + IsListInitialization)) return ExprError(); @@ -4673,13 +4777,12 @@ PerformConstructorInitialization(Sema &S, if (Kind.getKind() != InitializationKind::IK_DirectList) ParenRange = Kind.getParenRange(); - CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, - Constructor, - TSInfo, - ConstructorArgs, - ParenRange, - HadMultipleCandidates, - ConstructorInitRequiresZeroInit)); + CurInit = S.Owned( + new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor, + TSInfo, ConstructorArgs, + ParenRange, IsListInitialization, + HadMultipleCandidates, + ConstructorInitRequiresZeroInit)); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; @@ -4704,6 +4807,7 @@ PerformConstructorInitialization(Sema &S, Constructor, /*Elidable=*/true, ConstructorArgs, HadMultipleCandidates, + IsListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, parenRange); @@ -4712,6 +4816,7 @@ PerformConstructorInitialization(Sema &S, Constructor, ConstructorArgs, HadMultipleCandidates, + IsListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, parenRange); @@ -4802,9 +4907,9 @@ InitializationSequence::Perform(Sema &S, if (DeclaratorDecl *DD = Entity.getDecl()) { if (TypeSourceInfo *TInfo = DD->getTypeSourceInfo()) { TypeLoc TL = TInfo->getTypeLoc(); - if (IncompleteArrayTypeLoc *ArrayLoc - = dyn_cast<IncompleteArrayTypeLoc>(&TL)) - Brackets = ArrayLoc->getBracketsRange(); + if (IncompleteArrayTypeLoc ArrayLoc = + TL.getAs<IncompleteArrayTypeLoc>()) + Brackets = ArrayLoc.getBracketsRange(); } } @@ -4835,7 +4940,7 @@ InitializationSequence::Perform(Sema &S, if (Steps.empty()) return S.Owned((Expr *)0); - if (S.getLangOpts().CPlusPlus0x && Entity.getType()->isReferenceType() && + if (S.getLangOpts().CPlusPlus11 && Entity.getType()->isReferenceType() && Args.size() == 1 && isa<InitListExpr>(Args[0]) && Entity.getKind() != InitializedEntity::EK_Parameter) { // Produce a C++98 compatibility warning if we are initializing a reference @@ -4895,7 +5000,9 @@ InitializationSequence::Perform(Sema &S, case SK_PassByIndirectCopyRestore: case SK_PassByIndirectRestore: case SK_ProduceObjCObject: - case SK_StdInitializerList: { + case SK_StdInitializerList: + case SK_OCLSamplerInit: + case SK_OCLZeroEvent: { assert(Args.size() == 1); CurInit = Args[0]; if (!CurInit.get()) return ExprError(); @@ -5047,6 +5154,7 @@ InitializationSequence::Perform(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -5161,10 +5269,11 @@ InitializationSequence::Perform(Sema &S, QualType Ty = ResultType ? ResultType->getNonReferenceType() : Step->Type; bool IsTemporary = Entity.getType()->isReferenceType(); InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(Ty); - InitListChecker PerformInitList(S, IsTemporary ? TempEntity : Entity, + InitializedEntity InitEntity = IsTemporary ? TempEntity : Entity; + InitListChecker PerformInitList(S, InitEntity, InitList, Ty, /*VerifyOnly=*/false, Kind.getKind() != InitializationKind::IK_DirectList || - !S.getLangOpts().CPlusPlus0x); + !S.getLangOpts().CPlusPlus11); if (PerformInitList.HadError()) return ExprError(); @@ -5180,7 +5289,9 @@ InitializationSequence::Perform(Sema &S, InitListExpr *StructuredInitList = PerformInitList.getFullyStructuredList(); CurInit.release(); - CurInit = S.Owned(StructuredInitList); + CurInit = shouldBindAsTemporary(InitEntity) + ? S.MaybeBindToTemporary(StructuredInitList) + : S.Owned(StructuredInitList); break; } @@ -5202,7 +5313,8 @@ InitializationSequence::Perform(Sema &S, CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, Kind, Arg, *Step, - ConstructorInitRequiresZeroInit); + ConstructorInitRequiresZeroInit, + /*IsListInitialization*/ true); break; } @@ -5235,7 +5347,8 @@ InitializationSequence::Perform(Sema &S, CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step, - ConstructorInitRequiresZeroInit); + ConstructorInitRequiresZeroInit, + /*IsListInitialization*/ false); break; } @@ -5359,7 +5472,7 @@ InitializationSequence::Perform(Sema &S, case SK_StdInitializerList: { QualType Dest = Step->Type; QualType E; - bool Success = S.isStdInitializerList(Dest, &E); + bool Success = S.isStdInitializerList(Dest.getNonReferenceType(), &E); (void)Success; assert(Success && "Destination type changed?"); @@ -5390,9 +5503,9 @@ InitializationSequence::Perform(Sema &S, for (unsigned i = 0; i < NumInits; ++i) { Element.setElementIndex(i); ExprResult Init = S.Owned(ILE->getInit(i)); - ExprResult Res = S.PerformCopyInitialization(Element, - Init.get()->getExprLoc(), - Init); + ExprResult Res = S.PerformCopyInitialization( + Element, Init.get()->getExprLoc(), Init, + /*TopLevelOfInitList=*/ true); assert(!Res.isInvalid() && "Result changed since try phase."); Converted[i] = Res.take(); } @@ -5405,6 +5518,32 @@ InitializationSequence::Perform(Sema &S, CurInit = S.Owned(Semantic); break; } + case SK_OCLSamplerInit: { + assert(Step->Type->isSamplerT() && + "Sampler initialization on non sampler type."); + + QualType SourceType = CurInit.get()->getType(); + InitializedEntity::EntityKind EntityKind = Entity.getKind(); + + if (EntityKind == InitializedEntity::EK_Parameter) { + if (!SourceType->isSamplerT()) + S.Diag(Kind.getLocation(), diag::err_sampler_argument_required) + << SourceType; + } else if (EntityKind != InitializedEntity::EK_Variable) { + llvm_unreachable("Invalid EntityKind!"); + } + + break; + } + case SK_OCLZeroEvent: { + assert(Step->Type->isEventT() && + "Event initialization on non event type."); + + CurInit = S.ImpCastExprToType(CurInit.take(), Step->Type, + CK_ZeroToOCLEvent, + CurInit.get()->getValueKind()); + break; + } } } @@ -5418,9 +5557,67 @@ InitializationSequence::Perform(Sema &S, return CurInit; } +/// Somewhere within T there is an uninitialized reference subobject. +/// Dig it out and diagnose it. +static bool DiagnoseUninitializedReference(Sema &S, SourceLocation Loc, + QualType T) { + if (T->isReferenceType()) { + S.Diag(Loc, diag::err_reference_without_init) + << T.getNonReferenceType(); + return true; + } + + CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + if (!RD || !RD->hasUninitializedReferenceMember()) + return false; + + for (CXXRecordDecl::field_iterator FI = RD->field_begin(), + FE = RD->field_end(); FI != FE; ++FI) { + if (FI->isUnnamedBitfield()) + continue; + + if (DiagnoseUninitializedReference(S, FI->getLocation(), FI->getType())) { + S.Diag(Loc, diag::note_value_initialization_here) << RD; + return true; + } + } + + for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin(), + BE = RD->bases_end(); + BI != BE; ++BI) { + if (DiagnoseUninitializedReference(S, BI->getLocStart(), BI->getType())) { + S.Diag(Loc, diag::note_value_initialization_here) << RD; + return true; + } + } + + return false; +} + + //===----------------------------------------------------------------------===// // Diagnose initialization failures //===----------------------------------------------------------------------===// + +/// Emit notes associated with an initialization that failed due to a +/// "simple" conversion failure. +static void emitBadConversionNotes(Sema &S, const InitializedEntity &entity, + Expr *op) { + QualType destType = entity.getType(); + if (destType.getNonReferenceType()->isObjCObjectPointerType() && + op->getType()->isObjCObjectPointerType()) { + + // Emit a possible note about the conversion failing because the + // operand is a message send with a related result type. + S.EmitRelatedResultTypeNote(op); + + // Emit a possible note about a return failing because we're + // expecting a related result type. + if (entity.getKind() == InitializedEntity::EK_Result) + S.EmitRelatedResultTypeNoteForReturn(destType); + } +} + bool InitializationSequence::Diagnose(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -5432,10 +5629,17 @@ bool InitializationSequence::Diagnose(Sema &S, 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! + if (NumArgs == 0) { + // Dig out the reference subobject which is uninitialized and diagnose it. + // If this is value-initialization, this could be nested some way within + // the target type. + assert(Kind.getKind() == InitializationKind::IK_Value || + DestType->isReferenceType()); + bool Diagnosed = + DiagnoseUninitializedReference(S, Kind.getLocation(), DestType); + assert(Diagnosed && "couldn't find uninitialized reference to diagnose"); + (void)Diagnosed; + } 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; @@ -5558,9 +5762,7 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->isLValue() << Args[0]->getType() << Args[0]->getSourceRange(); - if (DestType.getNonReferenceType()->isObjCObjectPointerType() && - Args[0]->getType()->isObjCObjectPointerType()) - S.EmitRelatedResultTypeNote(Args[0]); + emitBadConversionNotes(S, Entity, Args[0]); break; case FK_ConversionFailed: { @@ -5573,9 +5775,7 @@ bool InitializationSequence::Diagnose(Sema &S, << Args[0]->getSourceRange(); S.HandleFunctionTypeMismatch(PDiag, FromType, DestType); S.Diag(Kind.getLocation(), PDiag); - if (DestType.getNonReferenceType()->isObjCObjectPointerType() && - Args[0]->getType()->isObjCObjectPointerType()) - S.EmitRelatedResultTypeNote(Args[0]); + emitBadConversionNotes(S, Entity, Args[0]); break; } @@ -5649,7 +5849,8 @@ bool InitializationSequence::Diagnose(Sema &S, = cast<CXXConstructorDecl>(S.CurContext); if (Entity.getKind() == InitializedEntity::EK_Base) { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) - << Constructor->isImplicit() + << (Constructor->getInheritedConstructor() ? 2 : + Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*base=*/0 << Entity.getType(); @@ -5661,7 +5862,8 @@ bool InitializationSequence::Diagnose(Sema &S, << S.Context.getTagDeclType(BaseDecl); } else { S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) - << Constructor->isImplicit() + << (Constructor->getInheritedConstructor() ? 2 : + Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*member=*/1 << Entity.getName(); @@ -5722,7 +5924,8 @@ bool InitializationSequence::Diagnose(Sema &S, // initialized. CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext); S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor) - << Constructor->isImplicit() + << (Constructor->getInheritedConstructor() ? 2 : + Constructor->isImplicit() ? 1 : 0) << S.Context.getTypeDeclType(Constructor->getParent()) << /*const=*/1 << Entity.getName(); @@ -5746,7 +5949,7 @@ bool InitializationSequence::Diagnose(Sema &S, InitListChecker DiagnoseInitList(S, Entity, InitList, DestType, /*VerifyOnly=*/false, Kind.getKind() != InitializationKind::IK_DirectList || - !S.getLangOpts().CPlusPlus0x); + !S.getLangOpts().CPlusPlus11); assert(DiagnoseInitList.HadError() && "Inconsistent init list check result."); break; @@ -5763,7 +5966,7 @@ bool InitializationSequence::Diagnose(Sema &S, unsigned NumInits = InitList->getNumInits(); QualType DestType = Entity.getType(); QualType E; - bool Success = S.isStdInitializerList(DestType, &E); + bool Success = S.isStdInitializerList(DestType.getNonReferenceType(), &E); (void)Success; assert(Success && "Where did the std::initializer_list go?"); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary( @@ -6047,8 +6250,20 @@ void InitializationSequence::dump(raw_ostream &OS) const { case SK_StdInitializerList: OS << "std::initializer_list from initializer list"; break; + + case SK_OCLSamplerInit: + OS << "OpenCL sampler_t from integer constant"; + break; + + case SK_OCLZeroEvent: + OS << "OpenCL event_t from zero"; + break; } + + OS << " [" << S->Type.getAsString() << ']'; } + + OS << '\n'; } void InitializationSequence::dump() const { @@ -6104,7 +6319,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, // narrowing conversion even if the value is a constant and can be // represented exactly as an integer. S.Diag(PostInit->getLocStart(), - S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11? diag::warn_init_list_type_narrowing : S.isSFINAEContext()? diag::err_init_list_type_narrowing_sfinae @@ -6117,7 +6332,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, case NK_Constant_Narrowing: // A constant value was narrowed. S.Diag(PostInit->getLocStart(), - S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11? diag::warn_init_list_constant_narrowing : S.isSFINAEContext()? diag::err_init_list_constant_narrowing_sfinae @@ -6130,7 +6345,7 @@ static void DiagnoseNarrowingInInitList(Sema &S, InitializationSequence &Seq, case NK_Variable_Narrowing: // A variable's value may have been narrowed. S.Diag(PostInit->getLocStart(), - S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus0x? + S.getLangOpts().MicrosoftExt || !S.getLangOpts().CPlusPlus11? diag::warn_init_list_variable_narrowing : S.isSFINAEContext()? diag::err_init_list_variable_narrowing_sfinae diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 15cd2a7..53fa6da 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -11,13 +11,13 @@ // //===----------------------------------------------------------------------===// #include "clang/Sema/DeclSpec.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/AST/ExprCXX.h" using namespace clang; using namespace sema; @@ -55,7 +55,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, - llvm::ArrayRef<ParmVarDecl *> Params) { + ArrayRef<ParmVarDecl *> Params) { // C++11 [expr.prim.lambda]p5: // The closure type for a lambda-expression has a public inline function // call operator (13.5.4) whose parameters and return type are described by @@ -74,7 +74,6 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, IntroducerRange.getBegin(), MethodNameLoc), MethodType->getType(), MethodType, - /*isStatic=*/false, SC_None, /*isInline=*/true, /*isConstExpr=*/false, @@ -225,73 +224,153 @@ void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) { } } -static bool checkReturnValueType(const ASTContext &Ctx, const Expr *E, - QualType &DeducedType, - QualType &AlternateType) { - // Handle ReturnStmts with no expressions. - if (!E) { - if (AlternateType.isNull()) - AlternateType = Ctx.VoidTy; +/// If this expression is an enumerator-like expression of some type +/// T, return the type T; otherwise, return null. +/// +/// Pointer comparisons on the result here should always work because +/// it's derived from either the parent of an EnumConstantDecl +/// (i.e. the definition) or the declaration returned by +/// EnumType::getDecl() (i.e. the definition). +static EnumDecl *findEnumForBlockReturn(Expr *E) { + // An expression is an enumerator-like expression of type T if, + // ignoring parens and parens-like expressions: + E = E->IgnoreParens(); + + // - it is an enumerator whose enum type is T or + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (EnumConstantDecl *D + = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { + return cast<EnumDecl>(D->getDeclContext()); + } + return 0; + } - return Ctx.hasSameType(DeducedType, Ctx.VoidTy); + // - it is a comma expression whose RHS is an enumerator-like + // expression of type T or + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + if (BO->getOpcode() == BO_Comma) + return findEnumForBlockReturn(BO->getRHS()); + return 0; } - QualType StrictType = E->getType(); - QualType LooseType = StrictType; - - // In C, enum constants have the type of their underlying integer type, - // not the enum. When inferring block return types, we should allow - // the enum type if an enum constant is used, unless the enum is - // anonymous (in which case there can be no variables of its type). - if (!Ctx.getLangOpts().CPlusPlus) { - const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()); - if (DRE) { - const Decl *D = DRE->getDecl(); - if (const EnumConstantDecl *ECD = dyn_cast<EnumConstantDecl>(D)) { - const EnumDecl *Enum = cast<EnumDecl>(ECD->getDeclContext()); - if (Enum->getDeclName() || Enum->getTypedefNameForAnonDecl()) - LooseType = Ctx.getTypeDeclType(Enum); - } - } + // - it is a statement-expression whose value expression is an + // enumerator-like expression of type T or + if (StmtExpr *SE = dyn_cast<StmtExpr>(E)) { + if (Expr *last = dyn_cast_or_null<Expr>(SE->getSubStmt()->body_back())) + return findEnumForBlockReturn(last); + return 0; } - // Special case for the first return statement we find. - // The return type has already been tentatively set, but we might still - // have an alternate type we should prefer. - if (AlternateType.isNull()) - AlternateType = LooseType; - - if (Ctx.hasSameType(DeducedType, StrictType)) { - // FIXME: The loose type is different when there are constants from two - // different enums. We could consider warning here. - if (AlternateType != Ctx.DependentTy) - if (!Ctx.hasSameType(AlternateType, LooseType)) - AlternateType = Ctx.VoidTy; - return true; + // - it is a ternary conditional operator (not the GNU ?: + // extension) whose second and third operands are + // enumerator-like expressions of type T or + if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { + if (EnumDecl *ED = findEnumForBlockReturn(CO->getTrueExpr())) + if (ED == findEnumForBlockReturn(CO->getFalseExpr())) + return ED; + return 0; } - if (Ctx.hasSameType(DeducedType, LooseType)) { - // Use DependentTy to signal that we're using an alternate type and may - // need to add casts somewhere. - AlternateType = Ctx.DependentTy; - return true; + // (implicitly:) + // - it is an implicit integral conversion applied to an + // enumerator-like expression of type T or + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + // We can only see integral conversions in valid enumerator-like + // expressions. + if (ICE->getCastKind() == CK_IntegralCast) + return findEnumForBlockReturn(ICE->getSubExpr()); + return 0; } - if (Ctx.hasSameType(AlternateType, StrictType) || - Ctx.hasSameType(AlternateType, LooseType)) { - DeducedType = AlternateType; - // Use DependentTy to signal that we're using an alternate type and may - // need to add casts somewhere. - AlternateType = Ctx.DependentTy; - return true; + // - it is an expression of that formal enum type. + if (const EnumType *ET = E->getType()->getAs<EnumType>()) { + return ET->getDecl(); } - return false; + // Otherwise, nope. + return 0; +} + +/// Attempt to find a type T for which the returned expression of the +/// given statement is an enumerator-like expression of that type. +static EnumDecl *findEnumForBlockReturn(ReturnStmt *ret) { + if (Expr *retValue = ret->getRetValue()) + return findEnumForBlockReturn(retValue); + return 0; +} + +/// Attempt to find a common type T for which all of the returned +/// expressions in a block are enumerator-like expressions of that +/// type. +static EnumDecl *findCommonEnumForBlockReturns(ArrayRef<ReturnStmt*> returns) { + ArrayRef<ReturnStmt*>::iterator i = returns.begin(), e = returns.end(); + + // Try to find one for the first return. + EnumDecl *ED = findEnumForBlockReturn(*i); + if (!ED) return 0; + + // Check that the rest of the returns have the same enum. + for (++i; i != e; ++i) { + if (findEnumForBlockReturn(*i) != ED) + return 0; + } + + // Never infer an anonymous enum type. + if (!ED->hasNameForLinkage()) return 0; + + return ED; +} + +/// Adjust the given return statements so that they formally return +/// the given type. It should require, at most, an IntegralCast. +static void adjustBlockReturnsToEnum(Sema &S, ArrayRef<ReturnStmt*> returns, + QualType returnType) { + for (ArrayRef<ReturnStmt*>::iterator + i = returns.begin(), e = returns.end(); i != e; ++i) { + ReturnStmt *ret = *i; + Expr *retValue = ret->getRetValue(); + if (S.Context.hasSameType(retValue->getType(), returnType)) + continue; + + // Right now we only support integral fixup casts. + assert(returnType->isIntegralOrUnscopedEnumerationType()); + assert(retValue->getType()->isIntegralOrUnscopedEnumerationType()); + + ExprWithCleanups *cleanups = dyn_cast<ExprWithCleanups>(retValue); + + Expr *E = (cleanups ? cleanups->getSubExpr() : retValue); + E = ImplicitCastExpr::Create(S.Context, returnType, CK_IntegralCast, + E, /*base path*/ 0, VK_RValue); + if (cleanups) { + cleanups->setSubExpr(E); + } else { + ret->setRetValue(E); + } + } } void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { assert(CSI.HasImplicitReturnType); + // C++ Core Issue #975, proposed resolution: + // If a lambda-expression does not include a trailing-return-type, + // it is as if the trailing-return-type denotes the following type: + // - if there are no return statements in the compound-statement, + // or all return statements return either an expression of type + // void or no expression or braced-init-list, the type void; + // - otherwise, if all return statements return an expression + // and the types of the returned expressions after + // lvalue-to-rvalue conversion (4.1 [conv.lval]), + // array-to-pointer conversion (4.2 [conv.array]), and + // function-to-pointer conversion (4.3 [conv.func]) are the + // same, that common type; + // - otherwise, the program is ill-formed. + // + // In addition, in blocks in non-C++ modes, if all of the return + // statements are enumerator-like expressions of some type T, where + // T has a name for linkage, then we infer the return type of the + // block to be that type. + // First case: no return statements, implicit void return type. ASTContext &Ctx = getASTContext(); if (CSI.Returns.empty()) { @@ -308,6 +387,17 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { if (CSI.ReturnType->isDependentType()) return; + // Try to apply the enum-fuzz rule. + if (!getLangOpts().CPlusPlus) { + assert(isa<BlockScopeInfo>(CSI)); + const EnumDecl *ED = findCommonEnumForBlockReturns(CSI.Returns); + if (ED) { + CSI.ReturnType = Context.getTypeDeclType(ED); + adjustBlockReturnsToEnum(*this, CSI.Returns, CSI.ReturnType); + return; + } + } + // Third case: only one return statement. Don't bother doing extra work! SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(), E = CSI.Returns.end(); @@ -316,47 +406,25 @@ void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) { // General case: many return statements. // Check that they all have compatible return types. - // For now, that means "identical", with an exception for enum constants. - // (In C, enum constants have the type of their underlying integer type, - // not the type of the enum. C++ uses the type of the enum.) - QualType AlternateType; // We require the return types to strictly match here. + // Note that we've already done the required promotions as part of + // processing the return statement. for (; I != E; ++I) { const ReturnStmt *RS = *I; const Expr *RetE = RS->getRetValue(); - if (!checkReturnValueType(Ctx, RetE, CSI.ReturnType, AlternateType)) { - // FIXME: This is a poor diagnostic for ReturnStmts without expressions. - Diag(RS->getLocStart(), - diag::err_typecheck_missing_return_type_incompatible) - << (RetE ? RetE->getType() : Ctx.VoidTy) << CSI.ReturnType - << isa<LambdaScopeInfo>(CSI); - // Don't bother fixing up the return statements in the block if some of - // them are unfixable anyway. - AlternateType = Ctx.VoidTy; - // Continue iterating so that we keep emitting diagnostics. - } - } - // If our return statements turned out to be compatible, but we needed to - // pick a different return type, go through and fix the ones that need it. - if (AlternateType == Ctx.DependentTy) { - for (SmallVectorImpl<ReturnStmt*>::iterator I = CSI.Returns.begin(), - E = CSI.Returns.end(); - I != E; ++I) { - ReturnStmt *RS = *I; - Expr *RetE = RS->getRetValue(); - if (RetE->getType() == CSI.ReturnType) - continue; + QualType ReturnType = (RetE ? RetE->getType() : Context.VoidTy); + if (Context.hasSameType(ReturnType, CSI.ReturnType)) + continue; - // Right now we only support integral fixup casts. - assert(CSI.ReturnType->isIntegralOrUnscopedEnumerationType()); - assert(RetE->getType()->isIntegralOrUnscopedEnumerationType()); - ExprResult Casted = ImpCastExprToType(RetE, CSI.ReturnType, - CK_IntegralCast); - assert(Casted.isUsable()); - RS->setRetValue(Casted.take()); - } + // FIXME: This is a poor diagnostic for ReturnStmts without expressions. + // TODO: It's possible that the *first* return is the divergent one. + Diag(RS->getLocStart(), + diag::err_typecheck_missing_return_type_incompatible) + << ReturnType << CSI.ReturnType + << isa<LambdaScopeInfo>(CSI); + // Continue iterating so that we keep emitting diagnostics. } } @@ -376,7 +444,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, bool ExplicitResultType = true; bool ContainsUnexpandedParameterPack = false; SourceLocation EndLoc; - llvm::SmallVector<ParmVarDecl *, 8> Params; + SmallVector<ParmVarDecl *, 8> Params; if (ParamInfo.getNumTypeObjects() == 0) { // C++11 [expr.prim.lambda]p4: // If a lambda-expression does not include a lambda-declarator, it is as @@ -385,7 +453,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, EPI.HasTrailingReturn = true; EPI.TypeQuals |= DeclSpec::TQ_const; QualType MethodTy = Context.getFunctionType(Context.DependentTy, - /*Args=*/0, /*NumArgs=*/0, EPI); + ArrayRef<QualType>(), + EPI); MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy); ExplicitParams = false; ExplicitResultType = false; @@ -449,7 +518,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, // Handle explicit captures. SourceLocation PrevCaptureLoc = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc; - for (llvm::SmallVector<LambdaCapture, 4>::const_iterator + for (SmallVector<LambdaCapture, 4>::const_iterator C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E; @@ -628,16 +697,18 @@ static void addFunctionPointerConversion(Sema &S, { FunctionProtoType::ExtProtoInfo ExtInfo = Proto->getExtProtoInfo(); ExtInfo.TypeQuals = 0; - FunctionTy = S.Context.getFunctionType(Proto->getResultType(), - Proto->arg_type_begin(), - Proto->getNumArgs(), - ExtInfo); + FunctionTy = + S.Context.getFunctionType(Proto->getResultType(), + ArrayRef<QualType>(Proto->arg_type_begin(), + Proto->getNumArgs()), + ExtInfo); FunctionPtrTy = S.Context.getPointerType(FunctionTy); } FunctionProtoType::ExtProtoInfo ExtInfo; ExtInfo.TypeQuals = Qualifiers::Const; - QualType ConvTy = S.Context.getFunctionType(FunctionPtrTy, 0, 0, ExtInfo); + QualType ConvTy = + S.Context.getFunctionType(FunctionPtrTy, ArrayRef<QualType>(), ExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name @@ -666,7 +737,7 @@ static void addFunctionPointerConversion(Sema &S, = CXXMethodDecl::Create(S.Context, Class, Loc, DeclarationNameInfo(Name, Loc), FunctionTy, CallOperator->getTypeSourceInfo(), - /*IsStatic=*/true, SC_Static, /*IsInline=*/true, + SC_Static, /*IsInline=*/true, /*IsConstexpr=*/false, CallOperator->getBody()->getLocEnd()); SmallVector<ParmVarDecl *, 4> InvokeParams; @@ -679,7 +750,6 @@ static void addFunctionPointerConversion(Sema &S, From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - From->getStorageClassAsWritten(), /*DefaultArg=*/0)); } Invoke->setParams(InvokeParams); @@ -701,15 +771,16 @@ static void addBlockPointerConversion(Sema &S, ExtInfo.TypeQuals = 0; QualType FunctionTy = S.Context.getFunctionType(Proto->getResultType(), - Proto->arg_type_begin(), - Proto->getNumArgs(), + ArrayRef<QualType>(Proto->arg_type_begin(), + Proto->getNumArgs()), ExtInfo); BlockPtrTy = S.Context.getBlockPointerType(FunctionTy); } FunctionProtoType::ExtProtoInfo ExtInfo; ExtInfo.TypeQuals = Qualifiers::Const; - QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, 0, 0, ExtInfo); + QualType ConvTy = S.Context.getFunctionType(BlockPtrTy, ArrayRef<QualType>(), + ExtInfo); SourceLocation Loc = IntroducerRange.getBegin(); DeclarationName Name @@ -734,8 +805,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope, bool IsInstantiation) { // Collect information from the lambda scope. - llvm::SmallVector<LambdaExpr::Capture, 4> Captures; - llvm::SmallVector<Expr *, 4> CaptureInits; + SmallVector<LambdaExpr::Capture, 4> Captures; + SmallVector<Expr *, 4> CaptureInits; LambdaCaptureDefault CaptureDefault; CXXRecordDecl *Class; CXXMethodDecl *CallOperator; @@ -744,8 +815,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, bool ExplicitResultType; bool LambdaExprNeedsCleanups; bool ContainsUnexpandedParameterPack; - llvm::SmallVector<VarDecl *, 4> ArrayIndexVars; - llvm::SmallVector<unsigned, 4> ArrayIndexStarts; + SmallVector<VarDecl *, 4> ArrayIndexVars; + SmallVector<unsigned, 4> ArrayIndexStarts; { LambdaScopeInfo *LSI = getCurLambda(); CallOperator = LSI->CallOperator; @@ -821,8 +892,8 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, = CallOperator->getType()->getAs<FunctionProtoType>(); QualType FunctionTy = Context.getFunctionType(LSI->ReturnType, - Proto->arg_type_begin(), - Proto->getNumArgs(), + ArrayRef<QualType>(Proto->arg_type_begin(), + Proto->getNumArgs()), Proto->getExtProtoInfo()); CallOperator->setType(FunctionTy); } @@ -902,8 +973,8 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, CXXRecordDecl *Lambda = Conv->getParent(); CXXMethodDecl *CallOperator = cast<CXXMethodDecl>( - *Lambda->lookup( - Context.DeclarationNames.getCXXOperatorName(OO_Call)).first); + Lambda->lookup( + Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); CallOperator->setUsed(); @@ -937,7 +1008,6 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, From->getType(), From->getTypeSourceInfo(), From->getStorageClass(), - From->getStorageClassAsWritten(), /*DefaultArg=*/0)); } Block->setParams(BlockParams); @@ -952,7 +1022,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, VarDecl *CapVar = VarDecl::Create(Context, Block, ConvLocation, ConvLocation, 0, Src->getType(), CapVarTSI, - SC_None, SC_None); + SC_None); BlockDecl::Capture Capture(/*Variable=*/CapVar, /*ByRef=*/false, /*Nested=*/false, /*Copy=*/Init.take()); Block->setCaptures(Context, &Capture, &Capture + 1, diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index f6987e7..f26b8ed 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -11,16 +11,7 @@ // 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/Sema/TypoCorrection.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" @@ -32,8 +23,17 @@ #include "clang/AST/ExprCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" -#include "llvm/ADT/SetVector.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ExternalSemaSource.h" +#include "clang/Sema/Overload.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/TemplateDeduction.h" +#include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/TinyPtrVector.h" @@ -287,10 +287,10 @@ void LookupResult::configure() { IDNS = getIDNS(LookupKind, SemaRef.getLangOpts().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()) { + // 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. switch (NameInfo.getName().getCXXOverloadedOperator()) { case OO_New: case OO_Delete: @@ -302,6 +302,15 @@ void LookupResult::configure() { default: break; } + + // Compiler builtins are always visible, regardless of where they end + // up being declared. + if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) { + if (unsigned BuiltinID = Id->getBuiltinID()) { + if (!SemaRef.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + AllowHidden = true; + } + } } } @@ -371,6 +380,12 @@ void LookupResult::resolveKind() { NamedDecl *D = Decls[I]->getUnderlyingDecl(); D = cast<NamedDecl>(D->getCanonicalDecl()); + // Ignore an invalid declaration unless it's the only one left. + if (D->isInvalidDecl() && I < N-1) { + Decls[I] = Decls[--N]; + continue; + } + // 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 @@ -451,9 +466,9 @@ void LookupResult::resolveKind() { 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) + for (DeclContext::lookup_iterator DI = I->Decls.begin(), + DE = I->Decls.end(); DI != DE; ++DI) addDecl(*DI); } @@ -528,22 +543,17 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { /// \brief Determine whether we can declare a special member function within /// the class at this point. -static bool CanDeclareSpecialMemberFunction(ASTContext &Context, - const CXXRecordDecl *Class) { +static bool CanDeclareSpecialMemberFunction(const CXXRecordDecl *Class) { // 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; + return !Class->isBeingDefined(); } void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { - if (!CanDeclareSpecialMemberFunction(Context, Class)) + if (!CanDeclareSpecialMemberFunction(Class)) return; // If the default constructor has not yet been declared, do so now. @@ -551,14 +561,14 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { DeclareImplicitDefaultConstructor(Class); // If the copy constructor has not yet been declared, do so now. - if (!Class->hasDeclaredCopyConstructor()) + if (Class->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(Class); // If the copy assignment operator has not yet been declared, do so now. - if (!Class->hasDeclaredCopyAssignment()) + if (Class->needsImplicitCopyAssignment()) DeclareImplicitCopyAssignment(Class); - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { // If the move constructor has not yet been declared, do so now. if (Class->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(Class); // might not actually do it @@ -569,7 +579,7 @@ void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { } // If the destructor has not yet been declared, do so now. - if (!Class->hasDeclaredDestructor()) + if (Class->needsImplicitDestructor()) DeclareImplicitDestructor(Class); } @@ -602,14 +612,13 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, switch (Name.getNameKind()) { case DeclarationName::CXXConstructorName: if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) - if (Record->getDefinition() && - CanDeclareSpecialMemberFunction(S.Context, Record)) { + if (Record->getDefinition() && CanDeclareSpecialMemberFunction(Record)) { CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record); if (Record->needsImplicitDefaultConstructor()) S.DeclareImplicitDefaultConstructor(Class); - if (!Record->hasDeclaredCopyConstructor()) + if (Record->needsImplicitCopyConstructor()) S.DeclareImplicitCopyConstructor(Class); - if (S.getLangOpts().CPlusPlus0x && + if (S.getLangOpts().CPlusPlus11 && Record->needsImplicitMoveConstructor()) S.DeclareImplicitMoveConstructor(Class); } @@ -617,8 +626,8 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, case DeclarationName::CXXDestructorName: if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) - if (Record->getDefinition() && !Record->hasDeclaredDestructor() && - CanDeclareSpecialMemberFunction(S.Context, Record)) + if (Record->getDefinition() && Record->needsImplicitDestructor() && + CanDeclareSpecialMemberFunction(Record)) S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record)); break; @@ -627,12 +636,11 @@ static void DeclareImplicitMemberFunctionsWithName(Sema &S, break; if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) { - if (Record->getDefinition() && - CanDeclareSpecialMemberFunction(S.Context, Record)) { + if (Record->getDefinition() && CanDeclareSpecialMemberFunction(Record)) { CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(Record); - if (!Record->hasDeclaredCopyAssignment()) + if (Record->needsImplicitCopyAssignment()) S.DeclareImplicitCopyAssignment(Class); - if (S.getLangOpts().CPlusPlus0x && + if (S.getLangOpts().CPlusPlus11 && Record->needsImplicitMoveAssignment()) S.DeclareImplicitMoveAssignment(Class); } @@ -654,8 +662,9 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { 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) { + DeclContext::lookup_const_result DR = DC->lookup(R.getLookupName()); + for (DeclContext::lookup_const_iterator I = DR.begin(), E = DR.end(); I != E; + ++I) { NamedDecl *D = *I; if ((D = R.getAcceptableDecl(D))) { R.addDecl(D); @@ -680,9 +689,8 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { if (!Record->isCompleteDefinition()) return Found; - const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions(); - for (UnresolvedSetImpl::iterator U = Unresolved->begin(), - UEnd = Unresolved->end(); U != UEnd; ++U) { + for (CXXRecordDecl::conversion_iterator U = Record->conversion_begin(), + UEnd = Record->conversion_end(); U != UEnd; ++U) { FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U); if (!ConvTemplate) continue; @@ -723,7 +731,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { EPI.NumExceptions = 0; QualType ExpectedType = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), - 0, 0, EPI); + ArrayRef<QualType>(), EPI); // Perform template argument deduction against the type that we would // expect the function to have. @@ -946,6 +954,21 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { continue; } + // If this is a file context, we need to perform unqualified name + // lookup considering using directives. + if (Ctx->isFileContext()) { + UnqualUsingDirectiveSet UDirs; + UDirs.visit(Ctx, Ctx); + UDirs.done(); + + if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) { + 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 @@ -980,7 +1003,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { // 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; @@ -1344,7 +1366,7 @@ static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, DeclarationName N = DeclarationName::getFromOpaquePtr(Name); Path.Decls = BaseRecord->lookup(N); - return Path.Decls.first != Path.Decls.second; + return !Path.Decls.empty(); } /// \brief Determine whether the given set of member declarations contains only @@ -1530,13 +1552,13 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // 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)) { + if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) { CXXBasePaths::paths_iterator FirstPath = Paths.begin(); - DeclContext::lookup_iterator FirstD = FirstPath->Decls.first; - DeclContext::lookup_iterator CurrentD = Path->Decls.first; + DeclContext::lookup_iterator FirstD = FirstPath->Decls.begin(); + DeclContext::lookup_iterator CurrentD = Path->Decls.begin(); - while (FirstD != FirstPath->Decls.second && - CurrentD != Path->Decls.second) { + while (FirstD != FirstPath->Decls.end() && + CurrentD != Path->Decls.end()) { if ((*FirstD)->getUnderlyingDecl()->getCanonicalDecl() != (*CurrentD)->getUnderlyingDecl()->getCanonicalDecl()) break; @@ -1545,8 +1567,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, ++CurrentD; } - if (FirstD == FirstPath->Decls.second && - CurrentD == Path->Decls.second) + if (FirstD == FirstPath->Decls.end() && + CurrentD == Path->Decls.end()) continue; } @@ -1561,7 +1583,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // 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)) + if (HasOnlyStaticMembers(Path->Decls.begin(), Path->Decls.end())) continue; // We have found a nonstatic member name in multiple, distinct @@ -1573,8 +1595,8 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // 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) { + DeclContext::lookup_result DR = Paths.front().Decls; + for (DeclContext::lookup_iterator I = DR.begin(), E = DR.end(); I != E; ++I) { NamedDecl *D = *I; AccessSpecifier AS = CXXRecordDecl::MergeAccess(SubobjectAccess, D->getAccess()); @@ -1655,7 +1677,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { << Name << SubobjectType << getAmbiguousPathsDisplayString(*Paths) << LookupRange; - DeclContext::lookup_iterator Found = Paths->front().Decls.first; + DeclContext::lookup_iterator Found = Paths->front().Decls.begin(); while (isa<CXXMethodDecl>(*Found) && cast<CXXMethodDecl>(*Found)->isStatic()) ++Found; @@ -1674,7 +1696,7 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { for (CXXBasePaths::paths_iterator Path = Paths->begin(), PathEnd = Paths->end(); Path != PathEnd; ++Path) { - Decl *D = *Path->Decls.first; + Decl *D = Path->Decls.front(); if (DeclsPrinted.insert(D).second) Diag(D->getLocation(), diag::note_ambiguous_member_found); } @@ -2233,9 +2255,9 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, bool RValueThis, bool ConstThis, bool VolatileThis) { - RD = RD->getDefinition(); - assert((RD && !RD->isBeingDefined()) && + assert(CanDeclareSpecialMemberFunction(RD) && "doing special member lookup into record that isn't fully complete"); + RD = RD->getDefinition(); if (RValueThis || ConstThis || VolatileThis) assert((SM == CXXCopyAssignment || SM == CXXMoveAssignment) && "constructors and destructors always have unqualified lvalue this"); @@ -2265,7 +2287,7 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, SpecialMemberCache.InsertNode(Result, InsertPoint); if (SM == CXXDestructor) { - if (!RD->hasDeclaredDestructor()) + if (RD->needsImplicitDestructor()) DeclareImplicitDestructor(RD); CXXDestructorDecl *DD = RD->getDestructor(); assert(DD && "record without a destructor"); @@ -2294,15 +2316,15 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, } else { if (SM == CXXCopyConstructor || SM == CXXMoveConstructor) { Name = Context.DeclarationNames.getCXXConstructorName(CanTy); - if (!RD->hasDeclaredCopyConstructor()) + if (RD->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(RD); - if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveConstructor()) + if (getLangOpts().CPlusPlus11 && RD->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(RD); } else { Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); - if (!RD->hasDeclaredCopyAssignment()) + if (RD->needsImplicitCopyAssignment()) DeclareImplicitCopyAssignment(RD); - if (getLangOpts().CPlusPlus0x && RD->needsImplicitMoveAssignment()) + if (getLangOpts().CPlusPlus11 && RD->needsImplicitMoveAssignment()) DeclareImplicitMoveAssignment(RD); } @@ -2345,12 +2367,11 @@ Sema::SpecialMemberOverloadResult *Sema::LookupSpecialMember(CXXRecordDecl *RD, // 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; + DeclContext::lookup_result R = RD->lookup(Name); - llvm::tie(I, E) = RD->lookup(Name); - assert((I != E) && + assert(!R.empty() && "lookup for a constructor or assignment operator was empty"); - for ( ; I != E; ++I) { + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { Decl *Cand = *I; if (Cand->isInvalidDecl()) @@ -2451,12 +2472,12 @@ CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class, /// \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 (CanDeclareSpecialMemberFunction(Class)) { if (Class->needsImplicitDefaultConstructor()) DeclareImplicitDefaultConstructor(Class); - if (!Class->hasDeclaredCopyConstructor()) + if (Class->needsImplicitCopyConstructor()) DeclareImplicitCopyConstructor(Class); - if (getLangOpts().CPlusPlus0x && Class->needsImplicitMoveConstructor()) + if (getLangOpts().CPlusPlus11 && Class->needsImplicitMoveConstructor()) DeclareImplicitMoveConstructor(Class); } @@ -2544,7 +2565,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, if (FD->getNumParams() == 1 && FD->getParamDecl(0)->getType()->getAs<PointerType>()) IsRaw = true; - else { + else if (FD->getNumParams() == ArgTys.size()) { IsExactMatch = true; for (unsigned ArgIdx = 0; ArgIdx != ArgTys.size(); ++ArgIdx) { QualType ParamTy = FD->getParamDecl(ArgIdx)->getType(); @@ -2690,8 +2711,9 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, // 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) { + DeclContext::lookup_result R = (*NS)->lookup(Name); + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); 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. @@ -2850,8 +2872,10 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, for (DeclContext::all_lookups_iterator L = Ctx->lookups_begin(), LEnd = Ctx->lookups_end(); L != LEnd; ++L) { - for (DeclContext::lookup_result R = *L; R.first != R.second; ++R.first) { - if (NamedDecl *ND = dyn_cast<NamedDecl>(*R.first)) { + DeclContext::lookup_result R = *L; + for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; + ++I) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(*I)) { if ((ND = Result.getAcceptableDecl(ND))) { Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass); Visited.add(ND); @@ -2918,10 +2942,12 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, // 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()) { + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IFace->visible_categories_begin(), + CatEnd = IFace->visible_categories_end(); + Cat != CatEnd; ++Cat) { ShadowContextRAII Shadow(Visited); - LookupVisibleDecls(Category, Result, QualifiedNameLookup, false, + LookupVisibleDecls(*Cat, Result, QualifiedNameLookup, false, Consumer, Visited); } @@ -3135,7 +3161,7 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, namespace { -typedef llvm::SmallVector<TypoCorrection, 1> TypoResultList; +typedef SmallVector<TypoCorrection, 1> TypoResultList; typedef llvm::StringMap<TypoResultList, llvm::BumpPtrAllocator> TypoResultsMap; typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap; @@ -3560,7 +3586,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, Consumer.addKeywordResult("typename"); Consumer.addKeywordResult("wchar_t"); - if (SemaRef.getLangOpts().CPlusPlus0x) { + if (SemaRef.getLangOpts().CPlusPlus11) { Consumer.addKeywordResult("char16_t"); Consumer.addKeywordResult("char32_t"); Consumer.addKeywordResult("constexpr"); @@ -3599,7 +3625,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, cast<CXXMethodDecl>(SemaRef.CurContext)->isInstance()) Consumer.addKeywordResult("this"); - if (SemaRef.getLangOpts().CPlusPlus0x) { + if (SemaRef.getLangOpts().CPlusPlus11) { Consumer.addKeywordResult("alignof"); Consumer.addKeywordResult("nullptr"); } @@ -3656,7 +3682,7 @@ static void AddKeywordsToConsumer(Sema &SemaRef, if (SemaRef.getLangOpts().CPlusPlus) { Consumer.addKeywordResult("using"); - if (SemaRef.getLangOpts().CPlusPlus0x) + if (SemaRef.getLangOpts().CPlusPlus11) Consumer.addKeywordResult("static_assert"); } } @@ -3731,6 +3757,17 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (!ActiveTemplateInstantiations.empty()) return TypoCorrection(); + // Don't try to correct 'super'. + if (S && S->isInObjcMethodScope() && Typo == getSuperIdentifier()) + return TypoCorrection(); + + // This is for testing. + if (Diags.getWarnOnSpellCheck()) { + unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning, + "spell-checking initiated for %0"); + Diag(TypoName.getLoc(), DiagID) << TypoName.getName(); + } + NamespaceSpecifierSet Namespaces(Context, CurContext, SS); TypoCorrectionConsumer Consumer(*this, Typo); @@ -3860,7 +3897,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, KnownNamespaces[ExternalKnownNamespaces[I]] = true; } - for (llvm::DenseMap<NamespaceDecl*, bool>::iterator + for (llvm::MapVector<NamespaceDecl*, bool>::iterator KNI = KnownNamespaces.begin(), KNIEnd = KnownNamespaces.end(); KNI != KNIEnd; ++KNI) @@ -3869,7 +3906,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Weed out any names that could not be found by name lookup or, if a // CorrectionCandidateCallback object was provided, failed validation. - llvm::SmallVector<TypoCorrection, 16> QualifiedResults; + SmallVector<TypoCorrection, 16> QualifiedResults; LookupResult TmpRes(*this, TypoName, LookupKind); TmpRes.suppressDiagnostics(); while (!Consumer.empty()) { @@ -3971,9 +4008,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, // Only perform the qualified lookups for C++ if (SearchNamespaces) { TmpRes.suppressDiagnostics(); - for (llvm::SmallVector<TypoCorrection, - 16>::iterator QRI = QualifiedResults.begin(), - QRIEnd = QualifiedResults.end(); + for (SmallVector<TypoCorrection, + 16>::iterator QRI = QualifiedResults.begin(), + QRIEnd = QualifiedResults.end(); QRI != QRIEnd; ++QRI) { for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(), NIEnd = Namespaces.end(); @@ -4094,7 +4131,7 @@ void TypoCorrection::addCorrectionDecl(NamedDecl *CDecl) { if (isKeyword()) CorrectionDecls.clear(); - CorrectionDecls.push_back(CDecl); + CorrectionDecls.push_back(CDecl->getUnderlyingDecl()); if (!CorrectionName) CorrectionName = CDecl->getDeclName(); @@ -4111,3 +4148,21 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const { return CorrectionName.getAsString(); } + +bool CorrectionCandidateCallback::ValidateCandidate(const TypoCorrection &candidate) { + if (!candidate.isResolved()) + return true; + + if (candidate.isKeyword()) + return WantTypeSpecifiers || WantExpressionKeywords || WantCXXNamedCasts || + WantRemainingKeywords || WantObjCSuper; + + for (TypoCorrection::const_decl_iterator CDecl = candidate.begin(), + CDeclEnd = candidate.end(); + CDecl != CDeclEnd; ++CDecl) { + if (!isa<TypeDecl>(*CDecl)) + return true; + } + + return WantTypeSpecifiers; +} diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 8d70860..c348a9c 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -13,16 +13,16 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/Initialization.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclObjC.h" -#include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/ASTMutationListener.h" -#include "clang/Lex/Lexer.h" +#include "clang/AST/ExprObjC.h" #include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" -#include "clang/Lex/Preprocessor.h" using namespace clang; @@ -112,6 +112,33 @@ static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) { return 0; } +/// \brief Check this Objective-C property against a property declared in the +/// given protocol. +static void +CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, + ObjCProtocolDecl *Proto, + llvm::SmallPtrSet<ObjCProtocolDecl *, 16> &Known) { + // Have we seen this protocol before? + if (!Known.insert(Proto)) + return; + + // Look for a property with the same name. + DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName()); + for (unsigned I = 0, N = R.size(); I != N; ++I) { + if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) { + S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier()); + return; + } + } + + // Check this property against any protocols we inherit. + for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), + PEnd = Proto->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(S, Prop, *P, Known); + } +} + Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, FieldDeclarator &FD, @@ -139,34 +166,31 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && !(Attributes & ObjCDeclSpec::DQ_PR_weak))); - // Proceed with constructing the ObjCPropertDecls. + // Proceed with constructing the ObjCPropertyDecls. ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext); - if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) + ObjCPropertyDecl *Res = 0; + if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { if (CDecl->IsClassExtension()) { - Decl *Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, + Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, FD, GetterSel, SetterSel, isAssign, isReadWrite, Attributes, ODS.getPropertyAttributes(), isOverridingProperty, TSI, MethodImplKind); - if (Res) { - CheckObjCPropertyAttributes(Res, AtLoc, Attributes, false); - if (getLangOpts().ObjCAutoRefCount) - checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res)); - } - ActOnDocumentableDecl(Res); - return Res; + if (!Res) + return 0; } - - ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, - GetterSel, SetterSel, - isAssign, isReadWrite, - Attributes, - ODS.getPropertyAttributes(), - TSI, MethodImplKind); - if (lexicalDC) - Res->setLexicalDeclContext(lexicalDC); + } + + if (!Res) { + Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, + GetterSel, SetterSel, isAssign, isReadWrite, + Attributes, ODS.getPropertyAttributes(), + TSI, MethodImplKind); + if (lexicalDC) + Res->setLexicalDeclContext(lexicalDC); + } // Validate the attributes on the @property. CheckObjCPropertyAttributes(Res, AtLoc, Attributes, @@ -176,6 +200,52 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, if (getLangOpts().ObjCAutoRefCount) checkARCPropertyDecl(*this, Res); + llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos; + if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { + // For a class, compare the property against a property in our superclass. + bool FoundInSuper = false; + if (ObjCInterfaceDecl *Super = IFace->getSuperClass()) { + DeclContext::lookup_result R = Super->lookup(Res->getDeclName()); + for (unsigned I = 0, N = R.size(); I != N; ++I) { + if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) { + DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier()); + FoundInSuper = true; + break; + } + } + } + + if (FoundInSuper) { + // Also compare the property against a property in our protocols. + for (ObjCInterfaceDecl::protocol_iterator P = IFace->protocol_begin(), + PEnd = IFace->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); + } + } else { + // Slower path: look in all protocols we referenced. + for (ObjCInterfaceDecl::all_protocol_iterator + P = IFace->all_referenced_protocol_begin(), + PEnd = IFace->all_referenced_protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); + } + } + } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { + for (ObjCCategoryDecl::protocol_iterator P = Cat->protocol_begin(), + PEnd = Cat->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); + } + } else { + ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl); + for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), + PEnd = Proto->protocol_end(); + P != PEnd; ++P) { + CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos); + } + } + ActOnDocumentableDecl(Res); return Res; } @@ -251,7 +321,7 @@ static unsigned getOwnershipRule(unsigned attr) { ObjCPropertyDecl::OBJC_PR_unsafe_unretained); } -Decl * +ObjCPropertyDecl * Sema::HandlePropertyInClassExtension(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, @@ -270,20 +340,22 @@ Sema::HandlePropertyInClassExtension(Scope *S, IdentifierInfo *PropertyId = FD.D.getIdentifier(); ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); - if (CCPrimary) + 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)) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = CCPrimary->known_extensions_begin(), + ExtEnd = CCPrimary->known_extensions_end(); + Ext != ExtEnd; ++Ext) { + if (ObjCPropertyDecl *prevDecl + = ObjCPropertyDecl::findPropertyDecl(*Ext, 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. @@ -296,6 +368,10 @@ Sema::HandlePropertyInClassExtension(Scope *S, PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); + if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); + if (Attributes & ObjCDeclSpec::DQ_PR_atomic) + PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); // Set setter/getter selector name. Needed later. PDecl->setGetterName(GetterSel); PDecl->setSetterName(SetterSel); @@ -577,20 +653,20 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, switch (propertyLifetime) { case Qualifiers::OCL_Strong: - S.Diag(propertyImplLoc, diag::err_arc_strong_property_ownership) + S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership) << property->getDeclName() << ivar->getDeclName() << ivarLifetime; break; case Qualifiers::OCL_Weak: - S.Diag(propertyImplLoc, diag::error_weak_property) + S.Diag(ivar->getLocation(), diag::error_weak_property) << property->getDeclName() << ivar->getDeclName(); break; case Qualifiers::OCL_ExplicitNone: - S.Diag(propertyImplLoc, diag::err_arc_assign_property_ownership) + S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership) << property->getDeclName() << ivar->getDeclName() << ((property->getPropertyAttributesAsWritten() @@ -606,6 +682,8 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, } S.Diag(property->getLocation(), diag::note_property_declare); + if (propertyImplLoc.isValid()) + S.Diag(propertyImplLoc, diag::note_property_synthesize); } /// setImpliedPropertyAttributeForReadOnlyProperty - @@ -644,16 +722,18 @@ DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl, ObjCPropertyDecl *property) { unsigned Attributes = property->getPropertyAttributesAsWritten(); bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly); - for (const ObjCCategoryDecl *CDecl = ClassDecl->getFirstClassExtension(); - CDecl; CDecl = CDecl->getNextClassExtension()) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = ClassDecl->known_extensions_begin(), + ExtEnd = ClassDecl->known_extensions_end(); + Ext != ExtEnd; ++Ext) { ObjCPropertyDecl *ClassExtProperty = 0; - for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(), - E = CDecl->prop_end(); P != E; ++P) { - if ((*P)->getIdentifier() == property->getIdentifier()) { - ClassExtProperty = *P; + DeclContext::lookup_result R = Ext->lookup(property->getDeclName()); + for (unsigned I = 0, N = R.size(); I != N; ++I) { + ClassExtProperty = dyn_cast<ObjCPropertyDecl>(R[0]); + if (ClassExtProperty) break; - } } + if (ClassExtProperty) { warn = false; unsigned classExtPropertyAttr = @@ -763,22 +843,40 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, return 0; } } - if (Synthesize&& (PIkind & ObjCPropertyDecl::OBJC_PR_readonly) && property->hasAttr<IBOutletAttr>() && !AtLoc.isValid()) { - Diag(IC->getLocation(), diag::warn_auto_readonly_iboutlet_property); - Diag(property->getLocation(), diag::note_property_declare); - SourceLocation readonlyLoc; - if (LocPropertyAttribute(Context, "readonly", - property->getLParenLoc(), readonlyLoc)) { - SourceLocation endLoc = - readonlyLoc.getLocWithOffset(strlen("readonly")-1); - SourceRange ReadonlySourceRange(readonlyLoc, endLoc); - Diag(property->getLocation(), - diag::note_auto_readonly_iboutlet_fixup_suggest) << - FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite"); + bool ReadWriteProperty = false; + // Search into the class extensions and see if 'readonly property is + // redeclared 'readwrite', then no warning is to be issued. + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = IDecl->known_extensions_begin(), + ExtEnd = IDecl->known_extensions_end(); Ext != ExtEnd; ++Ext) { + DeclContext::lookup_result R = Ext->lookup(property->getDeclName()); + if (!R.empty()) + if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) { + PIkind = ExtProp->getPropertyAttributesAsWritten(); + if (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) { + ReadWriteProperty = true; + break; + } + } + } + + if (!ReadWriteProperty) { + Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property) + << property->getName(); + SourceLocation readonlyLoc; + if (LocPropertyAttribute(Context, "readonly", + property->getLParenLoc(), readonlyLoc)) { + SourceLocation endLoc = + readonlyLoc.getLocWithOffset(strlen("readonly")-1); + SourceRange ReadonlySourceRange(readonlyLoc, endLoc); + Diag(property->getLocation(), + diag::note_auto_readonly_iboutlet_fixup_suggest) << + FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite"); + } } } @@ -1036,6 +1134,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, MarkDeclRefReferenced(SelfExpr); Expr *IvarRefExpr = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, + Ivar->getLocation(), SelfExpr, true, true); ExprResult Res = PerformCopyInitialization(InitializedEntity::InitializeResult( @@ -1071,6 +1170,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, MarkDeclRefReferenced(SelfExpr); Expr *lhs = new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, + Ivar->getLocation(), SelfExpr, true, true); ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); ParmVarDecl *Param = (*P); @@ -1198,15 +1298,21 @@ Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, } if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) - != (SAttr & 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(SuperProperty->getLocation(), diag::note_property_declare); + } + if (Property->getSetterName() != SuperProperty->getSetterName()) { Diag(Property->getLocation(), diag::warn_property_attribute) << Property->getDeclName() << "setter" << inheritedName; - if (Property->getGetterName() != SuperProperty->getGetterName()) + Diag(SuperProperty->getLocation(), diag::note_property_declare); + } + if (Property->getGetterName() != SuperProperty->getGetterName()) { Diag(Property->getLocation(), diag::warn_property_attribute) << Property->getDeclName() << "getter" << inheritedName; + Diag(SuperProperty->getLocation(), diag::note_property_declare); + } QualType LHSType = Context.getCanonicalType(SuperProperty->getType()); @@ -1270,119 +1376,56 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 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); +Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, ObjCProtocolDecl *PDecl) { + if (!CDecl) + return; + + // Category case. + if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { + // FIXME: We should perform this check when the property in the category + // is declared. 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()); + ObjCPropertyDecl *ProtoProp = *P; + DeclContext::lookup_result R + = CatDecl->lookup(ProtoProp->getDeclName()); + for (unsigned I = 0, N = R.size(); I != N; ++I) { + if (ObjCPropertyDecl *CatProp = dyn_cast<ObjCPropertyDecl>(R[I])) { + if (CatProp != ProtoProp) { + // Property protocol already exist in class. Diagnose any mismatch. + DiagnosePropertyMismatch(CatProp, ProtoProp, + 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); + // Class + // FIXME: We should perform this check when the property in the class + // is declared. + ObjCInterfaceDecl *IDecl = cast<ObjCInterfaceDecl>(CDecl); + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *ProtoProp = *P; + DeclContext::lookup_result R + = IDecl->lookup(ProtoProp->getDeclName()); + for (unsigned I = 0, N = R.size(); I != N; ++I) { + if (ObjCPropertyDecl *ClassProp = dyn_cast<ObjCPropertyDecl>(R[I])) { + if (ClassProp != ProtoProp) { + // Property protocol already exist in class. Diagnose any mismatch. + DiagnosePropertyMismatch(ClassProp, ProtoProp, + PDecl->getIdentifier()); + } + } } - 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); } } @@ -1402,14 +1445,14 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, // 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())) + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = IDecl->visible_categories_begin(), + CatEnd = IDecl->visible_categories_end(); + Cat != CatEnd; ++Cat) { + if (Cat->getInstanceMethod(PDecl->getSetterName())) return false; ObjCPropertyDecl *P = - Category->FindPropertyDeclaration(PDecl->getIdentifier()); + Cat->FindPropertyDeclaration(PDecl->getIdentifier()); if (P && !P->isReadOnly()) return false; } @@ -1438,7 +1481,7 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, } /// CollectImmediateProperties - This routine collects all properties in -/// the class and its conforming protocols; but not those it its super class. +/// the class and its conforming protocols; but not those in its super class. void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, ObjCContainerDecl::PropertyMap &PropMap, ObjCContainerDecl::PropertyMap &SuperPropMap) { @@ -1493,36 +1536,84 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, ObjCInterfaceDecl::PropertyMap &PropMap) { if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { + ObjCInterfaceDecl::PropertyDeclOrder PO; while (SDecl) { - SDecl->collectPropertiesToImplement(PropMap); + SDecl->collectPropertiesToImplement(PropMap, PO); SDecl = SDecl->getSuperClass(); } } } +/// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is +/// an ivar synthesized for 'Method' and 'Method' is a property accessor +/// declared in class 'IFace'. +bool +Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, + ObjCMethodDecl *Method, ObjCIvarDecl *IV) { + if (!IV->getSynthesize()) + return false; + ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(), + Method->isInstanceMethod()); + if (!IMD || !IMD->isPropertyAccessor()) + return false; + + // look up a property declaration whose one of its accessors is implemented + // by this method. + for (ObjCContainerDecl::prop_iterator P = IFace->prop_begin(), + E = IFace->prop_end(); P != E; ++P) { + ObjCPropertyDecl *property = *P; + if ((property->getGetterName() == IMD->getSelector() || + property->getSetterName() == IMD->getSelector()) && + (property->getPropertyIvarDecl() == IV)) + return true; + } + return false; +} + + /// \brief Default synthesizes all properties which must be synthesized /// in class's \@implementation. void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCInterfaceDecl *IDecl) { ObjCInterfaceDecl::PropertyMap PropMap; - IDecl->collectPropertiesToImplement(PropMap); + ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder; + IDecl->collectPropertiesToImplement(PropMap, PropertyOrder); if (PropMap.empty()) return; ObjCInterfaceDecl::PropertyMap SuperPropMap; CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); - for (ObjCInterfaceDecl::PropertyMap::iterator - P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { - ObjCPropertyDecl *Prop = P->second; + for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) { + ObjCPropertyDecl *Prop = PropertyOrder[i]; // If property to be implemented in the super class, ignore. - if (SuperPropMap[Prop->getIdentifier()]) + if (SuperPropMap[Prop->getIdentifier()]) { + ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()]; + if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) && + (PropInSuperClass->getPropertyAttributes() & + ObjCPropertyDecl::OBJC_PR_readonly) && + !IMPDecl->getInstanceMethod(Prop->getSetterName()) && + !IDecl->HasUserDeclaredSetterMethod(Prop)) { + Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property) + << Prop->getIdentifier()->getName(); + Diag(PropInSuperClass->getLocation(), diag::note_property_declare); + } continue; + } // Is there a matching property synthesize/dynamic? if (Prop->isInvalidDecl() || - Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || - IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) + Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) continue; + if (ObjCPropertyImplDecl *PID = + IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { + if (PID->getPropertyDecl() != Prop) { + Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) + << Prop->getIdentifier()->getName(); + if (!PID->getLocation().isInvalid()) + Diag(PID->getLocation(), diag::note_property_synthesize); + } + continue; + } // Property may have been synthesized by user. if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) continue; @@ -1571,12 +1662,25 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl *CDecl, const SelectorSet &InsMap) { - ObjCContainerDecl::PropertyMap SuperPropMap; - if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) - CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); + ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; + ObjCInterfaceDecl *IDecl; + // Gather properties which need not be implemented in this class + // or category. + if (!(IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))) + if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { + // For categories, no need to implement properties declared in + // its primary class (and its super classes) if property is + // declared in one of those containers. + if ((IDecl = C->getClassInterface())) { + ObjCInterfaceDecl::PropertyDeclOrder PO; + IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO); + } + } + if (IDecl) + CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap); ObjCContainerDecl::PropertyMap PropMap; - CollectImmediateProperties(CDecl, PropMap, SuperPropMap); + CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap); if (PropMap.empty()) return; @@ -1592,7 +1696,8 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, // Is there a matching propery synthesize/dynamic? if (Prop->isInvalidDecl() || Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || - PropImplMap.count(Prop) || Prop->hasAttr<UnavailableAttr>()) + PropImplMap.count(Prop) || + Prop->getAvailability() == AR_Unavailable) continue; if (!InsMap.count(Prop->getGetterName())) { Diag(IMPDecl->getLocation(), @@ -1829,6 +1934,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, if (property->hasAttr<NSReturnsNotRetainedAttr>()) GetterMethod->addAttr( ::new (Context) NSReturnsNotRetainedAttr(Loc, Context)); + + if (getLangOpts().ObjCAutoRefCount) + CheckARCMethodDecl(GetterMethod); } else // A user declared getter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation @@ -1866,7 +1974,6 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, property->getType().getUnqualifiedType(), /*TInfo=*/0, SC_None, - SC_None, 0); SetterMethod->setMethodParams(Context, Argument, ArrayRef<SourceLocation>()); @@ -1878,6 +1985,11 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, // and the real context should be the same. if (lexicalDC) SetterMethod->setLexicalDeclContext(lexicalDC); + + // It's possible for the user to have set a very odd custom + // setter selector that causes it to have a method family. + if (getLangOpts().ObjCAutoRefCount) + CheckARCMethodDecl(SetterMethod); } else // A user declared setter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp new file mode 100644 index 0000000..b8acb2d --- /dev/null +++ b/lib/Sema/SemaOpenMP.cpp @@ -0,0 +1,181 @@ +//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// \brief This file implements semantic analysis for OpenMP directives and +/// clauses +/// +//===----------------------------------------------------------------------===// + +#include "clang/Basic/OpenMPKinds.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclOpenMP.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +using namespace clang; + +namespace { + + class VarDeclFilterCCC : public CorrectionCandidateCallback { + private: + Sema &Actions; + public: + VarDeclFilterCCC(Sema &S) : Actions(S) { } + virtual bool ValidateCandidate(const TypoCorrection &Candidate) { + NamedDecl *ND = Candidate.getCorrectionDecl(); + if (VarDecl *VD = dyn_cast_or_null<VarDecl>(ND)) { + return VD->hasGlobalStorage() && + Actions.isDeclInScope(ND, Actions.getCurLexicalContext(), + Actions.getCurScope()); + } + return false; + } + }; +} +Sema::DeclGroupPtrTy Sema::ActOnOpenMPThreadprivateDirective( + SourceLocation Loc, + Scope *CurScope, + ArrayRef<DeclarationNameInfo> IdList) { + SmallVector<DeclRefExpr *, 5> Vars; + for (ArrayRef<DeclarationNameInfo>::iterator I = IdList.begin(), + E = IdList.end(); + I != E; ++I) { + LookupResult Lookup(*this, *I, LookupOrdinaryName); + LookupParsedName(Lookup, CurScope, NULL, true); + + if (Lookup.isAmbiguous()) + continue; + + VarDecl *VD; + if (!Lookup.isSingleResult()) { + VarDeclFilterCCC Validator(*this); + TypoCorrection Corrected = CorrectTypo(*I, LookupOrdinaryName, CurScope, + 0, Validator); + std::string CorrectedStr = Corrected.getAsString(getLangOpts()); + std::string CorrectedQuotedStr = Corrected.getQuoted(getLangOpts()); + if (Lookup.empty()) { + if (Corrected.isResolved()) { + Diag(I->getLoc(), diag::err_undeclared_var_use_suggest) + << I->getName() << CorrectedQuotedStr + << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr); + } else { + Diag(I->getLoc(), diag::err_undeclared_var_use) + << I->getName(); + } + } else { + Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest) + << I->getName() << Corrected.isResolved() << CorrectedQuotedStr + << FixItHint::CreateReplacement(I->getLoc(), CorrectedStr); + } + if (!Corrected.isResolved()) continue; + VD = Corrected.getCorrectionDeclAs<VarDecl>(); + } else { + if (!(VD = Lookup.getAsSingle<VarDecl>())) { + Diag(I->getLoc(), diag::err_omp_expected_var_arg_suggest) + << I->getName() << 0; + Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at); + continue; + } + } + + // OpenMP [2.9.2, Syntax, C/C++] + // Variables must be file-scope, namespace-scope, or static block-scope. + if (!VD->hasGlobalStorage()) { + Diag(I->getLoc(), diag::err_omp_global_var_arg) + << getOpenMPDirectiveName(OMPD_threadprivate) + << !VD->isStaticLocal(); + Diag(VD->getLocation(), diag::note_forward_declaration) << VD; + continue; + } + + // OpenMP [2.9.2, Restrictions, C/C++, p.2] + // A threadprivate directive for file-scope variables must appear outside + // any definition or declaration. + // OpenMP [2.9.2, Restrictions, C/C++, p.3] + // A threadprivate directive for static class member variables must appear + // in the class definition, in the same scope in which the member + // variables are declared. + // OpenMP [2.9.2, Restrictions, C/C++, p.4] + // A threadprivate directive for namespace-scope variables must appear + // outside any definition or declaration other than the namespace + // definition itself. + // OpenMP [2.9.2, Restrictions, C/C++, p.6] + // A threadprivate directive for static block-scope variables must appear + // in the scope of the variable and not in a nested scope. + NamedDecl *ND = cast<NamedDecl>(VD); + if (!isDeclInScope(ND, getCurLexicalContext(), CurScope)) { + Diag(I->getLoc(), diag::err_omp_var_scope) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + Diag(VD->getLocation(), diag::note_forward_declaration) << VD; + continue; + } + + // OpenMP [2.9.2, Restrictions, C/C++, p.2-6] + // A threadprivate directive must lexically precede all references to any + // of the variables in its list. + if (VD->isUsed()) { + Diag(I->getLoc(), diag::err_omp_var_used) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD; + continue; + } + + QualType ExprType = VD->getType().getNonReferenceType(); + DeclRefExpr *Var = cast<DeclRefExpr>(BuildDeclRefExpr(VD, + ExprType, + VK_RValue, + I->getLoc()).take()); + Vars.push_back(Var); + } + if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, Vars)) { + CurContext->addDecl(D); + return DeclGroupPtrTy::make(DeclGroupRef(D)); + } + return DeclGroupPtrTy(); +} + +OMPThreadPrivateDecl *Sema::CheckOMPThreadPrivateDecl( + SourceLocation Loc, + ArrayRef<DeclRefExpr *> VarList) { + SmallVector<DeclRefExpr *, 5> Vars; + for (ArrayRef<DeclRefExpr *>::iterator I = VarList.begin(), + E = VarList.end(); + I != E; ++I) { + VarDecl *VD = cast<VarDecl>((*I)->getDecl()); + SourceLocation ILoc = (*I)->getLocation(); + + // OpenMP [2.9.2, Restrictions, C/C++, p.10] + // A threadprivate variable must not have an incomplete type. + if (RequireCompleteType(ILoc, VD->getType(), + diag::err_omp_incomplete_type)) { + continue; + } + + // OpenMP [2.9.2, Restrictions, C/C++, p.10] + // A threadprivate variable must not have a reference type. + if (VD->getType()->isReferenceType()) { + Diag(ILoc, diag::err_omp_ref_type_arg) + << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType(); + Diag(VD->getLocation(), diag::note_forward_declaration) << VD; + continue; + } + + // Check if threadspecified is set. + if (VD->isThreadSpecified()) { + Diag(ILoc, diag::err_omp_var_thread_local) << VD; + Diag(VD->getLocation(), diag::note_forward_declaration) << VD; + continue; + } + + Vars.push_back(*I); + } + return Vars.empty() ? + 0 : OMPThreadPrivateDecl::Create(Context, + getCurLexicalContext(), + Loc, Vars); +} diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 9111878..89d495d 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1,4 +1,4 @@ -//===--- SemaOverload.cpp - C++ Overloading ---------------------*- C++ -*-===// +//===--- SemaOverload.cpp - C++ Overloading -------------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,13 +11,7 @@ // //===----------------------------------------------------------------------===// -#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/Sema/Overload.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" @@ -25,26 +19,37 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeOrdering.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/STLExtras.h" #include <algorithm> namespace clang { using namespace sema; -/// A convenience routine for creating a decayed reference to a -/// function. +/// A convenience routine for creating a decayed reference to a function. static ExprResult -CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates, +CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, NamedDecl *FoundDecl, + bool HadMultipleCandidates, SourceLocation Loc = SourceLocation(), const DeclarationNameLoc &LocInfo = DeclarationNameLoc()){ DeclRefExpr *DRE = new (S.Context) DeclRefExpr(Fn, false, Fn->getType(), VK_LValue, Loc, LocInfo); if (HadMultipleCandidates) DRE->setHadMultipleCandidates(true); + + S.MarkDeclRefReferenced(DRE); + S.DiagnoseUseOfDecl(FoundDecl, Loc); + ExprResult E = S.Owned(DRE); E = S.DefaultFunctionArrayConversion(E.take()); if (E.isInvalid()) @@ -535,12 +540,16 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { namespace { // Structure used by OverloadCandidate::DeductionFailureInfo to store - // template parameter and template argument information. - struct DFIParamWithArguments { - TemplateParameter Param; + // template argument information. + struct DFIArguments { TemplateArgument FirstArg; TemplateArgument SecondArg; }; + // Structure used by OverloadCandidate::DeductionFailureInfo to store + // template parameter and template argument information. + struct DFIParamWithArguments : DFIArguments { + TemplateParameter Param; + }; } /// \brief Convert from Sema's representation of template deduction information @@ -566,6 +575,15 @@ static MakeDeductionFailureInfo(ASTContext &Context, Result.Data = Info.Param.getOpaqueValue(); break; + case Sema::TDK_NonDeducedMismatch: { + // FIXME: Should allocate from normal heap so that we can free this later. + DFIArguments *Saved = new (Context) DFIArguments; + Saved->FirstArg = Info.FirstArg; + Saved->SecondArg = Info.SecondArg; + Result.Data = Saved; + break; + } + case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: { // FIXME: Should allocate from normal heap so that we can free this later. @@ -587,8 +605,11 @@ static MakeDeductionFailureInfo(ASTContext &Context, } break; - case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: + Result.Data = Info.Expression; + break; + + case Sema::TDK_MiscellaneousDeductionFailure: break; } @@ -604,10 +625,12 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_FailedOverloadResolution: break; case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: + case Sema::TDK_NonDeducedMismatch: // FIXME: Destroy the data? Data = 0; break; @@ -622,8 +645,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { break; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } } @@ -644,6 +666,8 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_SubstitutionFailure: + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: return TemplateParameter(); case Sema::TDK_Incomplete: @@ -655,8 +679,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { return static_cast<DFIParamWithArguments*>(Data)->Param; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } @@ -666,24 +689,25 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { TemplateArgumentList * OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { - case Sema::TDK_Success: - case Sema::TDK_Invalid: - 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_Success: + case Sema::TDK_Invalid: + 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: + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + return 0; - case Sema::TDK_SubstitutionFailure: - return static_cast<TemplateArgumentList*>(Data); + case Sema::TDK_SubstitutionFailure: + return static_cast<TemplateArgumentList*>(Data); - // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: - break; + // Unhandled + case Sema::TDK_MiscellaneousDeductionFailure: + break; } return 0; @@ -699,15 +723,16 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: + case Sema::TDK_FailedOverloadResolution: return 0; case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: - return &static_cast<DFIParamWithArguments*>(Data)->FirstArg; + case Sema::TDK_NonDeducedMismatch: + return &static_cast<DFIArguments*>(Data)->FirstArg; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } @@ -725,21 +750,31 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: + case Sema::TDK_FailedOverloadResolution: return 0; case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: - return &static_cast<DFIParamWithArguments*>(Data)->SecondArg; + case Sema::TDK_NonDeducedMismatch: + return &static_cast<DFIArguments*>(Data)->SecondArg; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } return 0; } +Expr * +OverloadCandidate::DeductionFailureInfo::getExpr() { + if (static_cast<Sema::TemplateDeductionResult>(Result) == + Sema::TDK_FailedOverloadResolution) + return static_cast<Expr*>(Data); + + return 0; +} + void OverloadCandidateSet::destroyCandidates() { for (iterator i = begin(), e = end(); i != e; ++i) { for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) @@ -885,7 +920,8 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, // function templates hide function templates with different // return types or template parameter lists. bool UseMemberUsingDeclRules = - (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord(); + (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() && + !New->getFriendObjectKind(); if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) { if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) { @@ -929,13 +965,21 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, 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()) +static bool canBeOverloaded(const FunctionDecl &D) { + if (D.getAttr<OverloadableAttr>()) + return true; + if (D.isExternC()) + return false; + + // Main cannot be overloaded (basic.start.main). + if (D.isMain()) return false; + return true; +} + +static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old, + bool UseUsingDeclRules) { FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); @@ -946,8 +990,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return true; // Is the function New an overload of the function Old? - QualType OldQType = Context.getCanonicalType(Old->getType()); - QualType NewQType = Context.getCanonicalType(New->getType()); + QualType OldQType = S.Context.getCanonicalType(Old->getType()); + QualType NewQType = S.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 @@ -968,7 +1012,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, if (OldQType != NewQType && (OldType->getNumArgs() != NewType->getNumArgs() || OldType->isVariadic() != NewType->isVariadic() || - !FunctionArgTypesAreEqual(OldType, NewType))) + !S.FunctionArgTypesAreEqual(OldType, NewType))) return true; // C++ [temp.over.link]p4: @@ -984,9 +1028,9 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // 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) || + (!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), + OldTemplate->getTemplateParameters(), + false, S.TPL_TemplateMatch) || OldType->getResultType() != NewType->getResultType())) return true; @@ -998,34 +1042,55 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, // 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); + 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); + !OldMethod->isStatic() && !NewMethod->isStatic()) { + if (OldMethod->getRefQualifier() != NewMethod->getRefQualifier()) { + if (!UseUsingDeclRules && + (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). + S.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) + << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); + S.Diag(OldMethod->getLocation(), diag::note_previous_declaration); + } + return true; } - return true; + // We may not have applied the implicit const for a constexpr member + // function yet (because we haven't yet resolved whether this is a static + // or non-static member function). Add it now, on the assumption that this + // is a redeclaration of OldMethod. + unsigned NewQuals = NewMethod->getTypeQualifiers(); + if (NewMethod->isConstexpr() && !isa<CXXConstructorDecl>(NewMethod)) + NewQuals |= Qualifiers::Const; + if (OldMethod->getTypeQualifiers() != NewQuals) + return true; } // The signatures match; this is not an overload. return false; } +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, + bool UseUsingDeclRules) { + if (!shouldTryToOverload(*this, New, Old, UseUsingDeclRules)) + return false; + + // If both of the functions are extern "C", then they are not + // overloads. + if (!canBeOverloaded(*Old) && !canBeOverloaded(*New)) + return false; + + return true; +} + /// \brief Checks availability of the function depending on the current /// function context. Inside an unavailable function, unavailability is ignored. /// @@ -1577,6 +1642,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // tryAtomicConversion has updated the standard conversion sequence // appropriately. return true; + } else if (ToType->isEventT() && + From->isIntegerConstantExpr(S.getASTContext()) && + (From->EvaluateKnownConstInt(S.getASTContext()) == 0)) { + SCS.Second = ICK_Zero_Event_Conversion; + FromType = ToType; } else { // No second conversion required. SCS.Second = ICK_Identity; @@ -1606,9 +1676,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, CanonTo = S.Context.getCanonicalType(ToType); if (CanonFrom.getLocalUnqualifiedType() == CanonTo.getLocalUnqualifiedType() && - (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers() - || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr() - || CanonFrom.getObjCLifetime() != CanonTo.getObjCLifetime())) { + CanonFrom.getLocalQualifiers() != CanonTo.getLocalQualifiers()) { FromType = ToType; CanonFrom = CanonTo; } @@ -1818,7 +1886,8 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { return true; // Half can be promoted to float. - if (FromBuiltin->getKind() == BuiltinType::Half && + if (!getLangOpts().NativeHalfType && + FromBuiltin->getKind() == BuiltinType::Half && ToBuiltin->getKind() == BuiltinType::Float) return true; } @@ -2880,8 +2949,8 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, UserDefinedConversionSequence &User, OverloadCandidateSet &CandidateSet, bool AllowExplicit) { - DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = S.LookupConstructors(To); + DeclContext::lookup_result R = S.LookupConstructors(To); + for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end(); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -2980,7 +3049,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, S.IsDerivedFrom(From->getType(), ToType))) ConstructorsOnly = true; - S.RequireCompleteType(From->getLocStart(), ToType, 0); + S.RequireCompleteType(From->getExprLoc(), ToType, 0); // RequireCompleteType may have returned true due to some invalid decl // during template instantiation, but ToType may be complete enough now // to try to recover. @@ -3008,8 +3077,8 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, ListInitializing = true; } - DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = S.LookupConstructors(ToRecordDecl); + DeclContext::lookup_result R = S.LookupConstructors(ToRecordDecl); + for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end(); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -3065,10 +3134,11 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, 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) { + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = FromRecordDecl->getVisibleConversionFunctions(); + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { DeclAccessPair FoundDecl = I.getPair(); NamedDecl *D = FoundDecl.getDecl(); CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); @@ -3198,7 +3268,7 @@ static ImplicitConversionSequence::CompareKind compareConversionFunctions(Sema &S, FunctionDecl *Function1, FunctionDecl *Function2) { - if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus0x) + if (!S.getLangOpts().ObjC1 || !S.getLangOpts().CPlusPlus11) return ImplicitConversionSequence::Indistinguishable; // Objective-C++: @@ -3868,6 +3938,15 @@ CompareDerivedToBaseConversions(Sema &S, return ImplicitConversionSequence::Indistinguishable; } +/// \brief Determine whether the given type is valid, e.g., it is not an invalid +/// C++ class. +static bool isTypeValid(QualType T) { + if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) + return !Record->isInvalidDecl(); + + return true; +} + /// CompareReferenceRelationship - Compare the two types T1 and T2 to /// determine whether they are reference-related, /// reference-compatible, reference-compatible with added @@ -3901,7 +3980,8 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, if (UnqualT1 == UnqualT2) { // Nothing to do. } else if (!RequireCompleteType(Loc, OrigT2, 0) && - IsDerivedFrom(UnqualT2, UnqualT1)) + isTypeValid(UnqualT1) && isTypeValid(UnqualT2) && + IsDerivedFrom(UnqualT2, UnqualT1)) DerivedToBase = true; else if (UnqualT1->isObjCObjectOrInterfaceType() && UnqualT2->isObjCObjectOrInterfaceType() && @@ -3959,10 +4039,11 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, = 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) { + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = T2RecordDecl->getVisibleConversionFunctions(); + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -4213,7 +4294,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, // 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.getLangOpts().CPlusPlus0x || + S.getLangOpts().CPlusPlus11 || (InitCategory.isPRValue() && !T2->isRecordType()); ICS.Standard.IsLvalueReference = !isRValRef; ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); @@ -4374,7 +4455,7 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, bool toStdInitializerList = false; QualType X; if (ToType->isArrayType()) - X = S.Context.getBaseElementType(ToType); + X = S.Context.getAsArrayType(ToType)->getElementType(); else toStdInitializerList = S.isStdInitializerList(ToType, &X); if (!X.isNull()) { @@ -4595,7 +4676,7 @@ static bool TryCopyInitialization(const CanQualType FromQTy, /// parameter of the given member function (@c Method) from the /// expression @p From. static ImplicitConversionSequence -TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, +TryObjectArgumentInitialization(Sema &S, QualType FromType, Expr::Classification FromClassification, CXXMethodDecl *Method, CXXRecordDecl *ActingContext) { @@ -4611,7 +4692,6 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, ImplicitConversionSequence ICS; // We need to have an object of class type. - QualType FromType = OrigFromType; if (const PointerType *PT = FromType->getAs<PointerType>()) { FromType = PT->getPointeeType(); @@ -4646,7 +4726,7 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, != FromTypeCanon.getLocalCVRQualifiers() && !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) { ICS.setBad(BadConversionSequence::bad_qualifiers, - OrigFromType, ImplicitParamType); + FromType, ImplicitParamType); return ICS; } @@ -4811,6 +4891,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_Identity: case ICK_Integral_Promotion: case ICK_Integral_Conversion: + case ICK_Zero_Event_Conversion: return true; case ICK_Boolean_Conversion: @@ -4857,7 +4938,7 @@ static bool CheckConvertedConstantConversions(Sema &S, ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE) { - assert(LangOpts.CPlusPlus0x && "converted constant expression outside C++11"); + assert(LangOpts.CPlusPlus11 && "converted constant expression outside C++11"); assert(T->isIntegralOrEnumerationType() && "unexpected converted const type"); if (checkPlaceholderForOverload(*this, From)) @@ -4939,7 +5020,7 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, } // Check the expression is a constant expression. - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; Expr::EvalResult Eval; Eval.Diag = &Notes; @@ -5104,15 +5185,15 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, // Look for a conversion to an integral or enumeration type. UnresolvedSet<4> ViableConversions; UnresolvedSet<4> ExplicitConversions; - const UnresolvedSetImpl *Conversions + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> Conversions = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); - bool HadMultipleCandidates = (Conversions->size() > 1); + bool HadMultipleCandidates + = (std::distance(Conversions.first, Conversions.second) > 1); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); - I != E; - ++I) { + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { if (isIntegralOrEnumerationType( @@ -5230,7 +5311,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, void Sema::AddOverloadCandidate(FunctionDecl *Function, DeclAccessPair FoundDecl, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, bool PartialOverloading, @@ -5353,7 +5434,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, /// \brief Add all of the function declarations in the given function set to /// the overload canddiate set. void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, TemplateArgumentListInfo *ExplicitTemplateArgs) { @@ -5428,7 +5509,7 @@ void Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, Expr::Classification ObjectClassification, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { const FunctionProtoType* Proto @@ -5532,7 +5613,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { if (!CandidateSet.isNewCandidate(MethodTmpl)) @@ -5582,7 +5663,7 @@ void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) @@ -5816,7 +5897,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, Expr *Object, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet) { if (!CandidateSet.isNewCandidate(Conversion)) return; @@ -6286,10 +6367,11 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, return; CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); - const UnresolvedSetImpl *Conversions - = ClassDecl->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); I != E; ++I) { + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = ClassDecl->getVisibleConversionFunctions(); + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = I.getDecl(); if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); @@ -6355,11 +6437,12 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { if (!ClassDecl->hasDefinition()) return VRQuals; - const UnresolvedSetImpl *Conversions = - ClassDecl->getVisibleConversionFunctions(); + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> + Conversions = ClassDecl->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); I != E; ++I) { + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = I.getDecl(); if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); @@ -7449,7 +7532,7 @@ public: S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet); } - if (S.getLangOpts().CPlusPlus0x) { + if (S.getLangOpts().CPlusPlus11) { for (BuiltinCandidateTypeSet::iterator Enum = CandidateTypes[ArgIdx].enumeration_begin(), EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); @@ -7667,7 +7750,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, bool Operator, SourceLocation Loc, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading) { @@ -8380,7 +8463,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, case Sema::TDK_SubstitutionFailure: { // Format the template argument list into the argument string. - llvm::SmallString<128> TemplateArgString; + SmallString<128> TemplateArgString; if (TemplateArgumentList *Args = Cand->DeductionFailure.getTemplateArgumentList()) { TemplateArgString = " "; @@ -8402,7 +8485,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, // Format the SFINAE diagnostic into the argument string. // FIXME: Add a general mechanism to include a PartialDiagnostic *'s // formatted message in another diagnostic. - llvm::SmallString<128> SFINAEArgString; + SmallString<128> SFINAEArgString; SourceRange R; if (PDiag) { SFINAEArgString = ": "; @@ -8416,10 +8499,25 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, return; } + case Sema::TDK_FailedOverloadResolution: { + OverloadExpr::FindResult R = + OverloadExpr::find(Cand->DeductionFailure.getExpr()); + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_failed_overload_resolution) + << R.Expression->getName(); + return; + } + + case Sema::TDK_NonDeducedMismatch: + // FIXME: Provide a source location to indicate what we couldn't match. + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch) + << *Cand->DeductionFailure.getFirstArg() + << *Cand->DeductionFailure.getSecondArg(); + 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: + case Sema::TDK_MiscellaneousDeductionFailure: S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); MaybeEmitInheritedConstructorNote(S, Fn); return; @@ -8597,6 +8695,7 @@ RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) { case Sema::TDK_SubstitutionFailure: case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_MiscellaneousDeductionFailure: return 3; case Sema::TDK_InstantiationDepth: @@ -8721,7 +8820,7 @@ struct CompareOverloadCandidatesForDisplay { /// CompleteNonViableCandidate - Normally, overload resolution only /// computes up to the first. Produces the FixIt set if possible. void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, - llvm::ArrayRef<Expr *> Args) { + ArrayRef<Expr *> Args) { assert(!Cand->Viable); // Don't do anything on failures other than bad conversion. @@ -8809,7 +8908,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, /// set. void OverloadCandidateSet::NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, StringRef Opc, SourceLocation OpLoc) { // Sort the candidates by viability and position. Sorting directly would @@ -9400,7 +9499,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( static void AddOverloadedCallCandidate(Sema &S, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool PartialOverloading, bool KnownValid) { @@ -9431,7 +9530,7 @@ static void AddOverloadedCallCandidate(Sema &S, /// \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, - llvm::ArrayRef<Expr *> Args, + ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool PartialOverloading) { @@ -9495,7 +9594,7 @@ static bool DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, const CXXScopeSpec &SS, LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs, - llvm::ArrayRef<Expr *> Args) { + ArrayRef<Expr *> Args) { if (SemaRef.ActiveTemplateInstantiations.empty() || !SS.isEmpty()) return false; @@ -9536,18 +9635,23 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, SemaRef.FindAssociatedClassesAndNamespaces(FnLoc, Args, 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; + DeclContext *Std = SemaRef.getStdNamespace(); + for (Sema::AssociatedNamespaceSet::iterator + it = AssociatedNamespaces.begin(), + end = AssociatedNamespaces.end(); it != end; ++it) { + // Never suggest declaring a function within namespace 'std'. + if (Std && Std->Encloses(*it)) + continue; + + // Never suggest declaring a function within a namespace with a reserved + // name, like __gnu_cxx. + NamespaceDecl *NS = dyn_cast<NamespaceDecl>(*it); + if (NS && + NS->getQualifiedNameAsString().find("__") != std::string::npos) + continue; + + SuggestedNamespaces.insert(*it); } SemaRef.Diag(R.getNameLoc(), diag::err_not_found_by_two_phase_lookup) @@ -9587,7 +9691,7 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, static bool DiagnoseTwoPhaseOperatorLookup(Sema &SemaRef, OverloadedOperatorKind Op, SourceLocation OpLoc, - llvm::ArrayRef<Expr *> Args) { + ArrayRef<Expr *> Args) { DeclarationName OpName = SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); LookupResult R(SemaRef, OpName, OpLoc, Sema::LookupOperatorName); @@ -9827,7 +9931,6 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, switch (OverloadResult) { case OR_Success: { FunctionDecl *FDecl = (*Best)->Function; - SemaRef.MarkFunctionReferenced(Fn->getExprLoc(), FDecl); SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl); SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()); Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); @@ -10015,8 +10118,6 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // We matched an overloaded operator. Build a call to that // operator. - MarkFunctionReferenced(OpLoc, FnDecl); - // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { CheckMemberOperatorAccess(OpLoc, Args[0], 0, Best->FoundDecl); @@ -10040,15 +10141,13 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, 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, + ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, Best->FoundDecl, HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -10240,8 +10339,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkFunctionReferenced(OpLoc, FnDecl); - // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { // Best->Access is only meaningful for class members. @@ -10282,8 +10379,6 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Args[1] = RHS = Arg1.takeAs<Expr>(); } - DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); - // Determine the result type. QualType ResultTy = FnDecl->getResultType(); ExprValueKind VK = Expr::getValueKindForType(ResultTy); @@ -10291,6 +10386,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Build the actual expression node. ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + Best->FoundDecl, HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -10304,6 +10400,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, FnDecl)) return ExprError(); + ArrayRef<const Expr *> ArgsArray(Args, 2); + // Cut off the implicit 'this'. + if (isa<CXXMethodDecl>(FnDecl)) + ArgsArray = ArgsArray.slice(1); + checkCall(FnDecl, ArgsArray, 0, isa<CXXMethodDecl>(FnDecl), OpLoc, + TheCall->getSourceRange(), VariadicDoesNotApply); + return MaybeBindToTemporary(TheCall); } else { // We matched a built-in operator. Convert the arguments, then @@ -10376,16 +10479,13 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (isImplicitlyDeleted(Best->Function)) { CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); Diag(OpLoc, diag::err_ovl_deleted_special_oper) - << getSpecialMember(Method) - << BinaryOperator::getOpcodeStr(Opc) - << getDeletedOrUnavailableSuffix(Best->Function); + << Context.getRecordType(Method->getParent()) + << getSpecialMember(Method); - if (getSpecialMember(Method) != CXXInvalid) { - // The user probably meant to call this special member. Just - // explain why it's deleted. - NoteDeletedFunction(Method); - return ExprError(); - } + // The user probably meant to call this special member. Just + // explain why it's deleted. + NoteDeletedFunction(Method); + return ExprError(); } else { Diag(OpLoc, diag::err_ovl_deleted_oper) << Best->Function->isDeleted() @@ -10463,10 +10563,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched an overloaded operator. Build a call to that // operator. - MarkFunctionReferenced(LLoc, FnDecl); - CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl); - DiagnoseUseOfDecl(Best->FoundDecl, LLoc); // Convert the arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); @@ -10498,6 +10595,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, DeclarationNameInfo OpLocInfo(OpName, LLoc); OpLocInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); ExprResult FnExpr = CreateFunctionRefExpr(*this, FnDecl, + Best->FoundDecl, HadMultipleCandidates, OpLocInfo.getLoc(), OpLocInfo.getInfo()); @@ -10715,7 +10813,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); - MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method); FoundDecl = Best->FoundDecl; CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl); DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc()); @@ -10880,10 +10977,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // 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 + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> Conversions = cast<CXXRecordDecl>(Record->getDecl())->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); I != E; ++I) { + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { NamedDecl *D = *I; CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) @@ -10989,9 +11087,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, RParenLoc); } - MarkFunctionReferenced(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 @@ -11025,7 +11121,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, DeclarationNameInfo OpLocInfo( Context.DeclarationNames.getCXXOperatorName(OO_Call), LParenLoc); OpLocInfo.setCXXOperatorNameRange(SourceRange(LParenLoc, RParenLoc)); - ExprResult NewFn = CreateFunctionRefExpr(*this, Method, + ExprResult NewFn = CreateFunctionRefExpr(*this, Method, Best->FoundDecl, HadMultipleCandidates, OpLocInfo.getLoc(), OpLocInfo.getInfo()); @@ -11190,9 +11286,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { return ExprError(); } - MarkFunctionReferenced(OpLoc, Best->Function); CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl); - DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); // Convert the object parameter. CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); @@ -11204,7 +11298,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { Base = BaseResult.take(); // Build the operator call. - ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, + ExprResult FnExpr = CreateFunctionRefExpr(*this, Method, Best->FoundDecl, HadMultipleCandidates, OpLoc); if (FnExpr.isInvalid()) return ExprError(); @@ -11259,10 +11353,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, } FunctionDecl *FD = Best->Function; - MarkFunctionReferenced(UDSuffixLoc, FD); - DiagnoseUseOfDecl(Best->FoundDecl, UDSuffixLoc); - - ExprResult Fn = CreateFunctionRefExpr(*this, FD, HadMultipleCandidates, + ExprResult Fn = CreateFunctionRefExpr(*this, FD, Best->FoundDecl, + HadMultipleCandidates, SuffixInfo.getLoc(), SuffixInfo.getInfo()); if (Fn.isInvalid()) diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index a8d75b2..b135507 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -31,10 +31,11 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/Initialization.h" #include "clang/AST/ExprObjC.h" +#include "clang/Basic/CharInfo.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -113,7 +114,7 @@ namespace { Expr *rebuildSpecific(ObjCPropertyRefExpr *refExpr) { // Fortunately, the constraint that we're rebuilding something // with a base limits the number of cases here. - assert(refExpr->getBase()); + assert(refExpr->isObjectReceiver()); if (refExpr->isExplicitProperty()) { return new (S.Context) @@ -562,8 +563,9 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) { if (const ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) { const StringRef thisPropertyName(prop->getName()); + // Try flipping the case of the first character. char front = thisPropertyName.front(); - front = islower(front) ? toupper(front) : tolower(front); + front = isLowercase(front) ? toUppercase(front) : toLowercase(front); SmallString<100> PropertyName = thisPropertyName; PropertyName[0] = front; IdentifierInfo *AltMember = &S.PP.getIdentifierTable().get(PropertyName); @@ -713,10 +715,9 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { // Explicit properties always have getters, but implicit ones don't. // Check that before proceeding. - if (RefExpr->isImplicitProperty() && - !RefExpr->getImplicitPropertyGetter()) { + if (RefExpr->isImplicitProperty() && !RefExpr->getImplicitPropertyGetter()) { S.Diag(RefExpr->getLocation(), diag::err_getter_not_found) - << RefExpr->getBase()->getType(); + << RefExpr->getSourceRange(); return ExprError(); } @@ -954,16 +955,15 @@ Sema::ObjCSubscriptKind // objective-C pointer type. UnresolvedSet<4> ViableConversions; UnresolvedSet<4> ExplicitConversions; - const UnresolvedSetImpl *Conversions + std::pair<CXXRecordDecl::conversion_iterator, + CXXRecordDecl::conversion_iterator> Conversions = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); int NoIntegrals=0, NoObjCIdPointers=0; SmallVector<CXXConversionDecl *, 4> ConversionDecls; - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); - I != E; - ++I) { + for (CXXRecordDecl::conversion_iterator + I = Conversions.first, E = Conversions.second; I != E; ++I) { if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) { QualType CT = Conversion->getConversionType().getNonReferenceType(); @@ -1087,7 +1087,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { : S.Context.getObjCIdType(), /*TInfo=*/0, SC_None, - SC_None, 0); AtIndexGetter->setMethodParams(S.Context, Argument, ArrayRef<SourceLocation>()); @@ -1202,7 +1201,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { S.Context.getObjCIdType(), /*TInfo=*/0, SC_None, - SC_None, 0); Params.push_back(object); ParmVarDecl *key = ParmVarDecl::Create(S.Context, AtIndexSetter, @@ -1213,7 +1211,6 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { : S.Context.getObjCIdType(), /*TInfo=*/0, SC_None, - SC_None, 0); Params.push_back(key); AtIndexSetter->setMethodParams(S.Context, Params, ArrayRef<SourceLocation>()); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index f55174e..ff1db82 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -12,21 +12,22 @@ //===----------------------------------------------------------------------===// #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/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/EvaluatedExprVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" #include "clang/AST/TypeLoc.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" @@ -35,9 +36,13 @@ using namespace clang; using namespace sema; -StmtResult Sema::ActOnExprStmt(FullExprArg expr) { - Expr *E = expr.get(); - if (!E) // FIXME: FullExprArg has no error state? +StmtResult Sema::ActOnExprStmt(ExprResult FE) { + if (FE.isInvalid()) + return StmtError(); + + FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), + /*DiscardedValue*/ true); + if (FE.isInvalid()) return StmtError(); // C99 6.8.3p2: The expression in an expression statement is evaluated as a @@ -45,10 +50,15 @@ StmtResult Sema::ActOnExprStmt(FullExprArg expr) { // operand, even incomplete types. // Same thing in for stmt first clause (when expr) and third clause. - return Owned(static_cast<Stmt*>(E)); + return Owned(static_cast<Stmt*>(FE.take())); } +StmtResult Sema::ActOnExprStmtError() { + DiscardCleanupsInEvaluationContext(); + return StmtError(); +} + StmtResult Sema::ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro) { return Owned(new (Context) NullStmt(SemiLoc, HasLeadingEmptyMacro)); @@ -125,7 +135,7 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) { // Suppress warnings when the operator, suspicious as it may be, comes from // a macro expansion. - if (Loc.isMacroID()) + if (S.SourceMgr.isMacroBodyExpansion(Loc)) return false; S.Diag(Loc, diag::warn_unused_comparison) @@ -152,12 +162,20 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { const Expr *E = dyn_cast_or_null<Expr>(S); if (!E) return; + SourceLocation ExprLoc = E->IgnoreParens()->getExprLoc(); + // In most cases, we don't want to warn if the expression is written in a + // macro body, or if the macro comes from a system header. If the offending + // expression is a call to a function with the warn_unused_result attribute, + // we warn no matter the location. Because of the order in which the various + // checks need to happen, we factor out the macro-related test here. + bool ShouldSuppress = + SourceMgr.isMacroBodyExpansion(ExprLoc) || + SourceMgr.isInSystemMacro(ExprLoc); const Expr *WarnExpr; SourceLocation Loc; SourceRange R1, R2; - if (SourceMgr.isInSystemMacro(E->getExprLoc()) || - !E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context)) + if (!E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context)) return; // If this is a GNU statement expression expanded from a macro, it is probably @@ -185,12 +203,16 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { 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. + // a more specific message to make it clear what is happening. If the call + // is written in a macro body, only warn if it has the warn_unused_result + // attribute. if (const Decl *FD = CE->getCalleeDecl()) { if (FD->getAttr<WarnUnusedResultAttr>()) { Diag(Loc, diag::warn_unused_result) << R1 << R2; return; } + if (ShouldSuppress) + return; if (FD->getAttr<PureAttr>()) { Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure"; return; @@ -200,7 +222,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { return; } } - } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { + } else if (ShouldSuppress) + return; + + if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { if (getLangOpts().ObjCAutoRefCount && ME->isDelegateInitCall()) { Diag(Loc, diag::err_arc_unused_init_message) << R1; return; @@ -229,7 +254,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { // We really do want to use the non-canonical type here. if (T == Context.VoidPtrTy) { - PointerTypeLoc TL = cast<PointerTypeLoc>(TI->getTypeLoc()); + PointerTypeLoc TL = TI->getTypeLoc().castAs<PointerTypeLoc>(); Diag(Loc, diag::warn_unused_voidptr) << FixItHint::CreateRemoval(TL.getStarLoc()); @@ -298,7 +323,9 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, DiagnoseEmptyLoopBody(Elts[i], Elts[i + 1]); } - return Owned(new (Context) CompoundStmt(Context, Elts, NumElts, L, R)); + return Owned(new (Context) CompoundStmt(Context, + llvm::makeArrayRef(Elts, NumElts), + L, R)); } StmtResult @@ -312,7 +339,7 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, return StmtError(); } - if (!getLangOpts().CPlusPlus0x) { + if (!getLangOpts().CPlusPlus11) { // C99 6.8.4.2p3: The expression shall be an integer constant. // However, GCC allows any evaluatable integer expression. if (!LHSVal->isTypeDependent() && !LHSVal->isValueDependent()) { @@ -328,6 +355,12 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, // Recover from an error by just forgetting about it. } } + + LHSVal = ActOnFinishFullExpr(LHSVal, LHSVal->getExprLoc(), false, + getLangOpts().CPlusPlus11).take(); + if (RHSVal) + RHSVal = ActOnFinishFullExpr(RHSVal, RHSVal->getExprLoc(), false, + getLangOpts().CPlusPlus11).take(); CaseStmt *CS = new (Context) CaseStmt(LHSVal, RHSVal, CaseLoc, DotDotDotLoc, ColonLoc); @@ -390,6 +423,13 @@ StmtResult Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar, Stmt *thenStmt, SourceLocation ElseLoc, Stmt *elseStmt) { + // If the condition was invalid, discard the if statement. We could recover + // better by replacing it with a valid expr, but don't do that yet. + if (!CondVal.get() && !CondVar) { + getCurFunction()->setHasDroppedStmt(); + return StmtError(); + } + ExprResult CondResult(CondVal.release()); VarDecl *ConditionVar = 0; @@ -595,8 +635,7 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, Expr *Cond, Cond = CondResult.take(); if (!CondVar) { - CheckImplicitConversions(Cond, SwitchLoc); - CondResult = MaybeCreateExprWithCleanups(Cond); + CondResult = ActOnFinishFullExpr(Cond, SwitchLoc); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); @@ -710,7 +749,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, llvm::APSInt LoVal; - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { // C++11 [stmt.switch]p2: the constant-expression shall be a converted // constant expression of the promoted type of the switch condition. ExprResult ConvLo = @@ -792,7 +831,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, if (DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(CurrCase)) { CurrString = DeclRef->getDecl()->getName(); } - llvm::SmallString<16> CaseValStr; + SmallString<16> CaseValStr; CaseVals[i-1].first.toString(CaseValStr); if (PrevString == CurrString) @@ -830,7 +869,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, Stmt *Switch, Expr *Hi = CR->getRHS(); llvm::APSInt HiVal; - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { // C++11 [stmt.switch]p2: the constant-expression shall be a converted // constant expression of the promoted type of the switch condition. ExprResult ConvHi = @@ -1149,12 +1188,11 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, assert(Cond && "ActOnDoStmt(): missing expression"); ExprResult CondResult = CheckBooleanCondition(Cond, DoLoc); - if (CondResult.isInvalid() || CondResult.isInvalid()) + if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); - CheckImplicitConversions(Cond, DoLoc); - CondResult = MaybeCreateExprWithCleanups(Cond); + CondResult = ActOnFinishFullExpr(Cond, DoLoc); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.take(); @@ -1170,13 +1208,13 @@ namespace { // of the excluded constructs are used. class DeclExtractor : public EvaluatedExprVisitor<DeclExtractor> { llvm::SmallPtrSet<VarDecl*, 8> &Decls; - llvm::SmallVector<SourceRange, 10> &Ranges; + SmallVector<SourceRange, 10> &Ranges; bool Simple; public: typedef EvaluatedExprVisitor<DeclExtractor> Inherited; DeclExtractor(Sema &S, llvm::SmallPtrSet<VarDecl*, 8> &Decls, - llvm::SmallVector<SourceRange, 10> &Ranges) : + SmallVector<SourceRange, 10> &Ranges) : Inherited(S.Context), Decls(Decls), Ranges(Ranges), @@ -1325,7 +1363,7 @@ public: PartialDiagnostic PDiag = S.PDiag(diag::warn_variables_not_in_loop_body); llvm::SmallPtrSet<VarDecl*, 8> Decls; - llvm::SmallVector<SourceRange, 10> Ranges; + SmallVector<SourceRange, 10> Ranges; DeclExtractor DE(S, Decls, Ranges); DE.Visit(Second); @@ -1361,8 +1399,8 @@ public: // Load SourceRanges into diagnostic if there is room. // Otherwise, load the SourceRange of the conditional expression. if (Ranges.size() <= PartialDiagnostic::MaxArguments) - for (llvm::SmallVector<SourceRange, 10>::iterator I = Ranges.begin(), - E = Ranges.end(); + for (SmallVector<SourceRange, 10>::iterator I = Ranges.begin(), + E = Ranges.end(); I != E; ++I) PDiag << *I; else @@ -1432,12 +1470,10 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { if (result.isInvalid()) return StmtError(); E = result.take(); - CheckImplicitConversions(E); - - result = MaybeCreateExprWithCleanups(E); - if (result.isInvalid()) return StmtError(); - - return Owned(static_cast<Stmt*>(result.take())); + ExprResult FullExpr = ActOnFinishFullExpr(E); + if (FullExpr.isInvalid()) + return StmtError(); + return StmtResult(static_cast<Stmt*>(FullExpr.take())); } ExprResult @@ -1508,7 +1544,7 @@ Sema::CheckObjCForCollectionOperand(SourceLocation forLoc, Expr *collection) { } // Wrap up any cleanups in the expression. - return Owned(MaybeCreateExprWithCleanups(collection)); + return Owned(collection); } StmtResult @@ -1553,6 +1589,10 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (CollectionExprResult.isInvalid()) return StmtError(); + CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.take()); + if (CollectionExprResult.isInvalid()) + return StmtError(); + return Owned(new (Context) ObjCForCollectionStmt(First, CollectionExprResult.take(), 0, ForLoc, RParenLoc)); @@ -1625,7 +1665,7 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, 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); + TInfo, SC_None); Decl->setImplicit(); return Decl; } @@ -1937,8 +1977,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get(); Diag(Range->getLocStart(), diag::err_for_range_invalid) << RangeLoc << Range->getType() << BEFFailure; - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(&Range, /*NumArgs=*/1)); + CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Range); } // Return an error if no fix was discovered. if (RangeStatus != FRS_Success) @@ -2096,9 +2135,13 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, E = ExprRes.take(); if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); - E = MaybeCreateExprWithCleanups(E); } + ExprResult ExprRes = ActOnFinishFullExpr(E); + if (ExprRes.isInvalid()) + return StmtError(); + E = ExprRes.take(); + getCurFunction()->setHasIndirectGoto(); return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E)); @@ -2370,8 +2413,10 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - CheckImplicitConversions(RetValExp, ReturnLoc); - RetValExp = MaybeCreateExprWithCleanups(RetValExp); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + if (ER.isInvalid()) + return StmtError(); + RetValExp = ER.take(); } ReturnStmt *Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); @@ -2400,8 +2445,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { QualType RelatedRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getResultType(); - if (FD->hasAttr<NoReturnAttr>() || - FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) + if (FD->isNoReturn()) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << FD->getDeclName(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) { @@ -2473,8 +2517,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - CheckImplicitConversions(RetValExp, ReturnLoc); - RetValExp = MaybeCreateExprWithCleanups(RetValExp); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + if (ER.isInvalid()) + return StmtError(); + RetValExp = ER.take(); } } @@ -2490,24 +2536,12 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; Result = new (Context) ReturnStmt(ReturnLoc); } else { + assert(RetValExp || FnRetType->isDependentType()); const VarDecl *NRVOCandidate = 0; if (!FnRetType->isDependentType() && !RetValExp->isTypeDependent()) { // we have a non-void function with an expression, continue checking - if (!RelatedRetType.isNull()) { - // If we have a related result type, perform an extra conversion here. - // FIXME: The diagnostics here don't really describe what is happening. - InitializedEntity Entity = - InitializedEntity::InitializeTemporary(RelatedRetType); - - ExprResult Res = PerformCopyInitialization(Entity, SourceLocation(), - RetValExp); - if (Res.isInvalid()) { - // FIXME: Cleanup temporaries here, anyway? - return StmtError(); - } - RetValExp = Res.takeAs<Expr>(); - } + QualType RetType = (RelatedRetType.isNull() ? FnRetType : RelatedRetType); // 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 @@ -2517,23 +2551,40 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // the C version of which boils down to CheckSingleAssignmentConstraints. NRVOCandidate = getCopyElisionCandidate(FnRetType, RetValExp, false); InitializedEntity Entity = InitializedEntity::InitializeResult(ReturnLoc, - FnRetType, + RetType, NRVOCandidate != 0); ExprResult Res = PerformMoveOrCopyInitialization(Entity, NRVOCandidate, - FnRetType, RetValExp); + RetType, RetValExp); if (Res.isInvalid()) { - // FIXME: Cleanup temporaries here, anyway? + // FIXME: Clean up temporaries here anyway? return StmtError(); } - RetValExp = Res.takeAs<Expr>(); - if (RetValExp) - CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + + // If we have a related result type, we need to implicitly + // convert back to the formal result type. We can't pretend to + // initialize the result again --- we might end double-retaining + // --- so instead we initialize a notional temporary; this can + // lead to less-than-great diagnostics, but this stage is much + // less likely to fail than the previous stage. + if (!RelatedRetType.isNull()) { + Entity = InitializedEntity::InitializeTemporary(FnRetType); + Res = PerformCopyInitialization(Entity, ReturnLoc, RetValExp); + if (Res.isInvalid()) { + // FIXME: Clean up temporaries here anyway? + return StmtError(); + } + RetValExp = Res.takeAs<Expr>(); + } + + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); } if (RetValExp) { - CheckImplicitConversions(RetValExp, ReturnLoc); - RetValExp = MaybeCreateExprWithCleanups(RetValExp); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); + if (ER.isInvalid()) + return StmtError(); + RetValExp = ER.take(); } Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, NRVOCandidate); } @@ -2583,7 +2634,11 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Result.isInvalid()) return StmtError(); - Throw = MaybeCreateExprWithCleanups(Result.take()); + Result = ActOnFinishFullExpr(Result.take()); + 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() && @@ -2634,7 +2689,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { } // The operand to @synchronized is a full-expression. - return MaybeCreateExprWithCleanups(operand); + return ActOnFinishFullExpr(operand); } StmtResult @@ -2756,7 +2811,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, // and warns. return Owned(CXXTryStmt::Create(Context, TryLoc, TryBlock, - Handlers, NumHandlers)); + llvm::makeArrayRef(Handlers, NumHandlers))); } StmtResult diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp index 7c2c766..da33bdf 100644 --- a/lib/Sema/SemaStmtAsm.cpp +++ b/lib/Sema/SemaStmtAsm.cpp @@ -12,25 +12,25 @@ //===----------------------------------------------------------------------===// #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/RecordLayout.h" #include "clang/AST/TypeLoc.h" -#include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" @@ -124,11 +124,14 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // Check that the output exprs are valid lvalues. Expr *OutputExpr = Exprs[i]; - if (CheckAsmLValue(OutputExpr, *this)) { + if (CheckAsmLValue(OutputExpr, *this)) return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_invalid_lvalue_in_output) - << OutputExpr->getSourceRange()); - } + diag::err_asm_invalid_lvalue_in_output) + << OutputExpr->getSourceRange()); + + if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(), + diag::err_dereference_incomplete_type)) + return StmtError(); OutputConstraintInfos.push_back(Info); } @@ -179,6 +182,22 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, Exprs[i] = Result.take(); InputConstraintInfos.push_back(Info); + + const Type *Ty = Exprs[i]->getType().getTypePtr(); + if (Ty->isDependentType()) + continue; + + if (!Ty->isVoidType() || !Info.allowsMemory()) + if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(), + diag::err_dereference_incomplete_type)) + return StmtError(); + + unsigned Size = Context.getTypeSize(Ty); + if (!Context.getTargetInfo().validateInputSize(Literal->getString(), + Size)) + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_input_size) + << Info.getConstraintStr()); } // Check that the clobbers are valid. @@ -377,7 +396,7 @@ static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { static bool buildMSAsmString(Sema &SemaRef, SourceLocation AsmLoc, ArrayRef<Token> AsmToks, - llvm::SmallVectorImpl<unsigned> &TokOffsets, + SmallVectorImpl<unsigned> &TokOffsets, std::string &AsmString) { assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); @@ -426,9 +445,14 @@ public: : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { } ~MCAsmParserSemaCallbackImpl() {} - void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){ + void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, + unsigned &Length, unsigned &Size, + unsigned &Type, bool &IsVarDecl){ SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); - NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Size); + + NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Length, + Size, Type, + IsVarDecl); return static_cast<void *>(OpDecl); } @@ -471,8 +495,12 @@ public: } NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, - unsigned &Size) { + unsigned &Length, unsigned &Size, + unsigned &Type, bool &IsVarDecl) { + Length = 1; Size = 0; + Type = 0; + IsVarDecl = false; LookupResult Result(*this, &Context.Idents.get(Name), Loc, Sema::LookupOrdinaryName); @@ -487,12 +515,19 @@ NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, return 0; } - NamedDecl *ND = Result.getFoundDecl(); - if (isa<VarDecl>(ND) || isa<FunctionDecl>(ND)) { - if (VarDecl *Var = dyn_cast<VarDecl>(ND)) - Size = Context.getTypeInfo(Var->getType()).first; - - return ND; + NamedDecl *FoundDecl = Result.getFoundDecl(); + if (isa<FunctionDecl>(FoundDecl)) + return FoundDecl; + if (VarDecl *Var = dyn_cast<VarDecl>(FoundDecl)) { + QualType Ty = Var->getType(); + Type = Size = Context.getTypeSizeInChars(Ty).getQuantity(); + if (Ty->isArrayType()) { + const ArrayType *ATy = Context.getAsArrayType(Ty); + Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity(); + Length = Size / Type; + } + IsVarDecl = true; + return FoundDecl; } // FIXME: Handle other kinds of results? (FieldDecl, etc.) @@ -512,13 +547,12 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, if (!BaseResult.isSingleResult()) return true; - NamedDecl *FoundDecl = BaseResult.getFoundDecl(); const RecordType *RT = 0; - if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) { + NamedDecl *FoundDecl = BaseResult.getFoundDecl(); + if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) RT = VD->getType()->getAs<RecordType>(); - } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) { + else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) RT = TD->getUnderlyingType()->getAs<RecordType>(); - } if (!RT) return true; @@ -551,8 +585,15 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, SmallVector<Expr*, 4> Exprs; SmallVector<StringRef, 4> ClobberRefs; + llvm::Triple TheTriple = Context.getTargetInfo().getTriple(); + llvm::Triple::ArchType ArchTy = TheTriple.getArch(); + bool UnsupportedArch = ArchTy != llvm::Triple::x86 && + ArchTy != llvm::Triple::x86_64; + if (UnsupportedArch) + Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); + // Empty asm statements don't need to instantiate the AsmParser, etc. - if (AsmToks.empty()) { + if (UnsupportedArch || AsmToks.empty()) { StringRef EmptyAsmStr; MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, @@ -563,13 +604,13 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, } std::string AsmString; - llvm::SmallVector<unsigned, 8> TokOffsets; + SmallVector<unsigned, 8> TokOffsets; if (buildMSAsmString(*this, AsmLoc, AsmToks, TokOffsets, AsmString)) return StmtError(); // Get the target specific parser. std::string Error; - const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); + const std::string &TT = TheTriple.getTriple(); const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); @@ -614,7 +655,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, SmallVector<std::pair<void *, bool>, 4> OpDecls; SmallVector<std::string, 4> Constraints; SmallVector<std::string, 4> Clobbers; - if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, + if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs, NumInputs, OpDecls, Constraints, Clobbers, MII, IP, MCAPSI)) return StmtError(); @@ -641,7 +682,7 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, if (OpExpr.isInvalid()) return StmtError(); - // Need offset of variable. + // Need address of variable. if (OpDecls[i].second) OpExpr = BuildUnaryOp(getCurScope(), AsmLoc, clang::UO_AddrOf, OpExpr.take()); diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp index b268b45..eb0188a 100644 --- a/lib/Sema/SemaStmtAttr.cpp +++ b/lib/Sema/SemaStmtAttr.cpp @@ -58,8 +58,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, default: // if we're here, then we parsed a known attribute, but didn't recognize // it as a statement attribute => it is declaration attribute - S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt) - << A.getName()->getName() << St->getLocStart(); + S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt) + << A.getName() << St->getLocStart(); return 0; } } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f56b054..9906261 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -9,23 +9,23 @@ // 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/Expr.h" +#include "clang/AST/ExprCXX.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 "clang/Sema/DeclSpec.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -356,7 +356,7 @@ void Sema::LookupTemplateName(LookupResult &Found, } if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope && - !(getLangOpts().CPlusPlus0x && !Found.empty())) { + !(getLangOpts().CPlusPlus11 && !Found.empty())) { // C++03 [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 @@ -510,7 +510,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, TemplateName Template = Arg.getAsTemplate().get(); TemplateArgument TArg; if (Arg.getEllipsisLoc().isValid()) - TArg = TemplateArgument(Template, llvm::Optional<unsigned int>()); + TArg = TemplateArgument(Template, Optional<unsigned int>()); else TArg = Template; return TemplateArgumentLoc(TArg, @@ -1171,7 +1171,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, // 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). - S.Diag(ParamLoc, S.getLangOpts().CPlusPlus0x ? + S.Diag(ParamLoc, S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_parameter_default_in_function_template : diag::ext_template_parameter_default_in_function_template) << DefArgRange; @@ -2359,7 +2359,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, TemplateTy &Result) { if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent()) Diag(TemplateKWLoc, - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_outside_of_template : diag::ext_template_outside_of_template) << FixItHint::CreateRemoval(TemplateKWLoc); @@ -2387,7 +2387,7 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, // "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, + TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name, ObjectType, EnteringContext, Result, MemberOfUnknownSpecialization); if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && @@ -2972,7 +2972,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // 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) - << getLangOpts().CPlusPlus0x; + << getLangOpts().CPlusPlus11; return true; case TemplateArgument::Declaration: @@ -3023,7 +3023,7 @@ static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template, /// /// In \c A<int,int>::B, \c NTs and \c TTs have expanded pack size 2, and \c Us /// is not a pack expansion, so returns an empty Optional. -static llvm::Optional<unsigned> getExpandedPackSize(NamedDecl *Param) { +static Optional<unsigned> getExpandedPackSize(NamedDecl *Param) { if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { if (NTTP->isExpandedParameterPack()) @@ -3036,7 +3036,7 @@ static llvm::Optional<unsigned> getExpandedPackSize(NamedDecl *Param) { return TTP->getNumExpansionTemplateParameters(); } - return llvm::Optional<unsigned>(); + return None; } /// \brief Check that the given template argument list is well-formed @@ -3068,7 +3068,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, Param != ParamEnd; /* increment in loop */) { // If we have an expanded parameter pack, make sure we don't have too // many arguments. - if (llvm::Optional<unsigned> Expansions = getExpandedPackSize(*Param)) { + if (Optional<unsigned> Expansions = getExpandedPackSize(*Param)) { if (*Expansions == ArgumentPack.size()) { // We're done with this parameter pack. Pack up its arguments and add // them to the list. @@ -3486,16 +3486,16 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) { bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { if (Tag->getDeclContext()->isFunctionOrMethod()) { S.Diag(SR.getBegin(), - S.getLangOpts().CPlusPlus0x ? + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_arg_local_type : diag::ext_template_arg_local_type) << S.Context.getTypeDeclType(Tag) << SR; return true; } - if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) { + if (!Tag->hasNameForLinkage()) { S.Diag(SR.getBegin(), - S.getLangOpts().CPlusPlus0x ? + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_arg_unnamed_type : diag::ext_template_arg_unnamed_type) << SR; S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here); @@ -3549,7 +3549,7 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, // // C++11 allows these, and even in C++03 we allow them as an extension with // a warning. - if (LangOpts.CPlusPlus0x ? + if (LangOpts.CPlusPlus11 ? Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_unnamed_type, SR.getBegin()) != DiagnosticsEngine::Ignored || Diags.getDiagnosticLevel(diag::warn_cxx98_compat_template_arg_local_type, @@ -3576,7 +3576,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, if (Arg->isValueDependent() || Arg->isTypeDependent()) return NPV_NotNullPointer; - if (!S.getLangOpts().CPlusPlus0x) + if (!S.getLangOpts().CPlusPlus11) return NPV_NotNullPointer; // Determine whether we have a constant expression. @@ -3586,7 +3586,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, Arg = ArgRV.take(); Expr::EvalResult EvalResult; - llvm::SmallVector<PartialDiagnosticAt, 8> Notes; + SmallVector<PartialDiagnosticAt, 8> Notes; EvalResult.Diag = &Notes; if (!Arg->EvaluateAsRValue(EvalResult, S.Context) || EvalResult.HasSideEffects) { @@ -3704,7 +3704,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid && !ExtraParens) { S.Diag(Arg->getLocStart(), - S.getLangOpts().CPlusPlus0x ? + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_arg_extra_parens : diag::ext_template_arg_extra_parens) << Arg->getSourceRange(); @@ -3794,7 +3794,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // Address / reference template args must have external linkage in C++98. if (Entity->getLinkage() == InternalLinkage) { - S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus0x ? + S.Diag(Arg->getLocStart(), S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_arg_object_internal : diag::ext_template_arg_object_internal) << !Func << Entity << Arg->getSourceRange(); @@ -3950,7 +3950,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, // Create the template argument. Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType->isReferenceType()); - S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity); + S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false); return false; } @@ -4010,7 +4010,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid && !ExtraParens) { S.Diag(Arg->getLocStart(), - S.getLangOpts().CPlusPlus0x ? + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_template_arg_extra_parens : diag::ext_template_arg_extra_parens) << Arg->getSourceRange(); @@ -4139,7 +4139,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return ExprError(); } - if (getLangOpts().CPlusPlus0x) { + if (getLangOpts().CPlusPlus11) { // We can't check arbitrary value-dependent arguments. // FIXME: If there's no viable conversion to the template parameter type, // we should be able to diagnose that prior to instantiation. @@ -4495,6 +4495,16 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc) { + // 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. + if (ParamType->isArrayType()) + ParamType = Context.getArrayDecayedType(ParamType); + else if (ParamType->isFunctionType()) + ParamType = Context.getPointerType(ParamType); + // For a NULL non-type template argument, return nullptr casted to the // parameter's type. if (Arg.getKind() == TemplateArgument::NullPtr) { @@ -4560,6 +4570,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, } QualType T = VD->getType().getNonReferenceType(); + if (ParamType->isPointerType()) { // When the non-type template parameter is a pointer, take the // address of the declaration. @@ -4589,6 +4600,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, VK = VK_LValue; T = Context.getQualifiedType(T, TargetRef->getPointeeType().getQualifiers()); + } else if (isa<FunctionDecl>(VD)) { + // References to functions are always lvalues. + VK = VK_LValue; } return BuildDeclRefExpr(VD, T, VK, Loc); @@ -4606,7 +4620,18 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, SourceLocation Loc) { assert(Arg.getKind() == TemplateArgument::Integral && "Operation is only valid for integral template arguments"); - QualType T = Arg.getIntegralType(); + QualType OrigT = Arg.getIntegralType(); + + // 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. The integer type of an enum type can be of + // any integral type with C++11 enum classes, make sure we create the right + // type of literal for it. + QualType T = OrigT; + if (const EnumType *ET = OrigT->getAs<EnumType>()) + T = ET->getDecl()->getIntegerType(); + + Expr *E; if (T->isAnyCharacterType()) { CharacterLiteral::CharacterKind Kind; if (T->isWideCharType()) @@ -4618,34 +4643,22 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, else Kind = CharacterLiteral::Ascii; - return Owned(new (Context) CharacterLiteral( - Arg.getAsIntegral().getZExtValue(), - Kind, T, Loc)); + E = new (Context) CharacterLiteral(Arg.getAsIntegral().getZExtValue(), + Kind, T, Loc); + } else if (T->isBooleanType()) { + E = new (Context) CXXBoolLiteralExpr(Arg.getAsIntegral().getBoolValue(), + T, Loc); + } else if (T->isNullPtrType()) { + E = new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc); + } else { + E = IntegerLiteral::Create(Context, Arg.getAsIntegral(), 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()) { + if (OrigT->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), + E = CStyleCastExpr::Create(Context, OrigT, VK_RValue, CK_IntegralCast, E, 0, + Context.getTrivialTypeSourceInfo(OrigT, Loc), Loc, Loc); } @@ -4961,11 +4974,11 @@ static bool CheckTemplateSpecializationScope(Sema &S, EntityKind = 4; else if (isa<RecordDecl>(Specialized)) EntityKind = 5; - else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus0x) + else if (isa<EnumDecl>(Specialized) && S.getLangOpts().CPlusPlus11) EntityKind = 6; else { S.Diag(Loc, diag::err_template_spec_unknown_kind) - << S.getLangOpts().CPlusPlus0x; + << S.getLangOpts().CPlusPlus11; S.Diag(Specialized->getLocation(), diag::note_specialized_entity); return true; } @@ -5036,17 +5049,17 @@ static bool CheckTemplateSpecializationScope(Sema &S, // An explicit specialization shall be declared in a namespace enclosing // the specialized template. if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) { - bool IsCPlusPlus0xExtension = DC->Encloses(SpecializedContext); + bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext); if (isa<TranslationUnitDecl>(SpecializedContext)) { - assert(!IsCPlusPlus0xExtension && + assert(!IsCPlusPlus11Extension && "DC encloses TU but isn't in enclosing namespace set"); S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global) << EntityKind << Specialized; } else if (isa<NamespaceDecl>(SpecializedContext)) { int Diag; - if (!IsCPlusPlus0xExtension) + if (!IsCPlusPlus11Extension) Diag = diag::err_template_spec_decl_out_of_scope; - else if (!S.getLangOpts().CPlusPlus0x) + else if (!S.getLangOpts().CPlusPlus11) Diag = diag::ext_template_spec_decl_out_of_scope; else Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope; @@ -5056,7 +5069,7 @@ static bool CheckTemplateSpecializationScope(Sema &S, S.Diag(Specialized->getLocation(), diag::note_specialized_entity); ComplainedAboutScope = - !(IsCPlusPlus0xExtension && S.getLangOpts().CPlusPlus0x); + !(IsCPlusPlus11Extension && S.getLangOpts().CPlusPlus11); } } @@ -5629,23 +5642,21 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists); - 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; + return ActOnStartOfFunctionDef(FnBodyScope, DP); } /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { - // FIXME: "make check" is clean if the call to dropAttrs() is commented out. D->dropAttrs(); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { FD->setInlineSpecified(false); + + for (FunctionDecl::param_iterator I = FD->param_begin(), + E = FD->param_end(); + I != E; ++I) + (*I)->dropAttrs(); } } @@ -5803,7 +5814,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // 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. - Diag(NewLoc, getLangOpts().CPlusPlus0x ? + Diag(NewLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_explicit_instantiation_after_specialization : diag::ext_explicit_instantiation_after_specialization) << PrevDecl; @@ -5925,6 +5936,26 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, Ovl->getDeclContext()->getRedeclContext())) continue; + // When matching a constexpr member function template specialization + // against the primary template, we don't yet know whether the + // specialization has an implicit 'const' (because we don't know whether + // it will be a static member function until we know which template it + // specializes), so adjust it now assuming it specializes this template. + QualType FT = FD->getType(); + if (FD->isConstexpr()) { + CXXMethodDecl *OldMD = + dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + if (OldMD && OldMD->isConst()) { + const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>(); + FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); + EPI.TypeQuals |= Qualifiers::Const; + FT = Context.getFunctionType(FPT->getResultType(), + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI); + } + } + // C++ [temp.expl.spec]p11: // A trailing template-argument can be left unspecified in the // template-id naming an explicit function template specialization @@ -5935,10 +5966,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, TemplateDeductionInfo Info(FD->getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK - = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, - FD->getType(), - Specialization, - Info)) { + = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT, + Specialization, Info)) { // FIXME: Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. (void)TDK; @@ -6028,8 +6057,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, TemplArgs, /*InsertPos=*/0, SpecInfo->getTemplateSpecializationKind(), ExplicitTemplateArgs); - FD->setStorageClass(Specialization->getStorageClass()); - + // The "previous declaration" for this function template specialization is // the prior function template specialization. Previous.clear(); @@ -6257,19 +6285,19 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, if (NamespaceDecl *NS = dyn_cast<NamespaceDecl>(OrigContext)) { if (WasQualifiedName) S.Diag(InstLoc, - S.getLangOpts().CPlusPlus0x? + S.getLangOpts().CPlusPlus11? diag::err_explicit_instantiation_out_of_scope : diag::warn_explicit_instantiation_out_of_scope_0x) << D << NS; else S.Diag(InstLoc, - S.getLangOpts().CPlusPlus0x? + S.getLangOpts().CPlusPlus11? diag::err_explicit_instantiation_unqualified_wrong_namespace : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x) << D << NS; } else S.Diag(InstLoc, - S.getLangOpts().CPlusPlus0x? + S.getLangOpts().CPlusPlus11? diag::err_explicit_instantiation_must_be_global : diag::warn_explicit_instantiation_must_be_global_0x) << D; @@ -6663,7 +6691,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // well. if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::err_explicit_instantiation_inline : diag::warn_explicit_instantiation_inline_0x) << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); @@ -6920,7 +6948,7 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, if (TypenameLoc.isValid() && S && !S->getTemplateParamParent()) Diag(TypenameLoc, - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_typename_outside_of_template : diag::ext_typename_outside_of_template) << FixItHint::CreateRemoval(TypenameLoc); @@ -6933,15 +6961,15 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa<DependentNameType>(T)) { - DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); + DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); TL.setElaboratedKeywordLoc(TypenameLoc); TL.setQualifierLoc(QualifierLoc); TL.setNameLoc(IdLoc); } else { - ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); + ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>(); TL.setElaboratedKeywordLoc(TypenameLoc); TL.setQualifierLoc(QualifierLoc); - cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc); + TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc); } return CreateParsedType(T, TSI); @@ -6959,7 +6987,7 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation RAngleLoc) { if (TypenameLoc.isValid() && S && !S->getTemplateParamParent()) Diag(TypenameLoc, - getLangOpts().CPlusPlus0x ? + getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_typename_outside_of_template : diag::ext_typename_outside_of_template) << FixItHint::CreateRemoval(TypenameLoc); @@ -7031,12 +7059,12 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, if (!NNS || !NNS.getNestedNameSpecifier()->getAsType()) return false; TypeLoc EnableIfTy = NNS.getTypeLoc(); - TemplateSpecializationTypeLoc *EnableIfTSTLoc = - dyn_cast<TemplateSpecializationTypeLoc>(&EnableIfTy); - if (!EnableIfTSTLoc || EnableIfTSTLoc->getNumArgs() == 0) + TemplateSpecializationTypeLoc EnableIfTSTLoc = + EnableIfTy.getAs<TemplateSpecializationTypeLoc>(); + if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0) return false; const TemplateSpecializationType *EnableIfTST = - cast<TemplateSpecializationType>(EnableIfTSTLoc->getTypePtr()); + cast<TemplateSpecializationType>(EnableIfTSTLoc.getTypePtr()); // ... which names a complete class template declaration... const TemplateDecl *EnableIfDecl = @@ -7051,7 +7079,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, return false; // Assume the first template argument is the condition. - CondRange = EnableIfTSTLoc->getArgLoc(0).getSourceRange(); + CondRange = EnableIfTSTLoc.getArgLoc(0).getSourceRange(); return true; } diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index bf4533d..f3bbe8a 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -10,18 +10,18 @@ // //===----------------------------------------------------------------------===/ -#include "clang/Sema/Sema.h" -#include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" +#include "TreeTransform.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 "clang/AST/StmtVisitor.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/Template.h" #include "llvm/ADT/SmallBitVector.h" -#include "TreeTransform.h" #include <algorithm> namespace clang { @@ -130,8 +130,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgument *Params, unsigned NumParams, const TemplateArgument *Args, unsigned NumArgs, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - bool NumberOfArgumentsMustMatch = true); + SmallVectorImpl<DeducedTemplateArgument> &Deduced); /// \brief If the given expression is of a form that permits the deduction /// of a non-type template parameter, return the declaration of that @@ -482,21 +481,26 @@ DeduceTemplateArguments(Sema &S, return DeduceTemplateArguments(S, TemplateParams, Param->getArgs(), Param->getNumArgs(), SpecArg->getArgs(), SpecArg->getNumArgs(), - Info, Deduced, - /*NumberOfArgumentsMustMatch=*/false); + Info, Deduced); } // 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) + if (!RecordArg) { + Info.FirstArg = TemplateArgument(QualType(Param, 0)); + Info.SecondArg = TemplateArgument(Arg); return Sema::TDK_NonDeducedMismatch; + } ClassTemplateSpecializationDecl *SpecArg = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl()); - if (!SpecArg) + if (!SpecArg) { + Info.FirstArg = TemplateArgument(QualType(Param, 0)); + Info.SecondArg = TemplateArgument(Arg); return Sema::TDK_NonDeducedMismatch; + } // Perform template argument deduction for the template name. if (Sema::TemplateDeductionResult Result @@ -710,7 +714,7 @@ DeduceTemplateArguments(Sema &S, if (NumParams != NumArgs && !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) && !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1]))) - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; // C++0x [temp.deduct.type]p10: // Similarly, if P has a form that contains (T), then each parameter type @@ -727,14 +731,14 @@ DeduceTemplateArguments(Sema &S, // Make sure we have an argument. if (ArgIdx >= NumArgs) - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; 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; + return Sema::TDK_MiscellaneousDeductionFailure; } if (Sema::TemplateDeductionResult Result @@ -827,7 +831,7 @@ DeduceTemplateArguments(Sema &S, // Make sure we don't have any extra arguments. if (ArgIdx < NumArgs) - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; return Sema::TDK_Success; } @@ -1749,8 +1753,7 @@ DeduceTemplateArguments(Sema &S, const TemplateArgument *Params, unsigned NumParams, const TemplateArgument *Args, unsigned NumArgs, TemplateDeductionInfo &Info, - SmallVectorImpl<DeducedTemplateArgument> &Deduced, - bool NumberOfArgumentsMustMatch) { + SmallVectorImpl<DeducedTemplateArgument> &Deduced) { // 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 @@ -1770,13 +1773,12 @@ DeduceTemplateArguments(Sema &S, // Check whether we have enough arguments. if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) - return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch - : Sema::TDK_Success; + return 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; + return Sema::TDK_MiscellaneousDeductionFailure; } // Perform deduction for this Pi/Ai pair. @@ -1867,11 +1869,6 @@ DeduceTemplateArguments(Sema &S, 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; } @@ -2400,7 +2397,7 @@ Sema::SubstituteExplicitTemplateArguments( } CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals, - getLangOpts().CPlusPlus0x); + getLangOpts().CPlusPlus11); ResultType = SubstType(Proto->getResultType(), MultiLevelTemplateArgumentList(*ExplicitArgumentList), @@ -2420,15 +2417,10 @@ Sema::SubstituteExplicitTemplateArguments( return TDK_SubstitutionFailure; if (FunctionType) { - *FunctionType = BuildFunctionType(ResultType, - ParamTypes.data(), ParamTypes.size(), - Proto->isVariadic(), - Proto->hasTrailingReturn(), - Proto->getTypeQuals(), - Proto->getRefQualifier(), + *FunctionType = BuildFunctionType(ResultType, ParamTypes, Function->getLocation(), Function->getDeclName(), - Proto->getExtInfo()); + Proto->getExtProtoInfo()); if (FunctionType->isNull() || Trap.hasErrorOccurred()) return TDK_SubstitutionFailure; } @@ -2656,11 +2648,15 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, if (CurrentInstantiationScope && CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs, &NumExplicitArgs) - == Param) + == Param) { Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs)); - else - Builder.push_back(TemplateArgument::getEmptyPack()); + // Forget the partially-substituted pack; it's substitution is now + // complete. + CurrentInstantiationScope->ResetPartiallySubstitutedPack(); + } else { + Builder.push_back(TemplateArgument::getEmptyPack()); + } continue; } @@ -2884,7 +2880,8 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, /// 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. +/// argument deduction based on this P/A pair because the argument is an +/// overloaded function set that could not be resolved. static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, TemplateParameterList *TemplateParams, QualType &ParamType, @@ -2900,7 +2897,7 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S, if (ParamRefType) { QualType PointeeType = ParamRefType->getPointeeType(); - // If the argument has incomplete array type, try to complete it's type. + // If the argument has incomplete array type, try to complete its type. if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0)) ArgType = Arg->getType(); @@ -2998,8 +2995,8 @@ static bool hasDeducibleTemplateParameters(Sema &S, /// \brief Perform template argument deduction by matching a parameter type /// against a single expression, where the expression is an element of -/// an initializer list that was originally matched against the argument -/// type. +/// an initializer list that was originally matched against a parameter +/// of type \c initializer_list\<ParamType\>. static Sema::TemplateDeductionResult DeduceTemplateArgumentByListElement(Sema &S, TemplateParameterList *TemplateParams, @@ -3028,8 +3025,10 @@ DeduceTemplateArgumentByListElement(Sema &S, // For all other cases, just match by type. QualType ArgType = Arg->getType(); if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType, - ArgType, Arg, TDF)) + ArgType, Arg, TDF)) { + Info.Expression = Arg; return Sema::TDK_FailedOverloadResolution; + } return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, ArgType, Info, Deduced, TDF); } @@ -3045,11 +3044,6 @@ DeduceTemplateArgumentByListElement(Sema &S, /// /// \param Args the function call arguments /// -/// \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. @@ -3372,7 +3366,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // specialization, template argument deduction fails. if (!ArgFunctionType.isNull() && !Context.hasSameType(ArgFunctionType, Specialization->getType())) - return TDK_NonDeducedMismatch; + return TDK_MiscellaneousDeductionFailure; return TDK_Success; } @@ -3772,15 +3766,15 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // first argument of the free function, which seems to match // existing practice. SmallVector<QualType, 4> Args1; - unsigned Skip1 = !S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1; - if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2) + unsigned Skip1 = !S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1; + if (S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2) AddImplicitObjectParameterType(S.Context, Method1, Args1); Args1.insert(Args1.end(), Proto1->arg_type_begin() + Skip1, Proto1->arg_type_end()); SmallVector<QualType, 4> Args2; - Skip2 = !S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2; - if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1) + Skip2 = !S.getLangOpts().CPlusPlus11 && IsNonStatic1 && !Method2; + if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !Method1) AddImplicitObjectParameterType(S.Context, Method2, Args2); Args2.insert(Args2.end(), Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end()); @@ -3849,7 +3843,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, unsigned NumParams = std::min(NumCallArguments, std::min(Proto1->getNumArgs(), Proto2->getNumArgs())); - if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) + if (S.getLangOpts().CPlusPlus11 && IsNonStatic2 && !IsNonStatic1) ::MarkUsedTemplateParameters(S.Context, Method2->getThisType(S.Context), false, TemplateParams->getDepth(), UsedParameters); @@ -4052,10 +4046,6 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// 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. /// @@ -4618,7 +4608,7 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, /// call to the given function template. void Sema::MarkDeducedTemplateParameters(ASTContext &Ctx, - FunctionTemplateDecl *FunctionTemplate, + const FunctionTemplateDecl *FunctionTemplate, llvm::SmallBitVector &Deduced) { TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 665dd07..f755b8c 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -12,16 +12,16 @@ #include "clang/Sema/SemaInternal.h" #include "TreeTransform.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/Expr.h" +#include "clang/Basic/LangOptions.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; @@ -182,7 +182,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ActiveTemplateInstantiation Inst; Inst.Kind = ActiveTemplateInstantiation::TemplateInstantiation; Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(Entity); + Inst.Entity = Entity; Inst.TemplateArgs = 0; Inst.NumTemplateArgs = 0; Inst.InstantiationRange = InstantiationRange; @@ -205,7 +205,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ActiveTemplateInstantiation Inst; Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation; Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(Entity); + Inst.Entity = Entity; Inst.TemplateArgs = 0; Inst.NumTemplateArgs = 0; Inst.InstantiationRange = InstantiationRange; @@ -230,7 +230,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation; Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(Template); + Inst.Entity = Template; Inst.TemplateArgs = TemplateArgs.data(); Inst.NumTemplateArgs = TemplateArgs.size(); Inst.InstantiationRange = InstantiationRange; @@ -255,7 +255,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ActiveTemplateInstantiation Inst; Inst.Kind = Kind; Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate); + Inst.Entity = FunctionTemplate; Inst.TemplateArgs = TemplateArgs.data(); Inst.NumTemplateArgs = TemplateArgs.size(); Inst.DeductionInfo = &DeductionInfo; @@ -283,7 +283,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ActiveTemplateInstantiation Inst; Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); + Inst.Entity = PartialSpec; Inst.TemplateArgs = TemplateArgs.data(); Inst.NumTemplateArgs = TemplateArgs.size(); Inst.DeductionInfo = &DeductionInfo; @@ -308,7 +308,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.Kind = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.Entity = Param; Inst.TemplateArgs = TemplateArgs.data(); Inst.NumTemplateArgs = TemplateArgs.size(); Inst.InstantiationRange = InstantiationRange; @@ -332,7 +332,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; Inst.PointOfInstantiation = PointOfInstantiation; Inst.Template = Template; - Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.Entity = Param; Inst.TemplateArgs = TemplateArgs.data(); Inst.NumTemplateArgs = TemplateArgs.size(); Inst.InstantiationRange = InstantiationRange; @@ -356,7 +356,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; Inst.PointOfInstantiation = PointOfInstantiation; Inst.Template = Template; - Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.Entity = Param; Inst.TemplateArgs = TemplateArgs.data(); Inst.NumTemplateArgs = TemplateArgs.size(); Inst.InstantiationRange = InstantiationRange; @@ -380,7 +380,7 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking; Inst.PointOfInstantiation = PointOfInstantiation; Inst.Template = Template; - Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.Entity = Param; Inst.TemplateArgs = TemplateArgs.data(); Inst.NumTemplateArgs = TemplateArgs.size(); Inst.InstantiationRange = InstantiationRange; @@ -454,7 +454,7 @@ void Sema::PrintInstantiationStack() { switch (Active->Kind) { case ActiveTemplateInstantiation::TemplateInstantiation: { - Decl *D = reinterpret_cast<Decl *>(Active->Entity); + Decl *D = Active->Entity; if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { unsigned DiagID = diag::note_template_member_class_here; if (isa<ClassTemplateSpecializationDecl>(Record)) @@ -491,22 +491,23 @@ void Sema::PrintInstantiationStack() { } case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: { - TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( + TemplateDecl *Template = cast<TemplateDecl>(Active->Entity); + SmallVector<char, 128> TemplateArgsStr; + llvm::raw_svector_ostream OS(TemplateArgsStr); + Template->printName(OS); + TemplateSpecializationType::PrintTemplateArgumentList(OS, Active->TemplateArgs, Active->NumTemplateArgs, getPrintingPolicy()); Diags.Report(Active->PointOfInstantiation, diag::note_default_arg_instantiation_here) - << (Template->getNameAsString() + TemplateArgsStr) + << OS.str() << Active->InstantiationRange; break; } case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: { - FunctionTemplateDecl *FnTmpl - = cast<FunctionTemplateDecl>((Decl *)Active->Entity); + FunctionTemplateDecl *FnTmpl = cast<FunctionTemplateDecl>(Active->Entity); Diags.Report(Active->PointOfInstantiation, diag::note_explicit_template_arg_substitution_here) << FnTmpl @@ -518,9 +519,8 @@ void Sema::PrintInstantiationStack() { } case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution: - if (ClassTemplatePartialSpecializationDecl *PartialSpec - = dyn_cast<ClassTemplatePartialSpecializationDecl>( - (Decl *)Active->Entity)) { + if (ClassTemplatePartialSpecializationDecl *PartialSpec = + dyn_cast<ClassTemplatePartialSpecializationDecl>(Active->Entity)) { Diags.Report(Active->PointOfInstantiation, diag::note_partial_spec_deduct_instantiation_here) << Context.getTypeDeclType(PartialSpec) @@ -531,7 +531,7 @@ void Sema::PrintInstantiationStack() { << Active->InstantiationRange; } else { FunctionTemplateDecl *FnTmpl - = cast<FunctionTemplateDecl>((Decl *)Active->Entity); + = cast<FunctionTemplateDecl>(Active->Entity); Diags.Report(Active->PointOfInstantiation, diag::note_function_template_deduction_instantiation_here) << FnTmpl @@ -543,23 +543,25 @@ void Sema::PrintInstantiationStack() { break; case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: { - ParmVarDecl *Param = cast<ParmVarDecl>((Decl *)Active->Entity); + ParmVarDecl *Param = cast<ParmVarDecl>(Active->Entity); FunctionDecl *FD = cast<FunctionDecl>(Param->getDeclContext()); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( + SmallVector<char, 128> TemplateArgsStr; + llvm::raw_svector_ostream OS(TemplateArgsStr); + FD->printName(OS); + TemplateSpecializationType::PrintTemplateArgumentList(OS, Active->TemplateArgs, Active->NumTemplateArgs, getPrintingPolicy()); Diags.Report(Active->PointOfInstantiation, diag::note_default_function_arg_instantiation_here) - << (FD->getNameAsString() + TemplateArgsStr) + << OS.str() << Active->InstantiationRange; break; } case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: { - NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity); + NamedDecl *Parm = cast<NamedDecl>(Active->Entity); std::string Name; if (!Parm->getName().empty()) Name = std::string(" '") + Parm->getName().str() + "'"; @@ -603,16 +605,16 @@ void Sema::PrintInstantiationStack() { case ActiveTemplateInstantiation::ExceptionSpecInstantiation: Diags.Report(Active->PointOfInstantiation, diag::note_template_exception_spec_instantiation_here) - << cast<FunctionDecl>((Decl *)Active->Entity) + << cast<FunctionDecl>(Active->Entity) << Active->InstantiationRange; break; } } } -llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { +Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { if (InNonInstantiationSFINAEContext) - return llvm::Optional<TemplateDeductionInfo *>(0); + return Optional<TemplateDeductionInfo *>(0); for (SmallVector<ActiveTemplateInstantiation, 16>::const_reverse_iterator Active = ActiveTemplateInstantiations.rbegin(), @@ -624,13 +626,13 @@ llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { case ActiveTemplateInstantiation::TemplateInstantiation: // An instantiation of an alias template may or may not be a SFINAE // context, depending on what else is on the stack. - if (isa<TypeAliasTemplateDecl>(reinterpret_cast<Decl *>(Active->Entity))) + if (isa<TypeAliasTemplateDecl>(Active->Entity)) break; // Fall through. case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: case ActiveTemplateInstantiation::ExceptionSpecInstantiation: // This is a template instantiation, so there is no SFINAE. - return llvm::Optional<TemplateDeductionInfo *>(); + return None; case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: @@ -649,7 +651,7 @@ llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const { } } - return llvm::Optional<TemplateDeductionInfo *>(); + return None; } /// \brief Retrieve the depth and index of a parameter pack. @@ -709,7 +711,7 @@ namespace { llvm::ArrayRef<UnexpandedParameterPack> Unexpanded, bool &ShouldExpand, bool &RetainExpansion, - llvm::Optional<unsigned> &NumExpansions) { + Optional<unsigned> &NumExpansions) { return getSema().CheckParameterPacksForExpansion(EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, @@ -829,7 +831,7 @@ namespace { ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions, + Optional<unsigned> NumExpansions, bool ExpectParameterPack); /// \brief Transforms a template type parameter type by performing @@ -1267,7 +1269,7 @@ TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) { // Transform each of the parameter expansions into the corresponding // parameters in the instantiation of the function decl. - llvm::SmallVector<Decl*, 8> Parms; + SmallVector<Decl *, 8> Parms; Parms.reserve(E->getNumExpansions()); for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end(); I != End; ++I) { @@ -1365,7 +1367,7 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB, ParmVarDecl * TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions, + Optional<unsigned> NumExpansions, bool ExpectParameterPack) { return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment, NumExpansions, ExpectParameterPack); @@ -1568,10 +1570,10 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) { return true; TypeLoc TL = T->getTypeLoc().IgnoreParens(); - if (!isa<FunctionProtoTypeLoc>(TL)) + if (!TL.getAs<FunctionProtoTypeLoc>()) return false; - FunctionProtoTypeLoc FP = cast<FunctionProtoTypeLoc>(TL); + FunctionProtoTypeLoc FP = TL.castAs<FunctionProtoTypeLoc>(); for (unsigned I = 0, E = FP.getNumArgs(); I != E; ++I) { ParmVarDecl *P = FP.getArg(I); @@ -1615,9 +1617,9 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, TLB.reserve(TL.getFullDataSize()); QualType Result; - - if (FunctionProtoTypeLoc *Proto = dyn_cast<FunctionProtoTypeLoc>(&TL)) { - Result = Instantiator.TransformFunctionProtoType(TLB, *Proto, ThisContext, + + if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { + Result = Instantiator.TransformFunctionProtoType(TLB, Proto, ThisContext, ThisTypeQuals); } else { Result = Instantiator.TransformType(TLB, TL); @@ -1631,15 +1633,14 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions, + Optional<unsigned> NumExpansions, bool ExpectParameterPack) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; TypeLoc OldTL = OldDI->getTypeLoc(); - if (isa<PackExpansionTypeLoc>(OldTL)) { - PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(OldTL); - + if (PackExpansionTypeLoc ExpansionTL = OldTL.getAs<PackExpansionTypeLoc>()) { + // We have a function parameter pack. Substitute into the pattern of the // expansion. NewDI = SubstType(ExpansionTL.getPatternLoc(), TemplateArgs, @@ -1681,8 +1682,7 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, OldParm->getLocation(), OldParm->getIdentifier(), NewDI->getType(), NewDI, - OldParm->getStorageClass(), - OldParm->getStorageClassAsWritten()); + OldParm->getStorageClass()); if (!NewParm) return 0; @@ -1715,7 +1715,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, NewParm->setScopeInfo(OldParm->getFunctionScopeDepth(), OldParm->getFunctionScopeIndex() + indexAdjustment); - + + InstantiateAttrs(TemplateArgs, OldParm, NewParm); + return NewParm; } @@ -1767,7 +1769,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Unexpanded); bool ShouldExpand = false; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(), Base->getSourceRange(), Unexpanded, @@ -2047,6 +2049,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, CheckCompletedCXXClass(Instantiation); // Attach any in-class member initializers now the class is complete. + // FIXME: We are supposed to defer instantiating these until they are needed. if (!FieldsWithMemberInitializers.empty()) { // C++11 [expr.prim.general]p4: // Otherwise, if a member-declarator declares a non-static data member @@ -2583,12 +2586,21 @@ Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) { return Instantiator.TransformExpr(E); } +ExprResult Sema::SubstInitializer(Expr *Init, + const MultiLevelTemplateArgumentList &TemplateArgs, + bool CXXDirectInit) { + TemplateInstantiator Instantiator(*this, TemplateArgs, + SourceLocation(), + DeclarationName()); + return Instantiator.TransformInitializer(Init, CXXDirectInit); +} + bool Sema::SubstExprs(Expr **Exprs, unsigned NumExprs, bool IsCall, const MultiLevelTemplateArgumentList &TemplateArgs, SmallVectorImpl<Expr *> &Outputs) { if (NumExprs == 0) return false; - + TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), DeclarationName()); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 19c46ab..33e83d0 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -10,9 +10,6 @@ // //===----------------------------------------------------------------------===/ #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" @@ -22,6 +19,9 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" #include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/PrettyDeclStackTrace.h" +#include "clang/Sema/Template.h" using namespace clang; @@ -60,6 +60,64 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, // Include attribute instantiation code. #include "clang/Sema/AttrTemplateInstantiate.inc" +static void instantiateDependentAlignedAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AlignedAttr *Aligned, Decl *New, bool IsPackExpansion) { + if (Aligned->isAlignmentExpr()) { + // The alignment expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated); + ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs); + if (!Result.isInvalid()) + S.AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(), + Aligned->getSpellingListIndex(), IsPackExpansion); + } else { + TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(), + TemplateArgs, Aligned->getLocation(), + DeclarationName()); + if (Result) + S.AddAlignedAttr(Aligned->getLocation(), New, Result, + Aligned->getSpellingListIndex(), IsPackExpansion); + } +} + +static void instantiateDependentAlignedAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AlignedAttr *Aligned, Decl *New) { + if (!Aligned->isPackExpansion()) { + instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); + return; + } + + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + if (Aligned->isAlignmentExpr()) + S.collectUnexpandedParameterPacks(Aligned->getAlignmentExpr(), + Unexpanded); + else + S.collectUnexpandedParameterPacks(Aligned->getAlignmentType()->getTypeLoc(), + Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + + // Determine whether we can expand this attribute pack yet. + bool Expand = true, RetainExpansion = false; + Optional<unsigned> NumExpansions; + // FIXME: Use the actual location of the ellipsis. + SourceLocation EllipsisLoc = Aligned->getLocation(); + if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(), + Unexpanded, TemplateArgs, Expand, + RetainExpansion, NumExpansions)) + return; + + if (!Expand) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, -1); + instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, true); + } else { + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I); + instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); + } + } +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -69,31 +127,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, 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()) { - if (Aligned->isAlignmentExpr()) { - // The alignment expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated(*this, - Sema::ConstantEvaluated); - - ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(), - TemplateArgs); - if (!Result.isInvalid()) - AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(), - Aligned->getIsMSDeclSpec()); - } else { - TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(), - TemplateArgs, - Aligned->getLocation(), - DeclarationName()); - if (Result) - AddAlignedAttr(Aligned->getLocation(), New, Result, - Aligned->getIsMSDeclSpec()); - } - continue; - } + const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr); + if (Aligned && Aligned->isAlignmentDependent()) { + instantiateDependentAlignedAttr(*this, TemplateArgs, Aligned, New); + continue; } + assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the // enclosing class has been instantiated. See Sema::InstantiateClass. @@ -189,9 +229,9 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, // 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) { + if (oldTag->getTypedefNameForAnonDecl() == D && !Invalid) { TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl(); - assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl()); + assert(!newTag->hasNameForLinkage()); newTag->setTypedefNameForAnonDecl(Typedef); } } @@ -245,8 +285,8 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { TypeAliasTemplateDecl *PrevAliasTemplate = 0; if (Pattern->getPreviousDecl()) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); - if (Found.first != Found.second) { - PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first); + if (!Found.empty()) { + PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Found.front()); } } @@ -298,8 +338,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { D->getInnerLocStart(), D->getLocation(), D->getIdentifier(), DI->getType(), DI, - D->getStorageClass(), - D->getStorageClassAsWritten()); + D->getStorageClass()); Var->setThreadSpecified(D->isThreadSpecified()); Var->setInitStyle(D->getInitStyle()); Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); @@ -322,6 +361,11 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Var->setReferenced(D->isReferenced()); } + SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope); + + if (Var->hasAttrs()) + SemaRef.CheckAlignasUnderalignment(Var); + // FIXME: In theory, we could have a previous declaration for variables that // are not static data members. // FIXME: having to fake up a LookupResult is dumb. @@ -345,7 +389,6 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { if (Owner->isFunctionOrMethod()) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var); } - SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope); // Link instantiations of static data members back to the template from // which they were instantiated. @@ -459,6 +502,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope); + if (Field->hasAttrs()) + SemaRef.CheckAlignasUnderalignment(Field); + if (Invalid) Field->setInvalidDecl(); @@ -745,8 +791,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (!isFriend && Pattern->getPreviousDecl()) { DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); - if (Found.first != Found.second) { - PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first); + if (!Found.empty()) { + PrevClassTemplate = dyn_cast<ClassTemplateDecl>(Found.front()); if (PrevClassTemplate) PrevDecl = PrevClassTemplate->getTemplatedDecl(); } @@ -911,11 +957,11 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( // of the class template and return that. DeclContext::lookup_result Found = Owner->lookup(ClassTemplate->getDeclName()); - if (Found.first == Found.second) + if (Found.empty()) return 0; ClassTemplateDecl *InstClassTemplate - = dyn_cast<ClassTemplateDecl>(*Found.first); + = dyn_cast<ClassTemplateDecl>(Found.front()); if (!InstClassTemplate) return 0; @@ -1043,8 +1089,8 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo(); NewEPI.ExtInfo = OrigFunc->getExtInfo(); return Context.getFunctionType(NewFunc->getResultType(), - NewFunc->arg_type_begin(), - NewFunc->getNumArgs(), + ArrayRef<QualType>(NewFunc->arg_type_begin(), + NewFunc->getNumArgs()), NewEPI); } @@ -1116,10 +1162,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, FunctionDecl *Function = FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), D->getNameInfo(), T, TInfo, - D->getStorageClass(), D->getStorageClassAsWritten(), + D->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr()); + if (D->isInlined()) + Function->setImplicitlyInline(); + if (QualifierLoc) Function->setQualifierInfo(QualifierLoc); @@ -1287,7 +1336,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // // If -Wc++98-compat is enabled, we go through the motions of checking for a // redefinition, but don't instantiate the function. - if ((!SemaRef.getLangOpts().CPlusPlus0x || + if ((!SemaRef.getLangOpts().CPlusPlus11 || SemaRef.Diags.getDiagnosticLevel( diag::warn_cxx98_compat_friend_redefinition, Function->getLocation()) @@ -1298,11 +1347,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, if (Function->isDefined(Definition) && Definition->getTemplateSpecializationKind() == TSK_Undeclared) { SemaRef.Diag(Function->getLocation(), - SemaRef.getLangOpts().CPlusPlus0x ? + SemaRef.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_friend_redefinition : diag::err_redefinition) << Function->getDeclName(); SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition); - if (!SemaRef.getLangOpts().CPlusPlus0x) + if (!SemaRef.getLangOpts().CPlusPlus11) Function->setInvalidDecl(); } // Check for redefinitions due to other instantiations of this or @@ -1314,7 +1363,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, continue; switch (R->getFriendObjectKind()) { case Decl::FOK_None: - if (!SemaRef.getLangOpts().CPlusPlus0x && + if (!SemaRef.getLangOpts().CPlusPlus11 && !queuedInstantiation && R->isUsed(false)) { if (MemberSpecializationInfo *MSInfo = Function->getMemberSpecializationInfo()) { @@ -1333,12 +1382,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, = R->getTemplateInstantiationPattern()) if (RPattern->isDefined(RPattern)) { SemaRef.Diag(Function->getLocation(), - SemaRef.getLangOpts().CPlusPlus0x ? + SemaRef.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_friend_redefinition : diag::err_redefinition) << Function->getDeclName(); SemaRef.Diag(R->getLocation(), diag::note_previous_definition); - if (!SemaRef.getLangOpts().CPlusPlus0x) + if (!SemaRef.getLangOpts().CPlusPlus11) Function->setInvalidDecl(); break; } @@ -1479,12 +1528,14 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, } else { Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - D->isStatic(), - D->getStorageClassAsWritten(), + D->getStorageClass(), D->isInlineSpecified(), D->isConstexpr(), D->getLocEnd()); } + if (D->isInlined()) + Method->setImplicitlyInline(); + if (QualifierLoc) Method->setQualifierInfo(QualifierLoc); @@ -1581,10 +1632,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, SemaRef.CheckOverrideControl(Method); // If a function is defined as defaulted or deleted, mark it as such now. - if (D->isDefaulted()) - Method->setDefaulted(); + if (D->isExplicitlyDefaulted()) + SemaRef.SetDeclDefaulted(Method, Method->getLocation()); if (D->isDeletedAsWritten()) - Method->setDeletedAsWritten(); + SemaRef.SetDeclDeleted(Method, Method->getLocation()); // If there's a function template, let our caller handle it. if (FunctionTemplate) { @@ -1610,13 +1661,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Owner->addDecl(Method); } - if (D->isExplicitlyDefaulted()) { - SemaRef.SetDeclDefaulted(Method, Method->getLocation()); - } else { - assert(!D->isDefaulted() && - "should not implicitly default uninstantiated function"); - } - return Method; } @@ -1633,9 +1677,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { } ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, - llvm::Optional<unsigned>(), - /*ExpectParameterPack=*/false); + return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, None, + /*ExpectParameterPack=*/ false); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( @@ -1701,7 +1744,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( // 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); + PackExpansionTypeLoc Expansion = TL.castAs<PackExpansionTypeLoc>(); TypeLoc Pattern = Expansion.getPatternLoc(); SmallVector<UnexpandedParameterPack, 2> Unexpanded; SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); @@ -1710,9 +1753,9 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( // be expanded. bool Expand = true; bool RetainExpansion = false; - llvm::Optional<unsigned> OrigNumExpansions + Optional<unsigned> OrigNumExpansions = Expansion.getTypePtr()->getNumExpansions(); - llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + Optional<unsigned> NumExpansions = OrigNumExpansions; if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(), Pattern.getSourceRange(), Unexpanded, @@ -1867,7 +1910,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( // be expanded. bool Expand = true; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; if (SemaRef.CheckParameterPacksForExpansion(D->getLocation(), TempParams->getSourceRange(), Unexpanded, @@ -2069,7 +2112,7 @@ Decl * TemplateDeclInstantiator SS.Adopt(QualifierLoc); // Since NameInfo refers to a typename, it cannot be a C++ special name. - // Hence, no tranformation is required for it. + // Hence, no transformation is required for it. DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation()); NamedDecl *UD = SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), @@ -2138,6 +2181,23 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( return NewFD; } +Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl( + OMPThreadPrivateDecl *D) { + SmallVector<DeclRefExpr *, 5> Vars; + for (ArrayRef<DeclRefExpr *>::iterator I = D->varlist_begin(), + E = D->varlist_end(); + I != E; ++I) { + Expr *Var = SemaRef.SubstExpr(*I, TemplateArgs).take(); + assert(isa<DeclRefExpr>(Var) && "threadprivate arg is not a DeclRefExpr"); + Vars.push_back(cast<DeclRefExpr>(Var)); + } + + OMPThreadPrivateDecl *TD = + SemaRef.CheckOMPThreadPrivateDecl(D->getLocation(), Vars); + + return TD; +} + Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs) { TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); @@ -2330,18 +2390,17 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, if (NewTInfo != OldTInfo) { // Get parameters from the new type info. TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); - if (FunctionProtoTypeLoc *OldProtoLoc - = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) { + if (FunctionProtoTypeLoc OldProtoLoc = + OldTL.getAs<FunctionProtoTypeLoc>()) { TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens(); - FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL); - assert(NewProtoLoc && "Missing prototype?"); + FunctionProtoTypeLoc NewProtoLoc = NewTL.castAs<FunctionProtoTypeLoc>(); unsigned NewIdx = 0; - for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs(); + for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc.getNumArgs(); OldIdx != NumOldParams; ++OldIdx) { - ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx); + ParmVarDecl *OldParam = OldProtoLoc.getArg(OldIdx); LocalInstantiationScope *Scope = SemaRef.CurrentInstantiationScope; - llvm::Optional<unsigned> NumArgumentsInExpansion; + Optional<unsigned> NumArgumentsInExpansion; if (OldParam->isParameterPack()) NumArgumentsInExpansion = SemaRef.getNumArgumentsInExpansion(OldParam->getType(), @@ -2349,14 +2408,14 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, if (!NumArgumentsInExpansion) { // Simple case: normal parameter, or a parameter pack that's // instantiated to a (still-dependent) parameter pack. - ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); + ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++); Params.push_back(NewParam); Scope->InstantiatedLocal(OldParam, NewParam); } else { // Parameter pack expansion: make the instantiation an argument pack. Scope->MakeInstantiatedLocalArgPack(OldParam); for (unsigned I = 0; I != *NumArgumentsInExpansion; ++I) { - ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); + ParmVarDecl *NewParam = NewProtoLoc.getArg(NewIdx++); Params.push_back(NewParam); Scope->InstantiatedLocalPackArg(OldParam, NewParam); } @@ -2368,10 +2427,10 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, // 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 (FunctionProtoTypeLoc OldProtoLoc = + OldTL.getAs<FunctionProtoTypeLoc>()) { + 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); @@ -2403,7 +2462,7 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, // Expand the parameter pack. Scope.MakeInstantiatedLocalArgPack(PatternParam); - llvm::Optional<unsigned> NumArgumentsInExpansion + Optional<unsigned> NumArgumentsInExpansion = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); assert(NumArgumentsInExpansion && "should only be called when all template arguments are known"); @@ -2434,7 +2493,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, ThisTypeQuals = Method->getTypeQualifiers(); } Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals, - SemaRef.getLangOpts().CPlusPlus0x); + SemaRef.getLangOpts().CPlusPlus11); // The function has an exception specification or a "noreturn" // attribute. Substitute into each of the exception types. @@ -2452,7 +2511,7 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, bool Expand = false; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions + Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions(); if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), SourceRange(), @@ -2541,8 +2600,8 @@ static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New, EPI.NoexceptExpr = NoexceptExpr; New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), - NewProto->arg_type_begin(), - NewProto->getNumArgs(), + ArrayRef<QualType>(NewProto->arg_type_begin(), + NewProto->getNumArgs()), EPI)); } @@ -2560,8 +2619,8 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); EPI.ExceptionSpecType = EST_None; Decl->setType(Context.getFunctionType(Proto->getResultType(), - Proto->arg_type_begin(), - Proto->getNumArgs(), + ArrayRef<QualType>(Proto->arg_type_begin(), + Proto->getNumArgs()), EPI)); return; } @@ -2605,12 +2664,12 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { if (FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) { + = dyn_cast<FunctionTemplateDecl>(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); + ActiveInst.Entity = New; } } @@ -2622,7 +2681,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, // DR1330: In C++11, defer instantiation of a non-trivial // exception specification. - if (SemaRef.getLangOpts().CPlusPlus0x && + if (SemaRef.getLangOpts().CPlusPlus11 && EPI.ExceptionSpecType != EST_None && EPI.ExceptionSpecType != EST_DynamicNone && EPI.ExceptionSpecType != EST_BasicNoexcept) { @@ -2641,8 +2700,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, EPI.ExceptionSpecDecl = New; EPI.ExceptionSpecTemplate = ExceptionSpecTemplate; New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), - NewProto->arg_type_begin(), - NewProto->getNumArgs(), + ArrayRef<QualType>(NewProto->arg_type_begin(), + NewProto->getNumArgs()), EPI)); } else { ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs); @@ -2770,6 +2829,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, !PatternDecl->isInlined()) return; + if (PatternDecl->isInlined()) + Function->setImplicitlyInline(); + InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); if (Inst) return; @@ -2789,7 +2851,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, 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 @@ -2801,21 +2862,21 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, LocalInstantiationScope Scope(*this, MergeWithParentScope); - // Enter the scope of this instantiation. We don't use - // PushDeclContext because we don't have a scope. - Sema::ContextRAII savedContext(*this, Function); + if (PatternDecl->isDefaulted()) + SetDeclDefaulted(Function, PatternDecl->getLocation()); + else { + ActOnStartOfFunctionDef(0, Function); - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(Function, 0, false, PatternDecl); + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + Sema::ContextRAII savedContext(*this, Function); - addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, - TemplateArgs); + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(Function, 0, false, PatternDecl); - if (PatternDecl->isDefaulted()) { - ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true); + addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope, + TemplateArgs); - SetDeclDefaulted(Function, PatternDecl->getLocation()); - } else { // If this is a constructor, instantiate the member initializers. if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(PatternDecl)) { @@ -2831,11 +2892,11 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, ActOnFinishFunctionBody(Function, Body.get(), /*IsInstantiation=*/true); - } - PerformDependentDiagnostics(PatternDecl, TemplateArgs); + PerformDependentDiagnostics(PatternDecl, TemplateArgs); - savedContext.pop(); + savedContext.pop(); + } DeclGroupRef DG(Function); Consumer.HandleTopLevelDecl(DG); @@ -2928,7 +2989,18 @@ void Sema::InstantiateStaticDataMemberDefinition( if (TSK == TSK_ExplicitInstantiationDeclaration) return; - Consumer.HandleCXXStaticMemberVarInstantiation(Var); + // Make sure to pass the instantiated variable to the consumer at the end. + struct PassToConsumerRAII { + ASTConsumer &Consumer; + VarDecl *Var; + + PassToConsumerRAII(ASTConsumer &Consumer, VarDecl *Var) + : Consumer(Consumer), Var(Var) { } + + ~PassToConsumerRAII() { + Consumer.HandleCXXStaticMemberVarInstantiation(Var); + } + } PassToConsumerRAII(Consumer, Var); // If we already have a definition, we're done. if (VarDecl *Def = Var->getDefinition()) { @@ -2965,12 +3037,11 @@ void Sema::InstantiateStaticDataMemberDefinition( previousContext.pop(); if (Var) { + PassToConsumerRAII.Var = Var; MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo(); assert(MSInfo && "Missing member specialization information?"); Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation()); - DeclGroupRef DG(Var); - Consumer.HandleTopLevelDecl(DG); } Local.Exit(); @@ -3024,7 +3095,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, collectUnexpandedParameterPacks(BaseTL, Unexpanded); bool ShouldExpand = false; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), BaseTL.getSourceRange(), Unexpanded, @@ -3142,49 +3213,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, ActOnMemInitializers(New, /*FIXME: ColonLoc */ SourceLocation(), - NewInits.data(), NewInits.size(), + NewInits, AnyErrors); } -ExprResult Sema::SubstInitializer(Expr *Init, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool CXXDirectInit) { - // Initializers are instantiated like expressions, except that various outer - // layers are stripped. - if (!Init) - return Owned(Init); - - 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 this is a direct-initializer, we take apart CXXConstructExprs. - // Everything else is passed through. - CXXConstructExpr *Construct; - if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) || - isa<CXXTemporaryObjectExpr>(Construct)) - return SubstExpr(Init, TemplateArgs); - - SmallVector<Expr*, 8> NewArgs; - if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, - TemplateArgs, NewArgs)) - return ExprError(); - - // Treat an empty initializer like none. - if (NewArgs.empty()) - return Owned((Expr*)0); - - // Build a ParenListExpr to represent anything else. - // FIXME: Fake locations! - SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart()); - return ActOnParenListExpr(Loc, Loc, NewArgs); -} - // TODO: this could be templated if the various decl types used the // same method name. static bool isInstantiationOf(ClassTemplateDecl *Pattern, @@ -3539,7 +3571,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, NamedDecl *Result = 0; if (D->getDeclName()) { DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName()); - Result = findInstantiationOf(Context, D, Found.first, Found.second); + Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); } 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 diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 6147d63..c0ad2be 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -10,14 +10,14 @@ //===----------------------------------------------------------------------===/ #include "clang/Sema/Sema.h" +#include "clang/AST/Expr.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/TypeLoc.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/ScopeInfo.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; @@ -443,17 +443,16 @@ TypeResult Sema::ActOnPackExpansion(ParsedType Type, if (!TSInfo) return true; - TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, - llvm::Optional<unsigned>()); + TypeSourceInfo *TSResult = CheckPackExpansion(TSInfo, EllipsisLoc, None); if (!TSResult) return true; return CreateParsedType(TSResult->getType(), TSResult); } -TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern, - SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions) { +TypeSourceInfo * +Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, + Optional<unsigned> NumExpansions) { // Create the pack expansion type and source-location information. QualType Result = CheckPackExpansion(Pattern->getType(), Pattern->getTypeLoc().getSourceRange(), @@ -462,7 +461,8 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern, return 0; TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result); - PackExpansionTypeLoc TL = cast<PackExpansionTypeLoc>(TSResult->getTypeLoc()); + PackExpansionTypeLoc TL = + TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>(); TL.setEllipsisLoc(EllipsisLoc); // Copy over the source-location information from the type. @@ -472,10 +472,9 @@ TypeSourceInfo *Sema::CheckPackExpansion(TypeSourceInfo *Pattern, return TSResult; } -QualType Sema::CheckPackExpansion(QualType Pattern, - SourceRange PatternRange, +QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions) { + 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 @@ -490,11 +489,11 @@ QualType Sema::CheckPackExpansion(QualType Pattern, } ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) { - return CheckPackExpansion(Pattern, EllipsisLoc, llvm::Optional<unsigned>()); + return CheckPackExpansion(Pattern, EllipsisLoc, None); } ExprResult Sema::CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions) { + Optional<unsigned> NumExpansions) { if (!Pattern) return ExprError(); @@ -526,13 +525,11 @@ getDepthAndIndex(NamedDecl *ND) { return std::make_pair(TTP->getDepth(), TTP->getIndex()); } -bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, - SourceRange PatternRange, - ArrayRef<UnexpandedParameterPack> Unexpanded, - const MultiLevelTemplateArgumentList &TemplateArgs, - bool &ShouldExpand, - bool &RetainExpansion, - llvm::Optional<unsigned> &NumExpansions) { +bool Sema::CheckParameterPacksForExpansion( + SourceLocation EllipsisLoc, SourceRange PatternRange, + ArrayRef<UnexpandedParameterPack> Unexpanded, + const MultiLevelTemplateArgumentList &TemplateArgs, bool &ShouldExpand, + bool &RetainExpansion, Optional<unsigned> &NumExpansions) { ShouldExpand = true; RetainExpansion = false; std::pair<IdentifierInfo *, SourceLocation> FirstPack; @@ -636,13 +633,13 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, return false; } -llvm::Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T, +Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs) { QualType Pattern = cast<PackExpansionType>(T)->getPattern(); SmallVector<UnexpandedParameterPack, 2> Unexpanded; CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern); - llvm::Optional<unsigned> Result; + Optional<unsigned> Result; for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) { // Compute the depth and index for this parameter pack. unsigned Depth; @@ -664,7 +661,7 @@ llvm::Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T, if (Instantiation->is<Decl*>()) // The pattern refers to an unexpanded pack. We're not ready to expand // this pack yet. - return llvm::Optional<unsigned>(); + return None; unsigned Size = Instantiation->get<DeclArgumentPack *>()->size(); assert((!Result || *Result == Size) && "inconsistent pack sizes"); @@ -678,7 +675,7 @@ llvm::Optional<unsigned> Sema::getNumArgumentsInExpansion(QualType T, !TemplateArgs.hasTemplateArgument(Depth, Index)) // The pattern refers to an unknown template argument. We're not ready to // expand this pack yet. - return llvm::Optional<unsigned>(); + return None; // Determine the size of the argument pack. unsigned Size = TemplateArgs(Depth, Index).pack_size(); @@ -731,6 +728,14 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_class: case TST_auto: case TST_unknown_anytype: + case TST_image1d_t: + case TST_image1d_array_t: + case TST_image1d_buffer_t: + case TST_image2d_t: + case TST_image2d_array_t: + case TST_image3d_t: + case TST_sampler_t: + case TST_event_t: case TST_error: break; } @@ -837,7 +842,7 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, return ExprError(); } - MarkAnyDeclReferenced(OpLoc, ParameterPack); + MarkAnyDeclReferenced(OpLoc, ParameterPack, true); return new (Context) SizeOfPackExpr(Context.getSizeType(), OpLoc, ParameterPack, NameLoc, RParenLoc); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 4b23167..7169eea 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -11,18 +11,16 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/ScopeInfo.h" #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/Expr.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" -#include "clang/AST/Expr.h" +#include "clang/Basic/OpenCL.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" #include "clang/Lex/Preprocessor.h" @@ -30,7 +28,10 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Template.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -106,7 +107,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_Pascal: \ case AttributeList::AT_Regparm: \ case AttributeList::AT_Pcs: \ - case AttributeList::AT_PnaclCall \ + case AttributeList::AT_PnaclCall: \ + case AttributeList::AT_IntelOclBicc \ namespace { /// An object which stores processing state for the entire @@ -149,6 +151,10 @@ namespace { return declarator; } + bool isProcessingDeclSpec() const { + return chunkIndex == declarator.getNumTypeObjects(); + } + unsigned getCurrentChunkIndex() const { return chunkIndex; } @@ -159,8 +165,7 @@ namespace { } AttributeList *&getCurrentAttrListRef() const { - assert(chunkIndex <= declarator.getNumTypeObjects()); - if (chunkIndex == declarator.getNumTypeObjects()) + if (isProcessingDeclSpec()) return getMutableDeclSpec().getAttributes().getListRef(); return declarator.getTypeObject(chunkIndex).getAttrListRef(); } @@ -269,8 +274,18 @@ static void moveAttrFromListToList(AttributeList &attr, spliceAttrIntoList(attr, toList); } +/// The location of a type attribute. +enum TypeAttrLocation { + /// The attribute is in the decl-specifier-seq. + TAL_DeclSpec, + /// The attribute is part of a DeclaratorChunk. + TAL_DeclChunk, + /// The attribute is immediately after the declaration's name. + TAL_DeclName +}; + static void processTypeAttrs(TypeProcessingState &state, - QualType &type, bool isDeclSpec, + QualType &type, TypeAttrLocation TAL, AttributeList *attrs); static bool handleFunctionTypeAttr(TypeProcessingState &state, @@ -291,6 +306,66 @@ static bool handleObjCPointerTypeAttr(TypeProcessingState &state, return handleObjCOwnershipTypeAttr(state, attr, type); } +/// Given the index of a declarator chunk, check whether that chunk +/// directly specifies the return type of a function and, if so, find +/// an appropriate place for it. +/// +/// \param i - a notional index which the search will start +/// immediately inside +static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator, + unsigned i) { + assert(i <= declarator.getNumTypeObjects()); + + DeclaratorChunk *result = 0; + + // First, look inwards past parens for a function declarator. + for (; i != 0; --i) { + DeclaratorChunk &fnChunk = declarator.getTypeObject(i-1); + switch (fnChunk.Kind) { + case DeclaratorChunk::Paren: + continue; + + // If we find anything except a function, bail out. + case DeclaratorChunk::Pointer: + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::Array: + case DeclaratorChunk::Reference: + case DeclaratorChunk::MemberPointer: + return result; + + // If we do find a function declarator, scan inwards from that, + // looking for a block-pointer declarator. + case DeclaratorChunk::Function: + for (--i; i != 0; --i) { + DeclaratorChunk &blockChunk = declarator.getTypeObject(i-1); + switch (blockChunk.Kind) { + case DeclaratorChunk::Paren: + case DeclaratorChunk::Pointer: + case DeclaratorChunk::Array: + case DeclaratorChunk::Function: + case DeclaratorChunk::Reference: + case DeclaratorChunk::MemberPointer: + continue; + case DeclaratorChunk::BlockPointer: + result = &blockChunk; + goto continue_outer; + } + llvm_unreachable("bad declarator chunk kind"); + } + + // If we run out of declarators doing that, we're done. + return result; + } + llvm_unreachable("bad declarator chunk kind"); + + // Okay, reconsider from our new point. + continue_outer: ; + } + + // Ran out of chunks, bail out. + return result; +} + /// 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 @@ -300,22 +375,44 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, AttributeList &attr, QualType type) { Declarator &declarator = state.getDeclarator(); + + // Move it to the outermost normal or block pointer declarator. for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) { DeclaratorChunk &chunk = declarator.getTypeObject(i-1); switch (chunk.Kind) { case DeclaratorChunk::Pointer: - case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::BlockPointer: { + // But don't move an ARC ownership attribute to the return type + // of a block. + DeclaratorChunk *destChunk = 0; + if (state.isProcessingDeclSpec() && + attr.getKind() == AttributeList::AT_ObjCOwnership) + destChunk = maybeMovePastReturnType(declarator, i - 1); + if (!destChunk) destChunk = &chunk; + moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + destChunk->getAttrListRef()); return; + } case DeclaratorChunk::Paren: case DeclaratorChunk::Array: continue; + // We may be starting at the return type of a block. + case DeclaratorChunk::Function: + if (state.isProcessingDeclSpec() && + attr.getKind() == AttributeList::AT_ObjCOwnership) { + if (DeclaratorChunk *dest = maybeMovePastReturnType(declarator, i)) { + moveAttrFromListToList(attr, state.getCurrentAttrListRef(), + dest->getAttrListRef()); + return; + } + } + goto error; + // Don't walk through these. case DeclaratorChunk::Reference: - case DeclaratorChunk::Function: case DeclaratorChunk::MemberPointer: goto error; } @@ -452,6 +549,15 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, QualType &declSpecType) { state.saveDeclSpecAttrs(); + // C++11 attributes before the decl specifiers actually appertain to + // the declarators. Move them straight there. We don't support the + // 'put them wherever you like' semantics we allow for GNU attributes. + if (attr.isCXX11Attribute()) { + moveAttrFromListToList(attr, state.getCurrentAttrListRef(), + state.getDeclarator().getAttrListRef()); + return; + } + // Try to distribute to the innermost. if (distributeFunctionTypeAttrToInnermost(state, attr, state.getCurrentAttrListRef(), @@ -501,6 +607,11 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, do { next = attr->getNext(); + // Do not distribute C++11 attributes. They have strict rules for what + // they appertain to. + if (attr->isCXX11Attribute()) + continue; + switch (attr->getKind()) { OBJC_POINTER_TYPE_ATTRS_CASELIST: distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType); @@ -712,7 +823,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { if (!S.getLangOpts().C99) { if (S.getLangOpts().CPlusPlus) S.Diag(DS.getTypeSpecWidthLoc(), - S.getLangOpts().CPlusPlus0x ? + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); else S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong); @@ -731,7 +842,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { if (!S.getLangOpts().C99) { if (S.getLangOpts().CPlusPlus) S.Diag(DS.getTypeSpecWidthLoc(), - S.getLangOpts().CPlusPlus0x ? + S.getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); else S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong); @@ -742,6 +853,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { break; } case DeclSpec::TST_int128: + if (!S.PP.getTargetInfo().hasInt128Type()) + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported); if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned) Result = Context.UnsignedInt128Ty; else @@ -901,6 +1014,38 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } break; + case DeclSpec::TST_image1d_t: + Result = Context.OCLImage1dTy; + break; + + case DeclSpec::TST_image1d_array_t: + Result = Context.OCLImage1dArrayTy; + break; + + case DeclSpec::TST_image1d_buffer_t: + Result = Context.OCLImage1dBufferTy; + break; + + case DeclSpec::TST_image2d_t: + Result = Context.OCLImage2dTy; + break; + + case DeclSpec::TST_image2d_array_t: + Result = Context.OCLImage2dArrayTy; + break; + + case DeclSpec::TST_image3d_t: + Result = Context.OCLImage3dTy; + break; + + case DeclSpec::TST_sampler_t: + Result = Context.OCLSamplerTy; + break; + + case DeclSpec::TST_event_t: + Result = Context.OCLEventTy; + break; + case DeclSpec::TST_error: Result = Context.IntTy; declarator.setInvalidType(true); @@ -936,57 +1081,27 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // 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); + processTypeAttrs(state, Result, TAL_DeclSpec, 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(); + S.Diag(DS.getConstSpecLoc(), diag::warn_typecheck_function_qualifiers) + << Result << DS.getSourceRange(); else if (TypeQuals & DeclSpec::TQ_volatile) - Loc = DS.getVolatileSpecLoc(); + S.Diag(DS.getVolatileSpecLoc(), diag::warn_typecheck_function_qualifiers) + << Result << DS.getSourceRange(); else { - assert((TypeQuals & DeclSpec::TQ_restrict) && - "Has CVR quals but not C, V, or R?"); - Loc = DS.getRestrictSpecLoc(); + assert((TypeQuals & (DeclSpec::TQ_restrict | DeclSpec::TQ_atomic)) && + "Has CVRA quals but not C, V, R, or A?"); + // No diagnostic; we'll diagnose 'restrict' or '_Atomic' applied to a + // function type later, in BuildQualifiedType. } - S.Diag(Loc, diag::warn_typecheck_function_qualifiers) - << Result << DS.getSourceRange(); } // C++ [dcl.ref]p1: @@ -999,6 +1114,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { TypeQuals && Result->isReferenceType()) { TypeQuals &= ~DeclSpec::TQ_const; TypeQuals &= ~DeclSpec::TQ_volatile; + TypeQuals &= ~DeclSpec::TQ_atomic; } // C90 6.5.3 constraints: "The same type qualifier shall not appear more @@ -1016,12 +1132,17 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { << "volatile"; } - // C90 doesn't have restrict, so it doesn't force us to produce a warning - // in this case. + // C90 doesn't have restrict nor _Atomic, so it doesn't force us to + // produce a warning in this case. } - Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals); - Result = Context.getQualifiedType(Result, Quals); + QualType Qualified = S.BuildQualifiedType(Result, DeclLoc, TypeQuals, &DS); + + // If adding qualifiers fails, just use the unqualified type. + if (Qualified.isNull()) + declarator.setInvalidType(true); + else + Result = Qualified; } return Result; @@ -1035,37 +1156,36 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) { } QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, - Qualifiers Qs) { + Qualifiers Qs, const DeclSpec *DS) { // 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()) { + if (T->isAnyPointerType() || T->isReferenceType() || + T->isMemberPointerType()) { + QualType EltTy; + if (T->isObjCObjectPointerType()) + EltTy = T; + else if (const MemberPointerType *PTy = T->getAs<MemberPointerType>()) + EltTy = PTy->getPointeeType(); + else + EltTy = T->getPointeeType(); + + // If we have a pointer or reference, the pointee must have an object + // incomplete type. + if (!EltTy->isIncompleteOrObjectType()) { DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; - ProblemTy = T->getAs<PointerType>()->getPointeeType(); + ProblemTy = EltTy; } - } else if (!Ty->isDependentType()) { - // FIXME: this deserves a proper diagnostic - DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + } else if (!T->isDependentType()) { + DiagID = diag::err_typecheck_invalid_restrict_not_pointer; ProblemTy = T; } if (DiagID) { - Diag(Loc, DiagID) << ProblemTy; + Diag(DS ? DS->getRestrictSpecLoc() : Loc, DiagID) << ProblemTy; Qs.removeRestrict(); } } @@ -1073,6 +1193,39 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, return Context.getQualifiedType(T, Qs); } +QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, + unsigned CVRA, const DeclSpec *DS) { + // Convert from DeclSpec::TQ to Qualifiers::TQ by just dropping TQ_atomic. + unsigned CVR = CVRA & ~DeclSpec::TQ_atomic; + + // C11 6.7.3/5: + // If the same qualifier appears more than once in the same + // specifier-qualifier-list, either directly or via one or more typedefs, + // the behavior is the same as if it appeared only once. + // + // It's not specified what happens when the _Atomic qualifier is applied to + // a type specified with the _Atomic specifier, but we assume that this + // should be treated as if the _Atomic qualifier appeared multiple times. + if (CVRA & DeclSpec::TQ_atomic && !T->isAtomicType()) { + // C11 6.7.3/5: + // If other qualifiers appear along with the _Atomic qualifier in a + // specifier-qualifier-list, the resulting type is the so-qualified + // atomic type. + // + // Don't need to worry about array types here, since _Atomic can't be + // applied to such types. + SplitQualType Split = T.getSplitUnqualifiedType(); + T = BuildAtomicType(QualType(Split.Ty, 0), + DS ? DS->getAtomicSpecLoc() : Loc); + if (T.isNull()) + return T; + Split.Quals.addCVRQualifiers(CVR); + return BuildQualifiedType(T, Loc, Split.Quals); + } + + return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR), DS); +} + /// \brief Build a paren type including \p T. QualType Sema::BuildParenType(QualType T) { return Context.getParenType(T); @@ -1338,7 +1491,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, // C99 6.7.5.2p1: The size expression shall have integer type. // C++11 allows contextual conversions to such types. - if (!getLangOpts().CPlusPlus0x && + if (!getLangOpts().CPlusPlus11 && ArraySize && !ArraySize->isTypeDependent() && !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) @@ -1359,7 +1512,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, isArraySizeVLA(*this, ArraySize, ConstVal)) { // Even in C++11, don't allow contextual conversions in the array bound // of a VLA. - if (getLangOpts().CPlusPlus0x && + if (getLangOpts().CPlusPlus11 && !ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) { Diag(ArraySize->getLocStart(), diag::err_array_size_non_int) << ArraySize->getType() << ArraySize->getSourceRange(); @@ -1409,6 +1562,12 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, T = Context.getConstantArrayType(T, ConstVal, ASM, Quals); } + + // OpenCL v1.2 s6.9.d: variable length arrays are not supported. + if (getLangOpts().OpenCL && T->isVariableArrayType()) { + Diag(Loc, diag::err_opencl_vla); + return QualType(); + } // If this is not C99, extwarn about VLA's and C99 array size modifiers. if (!getLangOpts().C99) { if (T->isVariableArrayType()) { @@ -1435,6 +1594,11 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, : diag::ext_c99_array_usage) << ASM; } + if (T->isVariableArrayType()) { + // Warn about VLAs for -Wvla. + Diag(Loc, diag::warn_vla_used); + } + return T; } @@ -1475,45 +1639,10 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, 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 HasTrailingReturn Whether this function has a trailing return 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, bool HasTrailingReturn, - unsigned Quals, - RefQualifierKind RefQualifier, + llvm::MutableArrayRef<QualType> ParamTypes, SourceLocation Loc, DeclarationName Entity, - FunctionType::ExtInfo Info) { + const FunctionProtoType::ExtProtoInfo &EPI) { if (T->isArrayType() || T->isFunctionType()) { Diag(Loc, diag::err_func_returning_array_function) << T->isFunctionType() << T; @@ -1528,7 +1657,7 @@ QualType Sema::BuildFunctionType(QualType T, } bool Invalid = false; - for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) { + for (unsigned Idx = 0, Cnt = ParamTypes.size(); Idx < Cnt; ++Idx) { // FIXME: Loc is too inprecise here, should use proper locations for args. QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]); if (ParamType->isVoidType()) { @@ -1547,14 +1676,7 @@ QualType Sema::BuildFunctionType(QualType T, if (Invalid) return QualType(); - FunctionProtoType::ExtProtoInfo EPI; - EPI.Variadic = Variadic; - EPI.HasTrailingReturn = HasTrailingReturn; - EPI.TypeQuals = Quals; - EPI.RefQualifier = RefQualifier; - EPI.ExtInfo = Info; - - return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI); + return Context.getFunctionType(T, ParamTypes, EPI); } /// \brief Build a member pointer type \c T Class::*. @@ -1601,13 +1723,33 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType 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.getTargetInfo().getCXXABI() == CXXABI_Microsoft && - RequireCompleteType(Loc, Class, diag::err_incomplete_type)) - return QualType(); + // C++ allows the class type in a member pointer to be an incomplete type. + // In the Microsoft ABI, the size of the member pointer can vary + // according to the class type, which means that we really need a + // complete type if possible, which means we need to instantiate templates. + // + // If template instantiation fails or the type is just incomplete, we have to + // add an extra slot to the member pointer. Yes, this does cause problems + // when passing pointers between TUs that disagree about the size. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + CXXRecordDecl *RD = Class->getAsCXXRecordDecl(); + if (RD && !RD->hasAttr<MSInheritanceAttr>()) { + // Lock in the inheritance model on the first use of a member pointer. + // Otherwise we may disagree about the size at different points in the TU. + // FIXME: MSVC picks a model on the first use that needs to know the size, + // rather than on the first mention of the type, e.g. typedefs. + if (RequireCompleteType(Loc, Class, 0) && !RD->isBeingDefined()) { + // We know it doesn't have an attribute and it's incomplete, so use the + // unspecified inheritance model. If we're in the record body, we can + // figure out the inheritance model. + for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), + E = RD->redecls_end(); I != E; ++I) { + I->addAttr(::new (Context) UnspecifiedInheritanceAttr( + RD->getSourceRange(), Context)); + } + } + } + } return Context.getMemberPointerType(T, Class.getTypePtr()); } @@ -1754,50 +1896,118 @@ static void inferARCWriteback(TypeProcessingState &state, // TODO: mark whether we did this inference? } -static void DiagnoseIgnoredQualifiers(unsigned Quals, - SourceLocation ConstQualLoc, - SourceLocation VolatileQualLoc, - SourceLocation RestrictQualLoc, - Sema& S) { - std::string QualStr; +static void diagnoseIgnoredQualifiers( + Sema &S, unsigned Quals, + SourceLocation FallbackLoc, + SourceLocation ConstQualLoc = SourceLocation(), + SourceLocation VolatileQualLoc = SourceLocation(), + SourceLocation RestrictQualLoc = SourceLocation(), + SourceLocation AtomicQualLoc = SourceLocation()) { + if (!Quals) + return; + + const SourceManager &SM = S.getSourceManager(); + + struct Qual { + unsigned Mask; + const char *Name; + SourceLocation Loc; + } const QualKinds[4] = { + { DeclSpec::TQ_const, "const", ConstQualLoc }, + { DeclSpec::TQ_volatile, "volatile", VolatileQualLoc }, + { DeclSpec::TQ_restrict, "restrict", RestrictQualLoc }, + { DeclSpec::TQ_atomic, "_Atomic", AtomicQualLoc } + }; + + llvm::SmallString<32> QualStr; unsigned NumQuals = 0; SourceLocation Loc; + FixItHint FixIts[4]; + + // Build a string naming the redundant qualifiers. + for (unsigned I = 0; I != 4; ++I) { + if (Quals & QualKinds[I].Mask) { + if (!QualStr.empty()) QualStr += ' '; + QualStr += QualKinds[I].Name; + + // If we have a location for the qualifier, offer a fixit. + SourceLocation QualLoc = QualKinds[I].Loc; + if (!QualLoc.isInvalid()) { + FixIts[NumQuals] = FixItHint::CreateRemoval(QualLoc); + if (Loc.isInvalid() || SM.isBeforeInTranslationUnit(QualLoc, Loc)) + Loc = QualLoc; + } - FixItHint ConstFixIt; - FixItHint VolatileFixIt; - FixItHint RestrictFixIt; + ++NumQuals; + } + } - const SourceManager &SM = S.getSourceManager(); + S.Diag(Loc.isInvalid() ? FallbackLoc : Loc, diag::warn_qual_return_type) + << QualStr << NumQuals << FixIts[0] << FixIts[1] << FixIts[2] << FixIts[3]; +} + +// Diagnose pointless type qualifiers on the return type of a function. +static void diagnoseIgnoredFunctionQualifiers(Sema &S, QualType RetTy, + Declarator &D, + unsigned FunctionChunkIndex) { + if (D.getTypeObject(FunctionChunkIndex).Fun.hasTrailingReturnType()) { + // FIXME: TypeSourceInfo doesn't preserve location information for + // qualifiers. + diagnoseIgnoredQualifiers(S, RetTy.getLocalCVRQualifiers(), + D.getIdentifierLoc()); + return; + } + + for (unsigned OuterChunkIndex = FunctionChunkIndex + 1, + End = D.getNumTypeObjects(); + OuterChunkIndex != End; ++OuterChunkIndex) { + DeclaratorChunk &OuterChunk = D.getTypeObject(OuterChunkIndex); + switch (OuterChunk.Kind) { + case DeclaratorChunk::Paren: + continue; + + case DeclaratorChunk::Pointer: { + DeclaratorChunk::PointerTypeInfo &PTI = OuterChunk.Ptr; + diagnoseIgnoredQualifiers( + S, PTI.TypeQuals, + SourceLocation(), + SourceLocation::getFromRawEncoding(PTI.ConstQualLoc), + SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc), + SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc), + SourceLocation::getFromRawEncoding(PTI.AtomicQualLoc)); + return; + } + + case DeclaratorChunk::Function: + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::Reference: + case DeclaratorChunk::Array: + case DeclaratorChunk::MemberPointer: + // FIXME: We can't currently provide an accurate source location and a + // fix-it hint for these. + unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0; + diagnoseIgnoredQualifiers(S, RetTy.getCVRQualifiers() | AtomicQual, + D.getIdentifierLoc()); + return; + } + + llvm_unreachable("unknown declarator chunk kind"); + } + + // If the qualifiers come from a conversion function type, don't diagnose + // them -- they're not necessarily redundant, since such a conversion + // operator can be explicitly called as "x.operator const int()". + if (D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) + return; - // 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; + // Just parens all the way out to the decl specifiers. Diagnose any qualifiers + // which are present there. + diagnoseIgnoredQualifiers(S, D.getDeclSpec().getTypeQualifiers(), + D.getIdentifierLoc(), + D.getDeclSpec().getConstSpecLoc(), + D.getDeclSpec().getVolatileSpecLoc(), + D.getDeclSpec().getRestrictSpecLoc(), + D.getDeclSpec().getAtomicSpecLoc()); } static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, @@ -1832,7 +2042,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // "void" instead. T = SemaRef.Context.VoidTy; if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList()) - processTypeAttrs(state, T, true, attrs); + processTypeAttrs(state, T, TAL_DeclSpec, attrs); break; case UnqualifiedId::IK_ConversionFunctionId: @@ -1851,7 +2061,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // 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 && - (!SemaRef.getLangOpts().CPlusPlus0x || !D.isFunctionDeclarator())) { + (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) { int Error = -1; switch (D.getContext()) { @@ -1917,7 +2127,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // 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 (SemaRef.getLangOpts().CPlusPlus0x && Error != -1) { + if (SemaRef.getLangOpts().CPlusPlus11 && Error != -1) { for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { unsigned chunkIndex = e - i - 1; state.setCurrentChunkIndex(chunkIndex); @@ -1969,6 +2179,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, SemaRef.Diag(OwnedTagDecl->getLocation(), diag::err_type_defined_in_alias_template) << SemaRef.Context.getTypeDeclType(OwnedTagDecl); + D.setInvalidType(true); break; case Declarator::TypeNameContext: case Declarator::TemplateParamContext: @@ -1979,6 +2190,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, SemaRef.Diag(OwnedTagDecl->getLocation(), diag::err_type_defined_in_type_specifier) << SemaRef.Context.getTypeDeclType(OwnedTagDecl); + D.setInvalidType(true); break; case Declarator::PrototypeContext: case Declarator::ObjCParameterContext: @@ -1989,6 +2201,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, SemaRef.Diag(OwnedTagDecl->getLocation(), diag::err_type_defined_in_param_type) << SemaRef.Context.getTypeDeclType(OwnedTagDecl); + D.setInvalidType(true); break; case Declarator::ConditionContext: // C++ 6.4p2: @@ -1996,6 +2209,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // a new class or enumeration. SemaRef.Diag(OwnedTagDecl->getLocation(), diag::err_type_defined_in_condition); + D.setInvalidType(true); break; } } @@ -2087,7 +2301,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, if (!D.isFunctionDeclarator() || D.getFunctionDefinitionKind() != FDK_Declaration || !S.CurContext->isFunctionOrMethod() || - D.getDeclSpec().getStorageClassSpecAsWritten() + D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_unspecified) return; @@ -2150,7 +2364,7 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, << FixItHint::CreateRemoval(ParenRange); else { std::string Init = S.getFixItZeroInitializerForType(RT); - if (Init.empty() && S.LangOpts.CPlusPlus0x) + if (Init.empty() && S.LangOpts.CPlusPlus11) Init = "{}"; if (!Init.empty()) S.Diag(DeclType.Loc, diag::note_empty_parens_zero_initialize) @@ -2376,38 +2590,61 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Do not allow returning half FP value. // FIXME: This really should be in BuildFunctionType. if (T->isHalfType()) { - S.Diag(D.getIdentifierLoc(), - diag::err_parameters_retval_cannot_have_fp16_type) << 1 - << FixItHint::CreateInsertion(D.getIdentifierLoc(), "*"); - D.setInvalidType(true); + if (S.getLangOpts().OpenCL) { + if (!S.getOpenCLOptions().cl_khr_fp16) { + S.Diag(D.getIdentifierLoc(), diag::err_opencl_half_return) << T; + D.setInvalidType(true); + } + } else { + S.Diag(D.getIdentifierLoc(), + diag::err_parameters_retval_cannot_have_fp16_type) << 1; + 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) && - (!LangOpts.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), - S); - - } else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() && - (!LangOpts.CPlusPlus || - (!T->isDependentType() && !T->isRecordType()))) { - - DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(), - D.getDeclSpec().getConstSpecLoc(), - D.getDeclSpec().getVolatileSpecLoc(), - D.getDeclSpec().getRestrictSpecLoc(), - S); + if ((T.getCVRQualifiers() || T->isAtomicType()) && + !(S.getLangOpts().CPlusPlus && + (T->isDependentType() || T->isRecordType()))) + diagnoseIgnoredFunctionQualifiers(S, T, D, chunkIndex); + + // Objective-C ARC ownership qualifiers are ignored on the function + // return type (by type canonicalization). Complain if this attribute + // was written here. + if (T.getQualifiers().hasObjCLifetime()) { + SourceLocation AttrLoc; + if (chunkIndex + 1 < D.getNumTypeObjects()) { + DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); + for (const AttributeList *Attr = ReturnTypeChunk.getAttrs(); + Attr; Attr = Attr->getNext()) { + if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = Attr->getLoc(); + break; + } + } + } + if (AttrLoc.isInvalid()) { + for (const AttributeList *Attr + = D.getDeclSpec().getAttributes().getList(); + Attr; Attr = Attr->getNext()) { + if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = Attr->getLoc(); + break; + } + } + } + + if (AttrLoc.isValid()) { + // The ownership attributes are almost always written via + // the predefined + // __strong/__weak/__autoreleasing/__unsafe_unretained. + if (AttrLoc.isMacroID()) + AttrLoc = S.SourceMgr.getImmediateExpansionRange(AttrLoc).first; + + S.Diag(AttrLoc, diag::warn_arc_lifetime_result_type) + << T.getQualifiers().getObjCLifetime(); + } } if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) { @@ -2457,6 +2694,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // definition. S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); D.setInvalidType(true); + // Recover by creating a K&R-style function type. + T = Context.getFunctionNoProtoType(T); break; } @@ -2514,10 +2753,18 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } else if (ArgTy->isHalfType()) { // Disallow half FP arguments. // FIXME: This really should be in BuildFunctionType. - S.Diag(Param->getLocation(), - diag::err_parameters_retval_cannot_have_fp16_type) << 0 - << FixItHint::CreateInsertion(Param->getLocation(), "*"); - D.setInvalidType(); + if (S.getLangOpts().OpenCL) { + if (!S.getOpenCLOptions().cl_khr_fp16) { + S.Diag(Param->getLocation(), + diag::err_opencl_half_argument) << ArgTy; + D.setInvalidType(); + Param->setInvalidDecl(); + } + } else { + S.Diag(Param->getLocation(), + diag::err_parameters_retval_cannot_have_fp16_type) << 0; + D.setInvalidType(); + } } else if (!FTI.hasPrototype) { if (ArgTy->isPromotableIntegerType()) { ArgTy = Context.getPromotedIntegerType(ArgTy); @@ -2568,7 +2815,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, Exceptions, EPI); - T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI); + T = Context.getFunctionType(T, ArgTys, EPI); } break; @@ -2634,7 +2881,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // See if there are any attributes on this declarator chunk. if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs())) - processTypeAttrs(state, T, false, attrs); + processTypeAttrs(state, T, TAL_DeclChunk, attrs); } if (LangOpts.CPlusPlus && T->isFunctionType()) { @@ -2659,30 +2906,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, FreeFunction = (DC && !DC->isRecord()); } - // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member - // function that is not a constructor declares that function to be const. - // FIXME: This should be deferred until we know whether this is a static - // member function (for an out-of-class definition, we don't know - // this until we perform redeclaration lookup). - if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static && - D.getName().getKind() != UnqualifiedId::IK_ConstructorName && - D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId && - !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) { - // Rebuild function type adding a 'const' qualifier. - FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo(); - EPI.TypeQuals |= DeclSpec::TQ_const; - T = Context.getFunctionType(FnTy->getResultType(), - FnTy->arg_type_begin(), - FnTy->getNumArgs(), EPI); - // Rebuild any parens around the identifier in the function type. - for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { - if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren) - break; - T = S.BuildParenType(T); - } - } - // C++11 [dcl.fct]p6 (w/DR1417): // An attempt to specify a function type with a cv-qualifier-seq or a // ref-qualifier (including by typedef-name) is ill-formed unless it is: @@ -2732,8 +2955,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, EPI.RefQualifier = RQ_None; T = Context.getFunctionType(FnTy->getResultType(), - FnTy->arg_type_begin(), - FnTy->getNumArgs(), EPI); + ArrayRef<QualType>(FnTy->arg_type_begin(), + FnTy->getNumArgs()), + EPI); // Rebuild any parens around the identifier in the function type. for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { if (D.getTypeObject(i).Kind != DeclaratorChunk::Paren) @@ -2746,7 +2970,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Apply any undistributed attributes from the declarator. if (!T.isNull()) if (AttributeList *attrs = D.getAttributes()) - processTypeAttrs(state, T, false, attrs); + processTypeAttrs(state, T, TAL_DeclName, attrs); // Diagnose any ignored type attributes. if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T); @@ -2782,7 +3006,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, << T << D.getSourceRange(); D.setEllipsisLoc(SourceLocation()); } else { - T = Context.getPackExpansionType(T, llvm::Optional<unsigned>()); + T = Context.getPackExpansionType(T, None); } break; @@ -2796,10 +3020,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // 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>()); + T = Context.getPackExpansionType(T, None); else S.Diag(D.getEllipsisLoc(), - LangOpts.CPlusPlus0x + LangOpts.CPlusPlus11 ? diag::warn_cxx98_compat_variadic_templates : diag::ext_variadic_templates); break; @@ -3006,6 +3230,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_Pcs; case AttributedType::attr_pnaclcall: return AttributeList::AT_PnaclCall; + case AttributedType::attr_inteloclbicc: + return AttributeList::AT_IntelOclBicc; } llvm_unreachable("unexpected attribute kind!"); } @@ -3099,13 +3325,13 @@ namespace { TypeLoc OldTL = TInfo->getTypeLoc(); if (TInfo->getType()->getAs<ElaboratedType>()) { - ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL); - TemplateSpecializationTypeLoc NamedTL = - cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc()); + ElaboratedTypeLoc ElabTL = OldTL.castAs<ElaboratedTypeLoc>(); + TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc() + .castAs<TemplateSpecializationTypeLoc>(); TL.copy(NamedTL); } else - TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL)); + TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>()); } void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr); @@ -3153,7 +3379,7 @@ namespace { TypeSourceInfo *TInfo = 0; Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); if (TInfo) { - TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc())); + TL.copy(TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>()); return; } } @@ -3169,7 +3395,7 @@ namespace { TypeSourceInfo *TInfo = 0; Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); assert(TInfo); - TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc())); + TL.copy(TInfo->getTypeLoc().castAs<DependentNameTypeLoc>()); } void VisitDependentTemplateSpecializationTypeLoc( DependentTemplateSpecializationTypeLoc TL) { @@ -3177,19 +3403,29 @@ namespace { TypeSourceInfo *TInfo = 0; Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); assert(TInfo); - TL.copy(cast<DependentTemplateSpecializationTypeLoc>( - TInfo->getTypeLoc())); + TL.copy( + TInfo->getTypeLoc().castAs<DependentTemplateSpecializationTypeLoc>()); } void VisitTagTypeLoc(TagTypeLoc TL) { TL.setNameLoc(DS.getTypeSpecTypeNameLoc()); } void VisitAtomicTypeLoc(AtomicTypeLoc TL) { - TL.setKWLoc(DS.getTypeSpecTypeLoc()); - TL.setParensRange(DS.getTypeofParensRange()); + // An AtomicTypeLoc can come from either an _Atomic(...) type specifier + // or an _Atomic qualifier. + if (DS.getTypeSpecType() == DeclSpec::TST_atomic) { + TL.setKWLoc(DS.getTypeSpecTypeLoc()); + TL.setParensRange(DS.getTypeofParensRange()); - TypeSourceInfo *TInfo = 0; - Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); - TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc()); + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo); + assert(TInfo); + TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc()); + } else { + TL.setKWLoc(DS.getAtomicSpecLoc()); + // No parens, to indicate this was spelled as an _Atomic qualifier. + TL.setParensRange(SourceRange()); + Visit(TL.getValueLoc()); + } } void VisitTypeLoc(TypeLoc TL) { @@ -3239,7 +3475,7 @@ namespace { case NestedNameSpecifier::Identifier: assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc"); { - DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL); + DependentNameTypeLoc DNTLoc = ClsTL.castAs<DependentNameTypeLoc>(); DNTLoc.setElaboratedKeywordLoc(SourceLocation()); DNTLoc.setQualifierLoc(NNSLoc.getPrefix()); DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc()); @@ -3249,7 +3485,7 @@ namespace { case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: if (isa<ElaboratedType>(ClsTy)) { - ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL); + ElaboratedTypeLoc ETLoc = ClsTL.castAs<ElaboratedTypeLoc>(); ETLoc.setElaboratedKeywordLoc(SourceLocation()); ETLoc.setQualifierLoc(NNSLoc.getPrefix()); TypeLoc NamedTL = ETLoc.getNamedTypeLoc(); @@ -3312,6 +3548,29 @@ namespace { }; } +static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { + SourceLocation Loc; + switch (Chunk.Kind) { + case DeclaratorChunk::Function: + case DeclaratorChunk::Array: + case DeclaratorChunk::Paren: + llvm_unreachable("cannot be _Atomic qualified"); + + case DeclaratorChunk::Pointer: + Loc = SourceLocation::getFromRawEncoding(Chunk.Ptr.AtomicQualLoc); + break; + + case DeclaratorChunk::BlockPointer: + case DeclaratorChunk::Reference: + case DeclaratorChunk::MemberPointer: + // FIXME: Provide a source location for the _Atomic keyword. + break; + } + + ATL.setKWLoc(Loc); + ATL.setParensRange(SourceRange()); +} + /// \brief Create and instantiate a TypeSourceInfo with type source information. /// /// \param T QualType referring to the type as written in source code. @@ -3328,13 +3587,19 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, // Handle parameter packs whose type is a pack expansion. if (isa<PackExpansionType>(T)) { - cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc()); + CurrTL.castAs<PackExpansionTypeLoc>().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); + // An AtomicTypeLoc might be produced by an atomic qualifier in this + // declarator chunk. + if (AtomicTypeLoc ATL = CurrTL.getAs<AtomicTypeLoc>()) { + fillAtomicQualLoc(ATL, D.getTypeObject(i)); + CurrTL = ATL.getValueLoc().getUnqualifiedLoc(); + } + + while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) { fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs()); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -3389,7 +3654,11 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { // Make sure there are no unused decl attributes on the declarator. // We don't want to do this for ObjC parameters because we're going // to apply them to the actual parameter declaration. - if (D.getContext() != Declarator::ObjCParameterContext) + // Likewise, we don't want to do this for alias declarations, because + // we are actually going to build a declaration from this eventually. + if (D.getContext() != Declarator::ObjCParameterContext && + D.getContext() != Declarator::AliasDeclContext && + D.getContext() != Declarator::AliasTemplateContext) checkUnusedDeclAttributes(D); if (getLangOpts().CPlusPlus) { @@ -3524,6 +3793,14 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, } else if (!type->isObjCRetainableType()) { return false; } + + // Don't accept an ownership attribute in the declspec if it would + // just be the return type of a block pointer. + if (state.isProcessingDeclSpec()) { + Declarator &D = state.getDeclarator(); + if (maybeMovePastReturnType(D, D.getNumTypeObjects())) + return false; + } } Sema &S = state.getSema(); @@ -3630,10 +3907,8 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // Forbid __weak for class objects marked as // objc_arc_weak_reference_unavailable if (lifetime == Qualifiers::OCL_Weak) { - QualType T = type; - while (const PointerType *ptr = T->getAs<PointerType>()) - T = ptr->getPointeeType(); - if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) { + if (const ObjCObjectPointerType *ObjT = + type->getAs<ObjCObjectPointerType>()) { if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) { if (Class->isArcWeakrefUnavailable()) { S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class); @@ -4141,7 +4416,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType, } static void processTypeAttrs(TypeProcessingState &state, QualType &type, - bool isDeclSpec, AttributeList *attrs) { + TypeAttrLocation TAL, 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 @@ -4156,10 +4431,45 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (attr.isInvalid()) continue; + if (attr.isCXX11Attribute()) { + // [[gnu::...]] attributes are treated as declaration attributes, so may + // not appertain to a DeclaratorChunk, even if we handle them as type + // attributes. + if (attr.getScopeName() && attr.getScopeName()->isStr("gnu")) { + if (TAL == TAL_DeclChunk) { + state.getSema().Diag(attr.getLoc(), + diag::warn_cxx11_gnu_attribute_on_type) + << attr.getName(); + continue; + } + } else if (TAL != TAL_DeclChunk) { + // Otherwise, only consider type processing for a C++11 attribute if + // it's actually been applied to a type. + 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; + default: + // A C++11 attribute on a declarator chunk must appertain to a type. + if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) { + state.getSema().Diag(attr.getLoc(), diag::err_attribute_not_type_attr) + << attr.getName(); + attr.setUsedAsTypeAttr(); + } + break; + + case AttributeList::UnknownAttribute: + if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk) + state.getSema().Diag(attr.getLoc(), + diag::warn_unknown_attribute_ignored) + << attr.getName(); + break; + + case AttributeList::IgnoredAttribute: + break; case AttributeList::AT_MayAlias: // FIXME: This attribute needs to actually be handled, but if we ignore @@ -4180,9 +4490,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, attr.setUsedAsTypeAttr(); break; case AttributeList::AT_ExtVectorType: - if (state.getDeclarator().getDeclSpec().getStorageClassSpec() - != DeclSpec::SCS_typedef) - HandleExtVectorTypeAttr(type, attr, state.getSema()); + HandleExtVectorTypeAttr(type, attr, state.getSema()); attr.setUsedAsTypeAttr(); break; case AttributeList::AT_NeonVectorType: @@ -4204,13 +4512,14 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, case AttributeList::AT_Win64: case AttributeList::AT_Ptr32: case AttributeList::AT_Ptr64: - // FIXME: don't ignore these + // FIXME: Don't ignore these. We have partial handling for them as + // declaration attributes in SemaDeclAttr.cpp; that should be moved here. attr.setUsedAsTypeAttr(); break; case AttributeList::AT_NSReturnsRetained: if (!state.getSema().getLangOpts().ObjCAutoRefCount) - break; + break; // fallthrough into the function attrs FUNCTION_TYPE_ATTRS_CASELIST: @@ -4218,7 +4527,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // Never process function type attributes as part of the // declaration-specifiers. - if (isDeclSpec) + if (TAL == TAL_DeclSpec) distributeFunctionTypeAttrFromDeclSpec(state, attr, type); // Otherwise, handle the possible delays. @@ -4359,9 +4668,14 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, // repeating the diagnostic. // FIXME: Add a Fix-It that imports the corresponding module or includes // the header. - if (isSFINAEContext() || HiddenDefinitions.insert(Def)) { - Diag(Loc, diag::err_module_private_definition) << T; - Diag(Def->getLocation(), diag::note_previous_definition); + Module *Owner = Def->getOwningModule(); + Diag(Loc, diag::err_module_private_definition) + << T << Owner->getFullModuleName(); + Diag(Def->getLocation(), diag::note_previous_definition); + + if (!isSFINAEContext()) { + // Recover by implicitly importing this module. + createImplicitModuleImport(Loc, Owner); } } @@ -4562,6 +4876,8 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, Diag(Dtor->getLocation(), Dtor->isUserProvided() ? diag::note_non_literal_user_provided_dtor : diag::note_non_literal_nontrivial_dtor) << RD; + if (!Dtor->isUserProvided()) + SpecialMemberIsTrivial(Dtor, CXXDestructor, /*Diagnose*/true); } return true; diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp index 25ace95..2f77012 100644 --- a/lib/Sema/TargetAttributesSema.cpp +++ b/lib/Sema/TargetAttributesSema.cpp @@ -13,9 +13,9 @@ //===----------------------------------------------------------------------===// #include "TargetAttributesSema.h" -#include "clang/Sema/SemaInternal.h" -#include "clang/Basic/TargetInfo.h" #include "clang/AST/DeclCXX.h" +#include "clang/Basic/TargetInfo.h" +#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/Triple.h" using namespace clang; @@ -151,7 +151,8 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D, S.Context)); } -DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range) { +DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex) { if (D->hasAttr<DLLExportAttr>()) { Diag(Range.getBegin(), diag::warn_attribute_ignored) << "dllimport"; return NULL; @@ -160,7 +161,8 @@ DLLImportAttr *Sema::mergeDLLImportAttr(Decl *D, SourceRange Range) { if (D->hasAttr<DLLImportAttr>()) return NULL; - return ::new (Context) DLLImportAttr(Range, Context); + return ::new (Context) DLLImportAttr(Range, Context, + AttrSpellingListIndex); } static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -189,12 +191,14 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange()); + unsigned Index = Attr.getAttributeSpellingListIndex(); + DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index); if (NewAttr) D->addAttr(NewAttr); } -DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range) { +DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex) { if (DLLImportAttr *Import = D->getAttr<DLLImportAttr>()) { Diag(Import->getLocation(), diag::warn_attribute_ignored) << "dllimport"; D->dropAttr<DLLImportAttr>(); @@ -203,7 +207,8 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range) { if (D->hasAttr<DLLExportAttr>()) return NULL; - return ::new (Context) DLLExportAttr(Range, Context); + return ::new (Context) DLLExportAttr(Range, Context, + AttrSpellingListIndex); } static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -229,7 +234,8 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange()); + unsigned Index = Attr.getAttributeSpellingListIndex(); + DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index); if (NewAttr) D->addAttr(NewAttr); } @@ -262,6 +268,57 @@ namespace { }; } +static void HandleMips16Attr(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; + } + // Attribute can only be applied to function types. + if (!isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << /* function */0; + return; + } + D->addAttr(::new (S.Context) Mips16Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +static void HandleNoMips16Attr(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; + } + // Attribute can only be applied to function types. + if (!isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << /* function */0; + return; + } + D->addAttr(::new (S.Context) + NoMips16Attr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); +} + +namespace { + class MipsAttributesSema : public TargetAttributesSema { + public: + MipsAttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, + Sema &S) const { + if (Attr.getName()->getName() == "mips16") { + HandleMips16Attr(D, Attr, S); + return true; + } else if (Attr.getName()->getName() == "nomips16") { + HandleNoMips16Attr(D, Attr, S); + return true; + } + return false; + } + }; +} + const TargetAttributesSema &Sema::getTargetAttributesSema() const { if (TheTargetAttributesSema) return *TheTargetAttributesSema; @@ -275,6 +332,9 @@ const TargetAttributesSema &Sema::getTargetAttributesSema() const { case llvm::Triple::x86: case llvm::Triple::x86_64: return *(TheTargetAttributesSema = new X86AttributesSema); + case llvm::Triple::mips: + case llvm::Triple::mipsel: + return *(TheTargetAttributesSema = new MipsAttributesSema); default: return *(TheTargetAttributesSema = new TargetAttributesSema); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 294d742..bdd68a7 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -14,11 +14,7 @@ #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 "TypeLocBuilder.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -28,12 +24,16 @@ #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 "clang/Sema/Designator.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorHandling.h" -#include "TypeLocBuilder.h" #include <algorithm> namespace clang { @@ -247,10 +247,10 @@ public: /// must be set. bool TryExpandParameterPacks(SourceLocation EllipsisLoc, SourceRange PatternRange, - llvm::ArrayRef<UnexpandedParameterPack> Unexpanded, + ArrayRef<UnexpandedParameterPack> Unexpanded, bool &ShouldExpand, bool &RetainExpansion, - llvm::Optional<unsigned> &NumExpansions) { + Optional<unsigned> &NumExpansions) { ShouldExpand = false; return false; } @@ -323,6 +323,15 @@ public: /// \returns the transformed expression. ExprResult TransformExpr(Expr *E); + /// \brief Transform the given initializer. + /// + /// By default, this routine transforms an initializer by stripping off the + /// semantic nodes added by initialization, then passing the result to + /// TransformExpr or TransformExprs. + /// + /// \returns the transformed initializer. + ExprResult TransformInitializer(Expr *Init, bool CXXDirectInit); + /// \brief Transform the given list of expressions. /// /// This routine transforms a list of expressions by invoking @@ -563,7 +572,7 @@ public: /// scope index; can be negative ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm, int indexAdjustment, - llvm::Optional<unsigned> NumExpansions, + Optional<unsigned> NumExpansions, bool ExpectParameterPack); QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); @@ -704,12 +713,8 @@ public: /// 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, bool HasTrailingReturn, - unsigned Quals, - RefQualifierKind RefQualifier, - const FunctionType::ExtInfo &Info); + llvm::MutableArrayRef<QualType> ParamTypes, + const FunctionProtoType::ExtProtoInfo &EPI); /// \brief Build a new unprototyped function type. QualType RebuildFunctionNoProtoType(QualType ResultType); @@ -941,7 +946,7 @@ public: QualType RebuildPackExpansionType(QualType Pattern, SourceRange PatternRange, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions) { + Optional<unsigned> NumExpansions) { return getSema().CheckPackExpansion(Pattern, PatternRange, EllipsisLoc, NumExpansions); } @@ -2113,6 +2118,7 @@ public: bool IsElidable, MultiExprArg Args, bool HadMultipleCandidates, + bool ListInitialization, bool RequiresZeroInit, CXXConstructExpr::ConstructionKind ConstructKind, SourceRange ParenRange) { @@ -2124,6 +2130,7 @@ public: return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable, ConvertedArgs, HadMultipleCandidates, + ListInitialization, RequiresZeroInit, ConstructKind, ParenRange); } @@ -2214,7 +2221,7 @@ public: ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, - llvm::Optional<unsigned> Length) { + Optional<unsigned> Length) { if (Length) return new (SemaRef.Context) SizeOfPackExpr(SemaRef.Context.getSizeType(), OperatorLoc, Pack, PackLoc, @@ -2382,13 +2389,14 @@ public: /// 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, + SourceLocation OpLoc, 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, + OpLoc, SS, 0, false); if (Result.isInvalid() || Base.isInvalid()) return ExprError(); @@ -2397,7 +2405,7 @@ public: return Result; return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), - /*FIXME:*/IsaLoc, IsArrow, + OpLoc, IsArrow, SS, SourceLocation(), /*FirstQualifierInScope=*/0, R, @@ -2416,10 +2424,10 @@ public: = 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?"); + assert(!Lookup.empty() && "No __builtin_shufflevector?"); // Build a reference to the __builtin_shufflevector builtin - FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); + FunctionDecl *Builtin = cast<FunctionDecl>(Lookup.front()); Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, false, SemaRef.Context.BuiltinFnTy, VK_RValue, BuiltinLoc); @@ -2445,7 +2453,7 @@ public: /// different behavior. TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions) { + Optional<unsigned> NumExpansions) { switch (Pattern.getArgument().getKind()) { case TemplateArgument::Expression: { ExprResult Result @@ -2492,7 +2500,7 @@ public: /// for an expression. Subclasses may override this routine to provide /// different behavior. ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, - llvm::Optional<unsigned> NumExpansions) { + Optional<unsigned> NumExpansions) { return getSema().CheckPackExpansion(Pattern, EllipsisLoc, NumExpansions); } @@ -2549,7 +2557,7 @@ StmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { if (E.isInvalid()) return StmtError(); - return getSema().ActOnExprStmt(getSema().MakeFullExpr(E.take())); + return getSema().ActOnExprStmt(E); } } @@ -2575,6 +2583,65 @@ ExprResult TreeTransform<Derived>::TransformExpr(Expr *E) { } template<typename Derived> +ExprResult TreeTransform<Derived>::TransformInitializer(Expr *Init, + bool CXXDirectInit) { + // Initializers are instantiated like expressions, except that various outer + // layers are stripped. + if (!Init) + return SemaRef.Owned(Init); + + 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 this is not a direct-initializer, we only need to reconstruct + // InitListExprs. Other forms of copy-initialization will be a no-op if + // the initializer is already the right type. + CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init); + if (!CXXDirectInit && !(Construct && Construct->isListInitialization())) + return getDerived().TransformExpr(Init); + + // Revert value-initialization back to empty parens. + if (CXXScalarValueInitExpr *VIE = dyn_cast<CXXScalarValueInitExpr>(Init)) { + SourceRange Parens = VIE->getSourceRange(); + return getDerived().RebuildParenListExpr(Parens.getBegin(), MultiExprArg(), + Parens.getEnd()); + } + + // FIXME: We shouldn't build ImplicitValueInitExprs for direct-initialization. + if (isa<ImplicitValueInitExpr>(Init)) + return getDerived().RebuildParenListExpr(SourceLocation(), MultiExprArg(), + SourceLocation()); + + // Revert initialization by constructor back to a parenthesized or braced list + // of expressions. Any other form of initializer can just be reused directly. + if (!Construct || isa<CXXTemporaryObjectExpr>(Construct)) + return getDerived().TransformExpr(Init); + + SmallVector<Expr*, 8> NewArgs; + bool ArgChanged = false; + if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(), + /*IsCall*/true, NewArgs, &ArgChanged)) + return ExprError(); + + // If this was list initialization, revert to list form. + if (Construct->isListInitialization()) + return getDerived().RebuildInitList(Construct->getLocStart(), NewArgs, + Construct->getLocEnd(), + Construct->getType()); + + // Build a ParenListExpr to represent anything else. + SourceRange Parens = Construct->getParenRange(); + return getDerived().RebuildParenListExpr(Parens.getBegin(), NewArgs, + Parens.getEnd()); +} + +template<typename Derived> bool TreeTransform<Derived>::TransformExprs(Expr **Inputs, unsigned NumInputs, bool IsCall, @@ -2600,9 +2667,8 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs, // be expanded. bool Expand = true; bool RetainExpansion = false; - llvm::Optional<unsigned> OrigNumExpansions - = Expansion->getNumExpansions(); - llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + Optional<unsigned> OrigNumExpansions = Expansion->getNumExpansions(); + Optional<unsigned> NumExpansions = OrigNumExpansions; if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, @@ -2656,7 +2722,9 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs, continue; } - ExprResult Result = getDerived().TransformExpr(Inputs[I]); + ExprResult Result = + IsCall ? getDerived().TransformInitializer(Inputs[I], /*DirectInit*/false) + : getDerived().TransformExpr(Inputs[I]); if (Result.isInvalid()) return true; @@ -2732,7 +2800,7 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc( return NestedNameSpecifierLoc(); if (TL.getType()->isDependentType() || TL.getType()->isRecordType() || - (SemaRef.getLangOpts().CPlusPlus0x && + (SemaRef.getLangOpts().CPlusPlus11 && TL.getType()->isEnumeralType())) { assert(!TL.getType().hasLocalQualifiers() && "Can't get cv-qualifiers here"); @@ -2745,8 +2813,8 @@ TreeTransform<Derived>::TransformNestedNameSpecifierLoc( } // 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()) { + TypedefTypeLoc TTL = TL.getAs<TypedefTypeLoc>(); + if (!TTL || !TTL.getTypedefNameDecl()->isInvalidDecl()) { SemaRef.Diag(TL.getBeginLoc(), diag::err_nested_name_spec_non_tag) << TL.getType() << SS.getRange(); } @@ -3119,7 +3187,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, // We have a pack expansion, for which we will be substituting into // the pattern. SourceLocation Ellipsis; - llvm::Optional<unsigned> OrigNumExpansions; + Optional<unsigned> OrigNumExpansions; TemplateArgumentLoc Pattern = In.getPackExpansionPattern(Ellipsis, OrigNumExpansions, getSema().Context); @@ -3132,7 +3200,7 @@ bool TreeTransform<Derived>::TransformTemplateArguments(InputIterator First, // be expanded. bool Expand = true; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + Optional<unsigned> NumExpansions = OrigNumExpansions; if (getDerived().TryExpandParameterPacks(Ellipsis, Pattern.getSourceRange(), Unexpanded, @@ -3254,9 +3322,10 @@ 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)); +#define TYPELOC(CLASS, PARENT) \ + case TypeLoc::CLASS: \ + return getDerived().Transform##CLASS##Type(TLB, \ + T.castAs<CLASS##TypeLoc>()); #include "clang/AST/TypeLocNodes.def" } @@ -3293,6 +3362,7 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, // Objective-C ARC: // A lifetime qualifier applied to a substituted template parameter // overrides the lifetime qualifier from the template argument. + const AutoType *AutoTy; if (const SubstTemplateTypeParmType *SubstTypeParam = dyn_cast<SubstTemplateTypeParmType>(Result)) { QualType Replacement = SubstTypeParam->getReplacementType(); @@ -3305,6 +3375,15 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, SubstTypeParam->getReplacedParameter(), Replacement); TLB.TypeWasModifiedSafely(Result); + } else if ((AutoTy = dyn_cast<AutoType>(Result)) && AutoTy->isDeduced()) { + // 'auto' types behave the same way as template parameters. + QualType Deduced = AutoTy->getDeducedType(); + Qualifiers Qs = Deduced.getQualifiers(); + Qs.removeObjCLifetime(); + Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(), + Qs); + Result = SemaRef.Context.getAutoType(Deduced); + TLB.TypeWasModifiedSafely(Result); } else { // Otherwise, complain about the addition of a qualifier to an // already-qualified type. @@ -3318,7 +3397,9 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, } if (!Quals.empty()) { Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals); - TLB.push<QualifiedTypeLoc>(Result); + // BuildQualifiedType might not add qualifiers if they are invalid. + if (Result.hasLocalQualifiers()) + TLB.push<QualifiedTypeLoc>(Result); // No location information to preserve. } @@ -3339,8 +3420,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, QualType Result; if (isa<TemplateSpecializationType>(T)) { - TemplateSpecializationTypeLoc SpecTL - = cast<TemplateSpecializationTypeLoc>(TL); + TemplateSpecializationTypeLoc SpecTL = + TL.castAs<TemplateSpecializationTypeLoc>(); TemplateName Template = getDerived().TransformTemplateName(SS, @@ -3353,8 +3434,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeLoc TL, Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, Template); } else if (isa<DependentTemplateSpecializationType>(T)) { - DependentTemplateSpecializationTypeLoc SpecTL - = cast<DependentTemplateSpecializationTypeLoc>(TL); + DependentTemplateSpecializationTypeLoc SpecTL = + TL.castAs<DependentTemplateSpecializationTypeLoc>(); TemplateName Template = getDerived().RebuildTemplateName(SS, @@ -3396,8 +3477,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo, TypeLoc TL = TSInfo->getTypeLoc(); if (isa<TemplateSpecializationType>(T)) { - TemplateSpecializationTypeLoc SpecTL - = cast<TemplateSpecializationTypeLoc>(TL); + TemplateSpecializationTypeLoc SpecTL = + TL.castAs<TemplateSpecializationTypeLoc>(); TemplateName Template = getDerived().TransformTemplateName(SS, @@ -3410,8 +3491,8 @@ TreeTransform<Derived>::TransformTypeInObjectScope(TypeSourceInfo *TSInfo, Result = getDerived().TransformTemplateSpecializationType(TLB, SpecTL, Template); } else if (isa<DependentTemplateSpecializationType>(T)) { - DependentTemplateSpecializationTypeLoc SpecTL - = cast<DependentTemplateSpecializationTypeLoc>(TL); + DependentTemplateSpecializationTypeLoc SpecTL = + TL.castAs<DependentTemplateSpecializationTypeLoc>(); TemplateName Template = getDerived().RebuildTemplateName(SS, @@ -3864,12 +3945,10 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB, return Result; } -template<typename Derived> -ParmVarDecl * -TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, - int indexAdjustment, - llvm::Optional<unsigned> NumExpansions, - bool ExpectParameterPack) { +template <typename Derived> +ParmVarDecl *TreeTransform<Derived>::TransformFunctionTypeParam( + ParmVarDecl *OldParm, int indexAdjustment, Optional<unsigned> NumExpansions, + bool ExpectParameterPack) { TypeSourceInfo *OldDI = OldParm->getTypeSourceInfo(); TypeSourceInfo *NewDI = 0; @@ -3877,7 +3956,7 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, // If we're substituting into a pack expansion type and we know the // length we want to expand to, just substitute for the pattern. TypeLoc OldTL = OldDI->getTypeLoc(); - PackExpansionTypeLoc OldExpansionTL = cast<PackExpansionTypeLoc>(OldTL); + PackExpansionTypeLoc OldExpansionTL = OldTL.castAs<PackExpansionTypeLoc>(); TypeLocBuilder TLB; TypeLoc NewTL = OldDI->getTypeLoc(); @@ -3915,7 +3994,6 @@ TreeTransform<Derived>::TransformFunctionTypeParam(ParmVarDecl *OldParm, NewDI->getType(), NewDI, OldParm->getStorageClass(), - OldParm->getStorageClassAsWritten(), /* DefArg */ NULL); newParm->setScopeInfo(OldParm->getFunctionScopeDepth(), OldParm->getFunctionScopeIndex() + indexAdjustment); @@ -3935,7 +4013,7 @@ bool TreeTransform<Derived>:: if (ParmVarDecl *OldParm = Params[i]) { assert(OldParm->getFunctionScopeIndex() == i); - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; ParmVarDecl *NewParm = 0; if (OldParm->isParameterPack()) { // We have a function parameter pack that may need to be expanded. @@ -3943,7 +4021,7 @@ bool TreeTransform<Derived>:: // Find the parameter packs that could be expanded. TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc(); - PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(TL); + PackExpansionTypeLoc ExpansionTL = TL.castAs<PackExpansionTypeLoc>(); TypeLoc Pattern = ExpansionTL.getPatternLoc(); SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); assert(Unexpanded.size() > 0 && "Could not find parameter packs!"); @@ -3951,8 +4029,8 @@ bool TreeTransform<Derived>:: // Determine whether we should expand the parameter packs. bool ShouldExpand = false; bool RetainExpansion = false; - llvm::Optional<unsigned> OrigNumExpansions - = ExpansionTL.getTypePtr()->getNumExpansions(); + Optional<unsigned> OrigNumExpansions = + ExpansionTL.getTypePtr()->getNumExpansions(); NumExpansions = OrigNumExpansions; if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), Pattern.getSourceRange(), @@ -4017,10 +4095,8 @@ bool TreeTransform<Derived>:: NumExpansions, /*ExpectParameterPack=*/true); } else { - NewParm = getDerived().TransformFunctionTypeParam(OldParm, - indexAdjustment, - llvm::Optional<unsigned>(), - /*ExpectParameterPack=*/false); + NewParm = getDerived().TransformFunctionTypeParam( + OldParm, indexAdjustment, None, /*ExpectParameterPack=*/ false); } if (!NewParm) @@ -4036,7 +4112,7 @@ bool TreeTransform<Derived>:: // declaration for this parameter. QualType OldType = ParamTypes[i]; bool IsPackExpansion = false; - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; QualType NewType; if (const PackExpansionType *Expansion = dyn_cast<PackExpansionType>(OldType)) { @@ -4188,14 +4264,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, 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->hasTrailingReturn(), - T->getTypeQuals(), - T->getRefQualifier(), - T->getExtInfo()); + Result = getDerived().RebuildFunctionProtoType(ResultType, ParamTypes, + T->getExtProtoInfo()); if (Result.isNull()) return QualType(); } @@ -4561,7 +4631,6 @@ QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB, return Result; } -namespace { /// \brief Simple iterator that traverses the template arguments in a /// container that provides a \c getArgLoc() member function. /// @@ -4625,7 +4694,6 @@ namespace { return !(X == Y); } }; -} template <typename Derived> @@ -5379,7 +5447,7 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) { if (Inc.isInvalid()) return StmtError(); - Sema::FullExprArg FullInc(getSema().MakeFullExpr(Inc.get())); + Sema::FullExprArg FullInc(getSema().MakeFullDiscardedValueExpr(Inc.get())); if (S->getInc() && !FullInc.get()) return StmtError(); @@ -6946,17 +7014,13 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { 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(); return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(), E->getStmtClass(), - FakeLAngleLoc, + E->getAngleBrackets().getBegin(), Type, - FakeRAngleLoc, - FakeRAngleLoc, + E->getAngleBrackets().getEnd(), + // FIXME. this should be '(' location + E->getAngleBrackets().getEnd(), SubExpr.get(), E->getRParenLoc()); } @@ -7105,9 +7169,14 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { QualType T; if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) T = MD->getThisType(getSema().Context); - else + else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) { T = getSema().Context.getPointerType( - getSema().Context.getRecordType(cast<CXXRecordDecl>(DC))); + getSema().Context.getRecordType(Record)); + } else { + assert(SemaRef.Context.getDiagnostics().hasErrorOccurred() && + "this in the wrong scope?"); + return ExprError(); + } if (!getDerived().AlwaysRebuild() && T == E->getType()) { // Make sure that we capture 'this'. @@ -7387,7 +7456,9 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( TypeSourceInfo *ScopeTypeInfo = 0; if (E->getScopeTypeInfo()) { - ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo()); + CXXScopeSpec EmptySS; + ScopeTypeInfo = getDerived().TransformTypeInObjectScope( + E->getScopeTypeInfo(), ObjectType, 0, EmptySS); if (!ScopeTypeInfo) return ExprError(); } @@ -7524,11 +7595,11 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { bool ArgChanged = false; - llvm::SmallVector<TypeSourceInfo *, 4> Args; + SmallVector<TypeSourceInfo *, 4> Args; for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { TypeSourceInfo *From = E->getArg(I); TypeLoc FromTL = From->getTypeLoc(); - if (!isa<PackExpansionTypeLoc>(FromTL)) { + if (!FromTL.getAs<PackExpansionTypeLoc>()) { TypeLocBuilder TLB; TLB.reserve(FromTL.getFullDataSize()); QualType To = getDerived().TransformType(TLB, FromTL); @@ -7547,7 +7618,7 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { ArgChanged = true; // We have a pack expansion. Instantiate it. - PackExpansionTypeLoc ExpansionTL = cast<PackExpansionTypeLoc>(FromTL); + PackExpansionTypeLoc ExpansionTL = FromTL.castAs<PackExpansionTypeLoc>(); TypeLoc PatternTL = ExpansionTL.getPatternLoc(); SmallVector<UnexpandedParameterPack, 2> Unexpanded; SemaRef.collectUnexpandedParameterPacks(PatternTL, Unexpanded); @@ -7556,9 +7627,9 @@ TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { // be expanded. bool Expand = true; bool RetainExpansion = false; - llvm::Optional<unsigned> OrigNumExpansions - = ExpansionTL.getTypePtr()->getNumExpansions(); - llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + Optional<unsigned> OrigNumExpansions = + ExpansionTL.getTypePtr()->getNumExpansions(); + Optional<unsigned> NumExpansions = OrigNumExpansions; if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), PatternTL.getSourceRange(), Unexpanded, @@ -7747,10 +7818,13 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( 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)))) + // CXXConstructExprs other than for list-initialization and + // CXXTemporaryObjectExpr 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)))) && + (!getDerived().DropCallArgument(E->getArg(0))) && + !E->isListInitialization()) return getDerived().TransformExpr(E->getArg(0)); TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); @@ -7786,6 +7860,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { Constructor, E->isElidable(), Args, E->hadMultipleCandidates(), + E->isListInitialization(), E->requiresZeroInitialization(), E->getConstructionKind(), E->getParenRange()); @@ -7843,6 +7918,7 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( return SemaRef.MaybeBindToTemporary(E); } + // FIXME: Pass in E->isListInitialization(). return getDerived().RebuildCXXTemporaryObjectExpr(T, /*FIXME:*/T->getTypeLoc().getEndLoc(), Args, @@ -7867,8 +7943,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { getDerived().transformedLocalDecl(E->getLambdaClass(), Class); // Transform lambda parameters. - llvm::SmallVector<QualType, 4> ParamTypes; - llvm::SmallVector<ParmVarDecl *, 4> Params; + SmallVector<QualType, 4> ParamTypes; + SmallVector<ParmVarDecl *, 4> Params; if (getDerived().TransformFunctionTypeParams(E->getLocStart(), E->getCallOperator()->param_begin(), E->getCallOperator()->param_size(), @@ -7931,7 +8007,7 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E, UnexpandedParameterPack Unexpanded(C->getCapturedVar(), C->getLocation()); bool ShouldExpand = false; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; if (getDerived().TryExpandParameterPacks(C->getEllipsisLoc(), C->getLocation(), Unexpanded, @@ -8274,7 +8350,7 @@ TreeTransform<Derived>::TransformSizeOfPackExpr(SizeOfPackExpr *E) { UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc()); bool ShouldExpand = false; bool RetainExpansion = false; - llvm::Optional<unsigned> NumExpansions; + Optional<unsigned> NumExpansions; if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), Unexpanded, ShouldExpand, RetainExpansion, @@ -8360,7 +8436,7 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformObjCArrayLiteral(ObjCArrayLiteral *E) { // Transform each of the elements. - llvm::SmallVector<Expr *, 8> Elements; + SmallVector<Expr *, 8> Elements; bool ArgChanged = false; if (getDerived().TransformExprs(E->getElements(), E->getNumElements(), /*IsCall=*/false, Elements, &ArgChanged)) @@ -8379,7 +8455,7 @@ ExprResult TreeTransform<Derived>::TransformObjCDictionaryLiteral( ObjCDictionaryLiteral *E) { // Transform each of the elements. - llvm::SmallVector<ObjCDictionaryElement, 8> Elements; + SmallVector<ObjCDictionaryElement, 8> Elements; bool ArgChanged = false; for (unsigned I = 0, N = E->getNumElements(); I != N; ++I) { ObjCDictionaryElement OrigElement = E->getKeyValueElement(I); @@ -8395,8 +8471,8 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral( // and should be expanded. bool Expand = true; bool RetainExpansion = false; - llvm::Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions; - llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + Optional<unsigned> OrigNumExpansions = OrigElement.NumExpansions; + Optional<unsigned> NumExpansions = OrigNumExpansions; SourceRange PatternRange(OrigElement.Key->getLocStart(), OrigElement.Value->getLocEnd()); if (getDerived().TryExpandParameterPacks(OrigElement.EllipsisLoc, @@ -8483,7 +8559,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral( ArgChanged = true; ObjCDictionaryElement Element = { - Key.get(), Value.get(), SourceLocation(), llvm::Optional<unsigned>() + Key.get(), Value.get(), SourceLocation(), None }; Elements.push_back(Element); } @@ -8712,6 +8788,7 @@ TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) { return SemaRef.Owned(E); return getDerived().RebuildObjCIsaExpr(Base.get(), E->getIsaMemberLoc(), + E->getOpLoc(), E->isArrow()); } @@ -8758,7 +8835,7 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { return ExprError(); } - const FunctionType *exprFunctionType = E->getFunctionType(); + const FunctionProtoType *exprFunctionType = E->getFunctionType(); QualType exprResultType = getDerived().TransformType(exprFunctionType->getResultType()); @@ -8771,13 +8848,9 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { return ExprError(); } - QualType functionType = getDerived().RebuildFunctionProtoType( - exprResultType, - paramTypes.data(), - paramTypes.size(), - oldBlock->isVariadic(), - false, 0, RQ_None, - exprFunctionType->getExtInfo()); + QualType functionType = + getDerived().RebuildFunctionProtoType(exprResultType, paramTypes, + exprFunctionType->getExtProtoInfo()); blockScope->FunctionType = functionType; // Set the parameters on the block decl. @@ -8993,19 +9066,14 @@ TreeTransform<Derived>::RebuildDependentSizedExtVectorType(QualType ElementType, } template<typename Derived> -QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T, - QualType *ParamTypes, - unsigned NumParamTypes, - bool Variadic, - bool HasTrailingReturn, - unsigned Quals, - RefQualifierKind RefQualifier, - const FunctionType::ExtInfo &Info) { - return SemaRef.BuildFunctionType(T, ParamTypes, NumParamTypes, Variadic, - HasTrailingReturn, Quals, RefQualifier, +QualType TreeTransform<Derived>::RebuildFunctionProtoType( + QualType T, + llvm::MutableArrayRef<QualType> ParamTypes, + const FunctionProtoType::ExtProtoInfo &EPI) { + return SemaRef.BuildFunctionType(T, ParamTypes, getDerived().getBaseLocation(), getDerived().getBaseEntity(), - Info); + EPI); } template<typename Derived> diff --git a/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h index 7a5e43e..f36ec9f 100644 --- a/lib/Sema/TypeLocBuilder.h +++ b/lib/Sema/TypeLocBuilder.h @@ -15,8 +15,8 @@ #ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H #define LLVM_CLANG_SEMA_TYPELOCBUILDER_H -#include "clang/AST/TypeLoc.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/TypeLoc.h" namespace clang { @@ -75,7 +75,7 @@ class TypeLocBuilder { /// previously retrieved from this builder. TypeSpecTypeLoc pushTypeSpec(QualType T) { size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; - return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); + return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>(); } /// Resets this builder to the newly-initialized state. @@ -97,8 +97,8 @@ class TypeLocBuilder { /// 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)); + size_t LocalSize = TypeLoc(T, 0).castAs<TyLocType>().getLocalDataSize(); + return pushImpl(T, LocalSize).castAs<TyLocType>(); } /// Creates a TypeSourceInfo for the given type. |