diff options
Diffstat (limited to 'lib/Sema')
41 files changed, 5560 insertions, 2925 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 19a7d6f..801a1b1 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -27,6 +27,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/ParentMap.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/AnalysisContext.h" @@ -36,10 +37,12 @@ #include "clang/Analysis/Analyses/ThreadSafety.h" #include "clang/Analysis/CFGStmtMap.h" #include "clang/Analysis/Analyses/UninitializedValues.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.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" @@ -182,13 +185,6 @@ static ControlFlowKind CheckFallThrough(AnalysisDeclContext &AC) { HasFakeEdge = true; continue; } - if (const AsmStmt *AS = dyn_cast<AsmStmt>(S)) { - if (AS->isMSAsm()) { - HasFakeEdge = true; - HasLiveReturn = true; - continue; - } - } if (isa<MSAsmStmt>(S)) { // TODO: Verify this is correct. HasFakeEdge = true; @@ -506,7 +502,7 @@ static void DiagUninitUse(Sema &S, const VarDecl *VD, const UninitUse &Use, // Information used when building the diagnostic. unsigned DiagKind; - const char *Str; + StringRef Str; SourceRange Range; // FixIts to suppress the diagnosic by removing the dead condition. @@ -822,6 +818,18 @@ namespace { static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, bool PerFunction) { + // Only perform this analysis when using C++11. There is no good workflow + // for this warning when not using C++11. There is no good way to silence + // the warning (no attribute is available) unless we are using C++11's support + // for generalized attributes. Once could use pragmas to silence the warning, + // but as a general solution that is gross and not in the spirit of this + // warning. + // + // 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) + return; + FallthroughMapper FM(S); FM.TraverseStmt(AC.getBody()); @@ -859,8 +867,21 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, if (S.getLangOpts().CPlusPlus0x) { const Stmt *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"), + tok::coloncolon, PP.getIdentifierInfo("fallthrough"), + tok::r_square, tok::r_square + }; + StringRef AnnotationSpelling = "[[clang::fallthrough]]"; + StringRef MacroName = PP.getLastMacroWithSpelling(L, Tokens); + if (!MacroName.empty()) + AnnotationSpelling = MacroName; + SmallString<64> TextToInsert(AnnotationSpelling); + TextToInsert += "; "; S.Diag(L, diag::note_insert_fallthrough_fixit) << - FixItHint::CreateInsertion(L, "[[clang::fallthrough]]; "); + AnnotationSpelling << + FixItHint::CreateInsertion(L, TextToInsert); } } S.Diag(L, diag::note_insert_break_fixit) << @@ -878,6 +899,199 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, } namespace { +typedef std::pair<const Stmt *, + sema::FunctionScopeInfo::WeakObjectUseMap::const_iterator> + StmtUsesPair; + +class StmtUseSorter { + const SourceManager &SM; + +public: + explicit StmtUseSorter(const SourceManager &SM) : SM(SM) { } + + bool operator()(const StmtUsesPair &LHS, const StmtUsesPair &RHS) { + return SM.isBeforeInTranslationUnit(LHS.first->getLocStart(), + RHS.first->getLocStart()); + } +}; +} + +static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM, + const Stmt *S) { + assert(S); + + do { + switch (S->getStmtClass()) { + case Stmt::ForStmtClass: + case Stmt::WhileStmtClass: + case Stmt::CXXForRangeStmtClass: + case Stmt::ObjCForCollectionStmtClass: + return true; + case Stmt::DoStmtClass: { + const Expr *Cond = cast<DoStmt>(S)->getCond(); + llvm::APSInt Val; + if (!Cond->EvaluateAsInt(Val, Ctx)) + return true; + return Val.getBoolValue(); + } + default: + break; + } + } while ((S = PM.getParent(S))); + + return false; +} + + +static void diagnoseRepeatedUseOfWeak(Sema &S, + const sema::FunctionScopeInfo *CurFn, + const Decl *D, + const ParentMap &PM) { + typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy; + typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap; + typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector; + + ASTContext &Ctx = S.getASTContext(); + + const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses(); + + // Extract all weak objects that are referenced more than once. + SmallVector<StmtUsesPair, 8> UsesByStmt; + for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end(); + I != E; ++I) { + const WeakUseVector &Uses = I->second; + + // Find the first read of the weak object. + WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); + for ( ; UI != UE; ++UI) { + if (UI->isUnsafe()) + break; + } + + // If there were only writes to this object, don't warn. + if (UI == UE) + continue; + + // If there was only one read, followed by any number of writes, and the + // read is not within a loop, don't warn. Additionally, don't warn in a + // loop if the base object is a local variable -- local variables are often + // changed in loops. + if (UI == Uses.begin()) { + WeakUseVector::const_iterator UI2 = UI; + for (++UI2; UI2 != UE; ++UI2) + if (UI2->isUnsafe()) + break; + + if (UI2 == UE) { + if (!isInLoop(Ctx, PM, UI->getUseExpr())) + continue; + + const WeakObjectProfileTy &Profile = I->first; + if (!Profile.isExactProfile()) + continue; + + const NamedDecl *Base = Profile.getBase(); + if (!Base) + Base = Profile.getProperty(); + assert(Base && "A profile always has a base or property."); + + if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base)) + if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base)) + continue; + } + } + + UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I)); + } + + if (UsesByStmt.empty()) + return; + + // Sort by first use so that we emit the warnings in a deterministic order. + std::sort(UsesByStmt.begin(), UsesByStmt.end(), + StmtUseSorter(S.getSourceManager())); + + // Classify the current code body for better warning text. + // This enum should stay in sync with the cases in + // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. + // FIXME: Should we use a common classification enum and the same set of + // possibilities all throughout Sema? + enum { + Function, + Method, + Block, + Lambda + } FunctionKind; + + if (isa<sema::BlockScopeInfo>(CurFn)) + FunctionKind = Block; + else if (isa<sema::LambdaScopeInfo>(CurFn)) + FunctionKind = Lambda; + else if (isa<ObjCMethodDecl>(D)) + FunctionKind = Method; + else + FunctionKind = Function; + + // Iterate through the sorted problems and emit warnings for each. + for (SmallVectorImpl<StmtUsesPair>::const_iterator I = UsesByStmt.begin(), + E = UsesByStmt.end(); + I != E; ++I) { + const Stmt *FirstRead = I->first; + const WeakObjectProfileTy &Key = I->second->first; + const WeakUseVector &Uses = I->second->second; + + // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy + // may not contain enough information to determine that these are different + // properties. We can only be 100% sure of a repeated use in certain cases, + // and we adjust the diagnostic kind accordingly so that the less certain + // case can be turned off if it is too noisy. + unsigned DiagKind; + if (Key.isExactProfile()) + DiagKind = diag::warn_arc_repeated_use_of_weak; + else + DiagKind = diag::warn_arc_possible_repeated_use_of_weak; + + // Classify the weak object being accessed for better warning text. + // This enum should stay in sync with the cases in + // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak. + enum { + Variable, + Property, + ImplicitProperty, + Ivar + } ObjectKind; + + const NamedDecl *D = Key.getProperty(); + if (isa<VarDecl>(D)) + ObjectKind = Variable; + else if (isa<ObjCPropertyDecl>(D)) + ObjectKind = Property; + else if (isa<ObjCMethodDecl>(D)) + ObjectKind = ImplicitProperty; + else if (isa<ObjCIvarDecl>(D)) + ObjectKind = Ivar; + else + llvm_unreachable("Unexpected weak object kind!"); + + // Show the first time the object was read. + S.Diag(FirstRead->getLocStart(), DiagKind) + << ObjectKind << D << FunctionKind + << FirstRead->getSourceRange(); + + // Print all the other accesses as notes. + for (WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); + UI != UE; ++UI) { + if (UI->getUseExpr() == FirstRead) + continue; + S.Diag(UI->getUseExpr()->getLocStart(), + diag::note_arc_weak_also_accessed_here) + << UI->getUseExpr()->getSourceRange(); + } + } +} + + +namespace { struct SLocSort { bool operator()(const UninitUse &a, const UninitUse &b) { // Prefer a more confident report over a less confident one. @@ -1091,27 +1305,47 @@ class ThreadSafetyReporter : public clang::thread_safety::ThreadSafetyHandler { diag::warn_variable_requires_any_lock: diag::warn_var_deref_requires_any_lock; PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) - << D->getName() << getLockKindFromAccessKind(AK)); + << D->getNameAsString() << getLockKindFromAccessKind(AK)); Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); } void handleMutexNotHeld(const NamedDecl *D, ProtectedOperationKind POK, - Name LockName, LockKind LK, SourceLocation Loc) { + Name LockName, LockKind LK, SourceLocation Loc, + Name *PossibleMatch) { unsigned DiagID = 0; - switch (POK) { - case POK_VarAccess: - DiagID = diag::warn_variable_requires_lock; - break; - case POK_VarDereference: - DiagID = diag::warn_var_deref_requires_lock; - break; - case POK_FunctionCall: - DiagID = diag::warn_fun_requires_lock; - break; + if (PossibleMatch) { + switch (POK) { + case POK_VarAccess: + DiagID = diag::warn_variable_requires_lock_precise; + break; + case POK_VarDereference: + DiagID = diag::warn_var_deref_requires_lock_precise; + break; + case POK_FunctionCall: + DiagID = diag::warn_fun_requires_lock_precise; + break; + } + PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) + << D->getNameAsString() << LockName << LK); + PartialDiagnosticAt Note(Loc, S.PDiag(diag::note_found_mutex_near_match) + << *PossibleMatch); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes(1, Note))); + } else { + switch (POK) { + case POK_VarAccess: + DiagID = diag::warn_variable_requires_lock; + break; + case POK_VarDereference: + DiagID = diag::warn_var_deref_requires_lock; + break; + case POK_FunctionCall: + DiagID = diag::warn_fun_requires_lock; + break; + } + PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) + << D->getNameAsString() << LockName << LK); + Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); } - PartialDiagnosticAt Warning(Loc, S.PDiag(DiagID) - << D->getName() << LockName << LK); - Warnings.push_back(DelayedDiag(Warning, OptionalNotes())); } void handleFunExcludesLock(Name FunName, Name LockName, SourceLocation Loc) { @@ -1206,7 +1440,8 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, AC.getCFGBuildOptions().AddEHEdges = false; AC.getCFGBuildOptions().AddInitializers = true; AC.getCFGBuildOptions().AddImplicitDtors = true; - + AC.getCFGBuildOptions().AddTemporaryDtors = true; + // Force that certain expressions appear as CFGElements in the CFG. This // is used to speed up various analyses. // FIXME: This isn't the right factoring. This is here for initial @@ -1350,6 +1585,11 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, DiagnoseSwitchLabelsFallthrough(S, AC, !FallThroughDiagFull); } + if (S.getLangOpts().ObjCARCWeak && + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + D->getLocStart()) != DiagnosticsEngine::Ignored) + diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap()); + // Collect statistics about the CFG if it was built. if (S.CollectStats && AC.isCFGBuilt()) { ++NumFunctionsAnalyzed; diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 46dfa05..7cfe3ae 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -13,7 +13,9 @@ add_clang_library(clangSema DelayedDiagnostic.cpp IdentifierResolver.cpp JumpDiagnostics.cpp + MultiplexExternalSemaSource.cpp Scope.cpp + ScopeInfo.cpp Sema.cpp SemaAccess.cpp SemaAttr.cpp @@ -39,6 +41,7 @@ add_clang_library(clangSema SemaOverload.cpp SemaPseudoObject.cpp SemaStmt.cpp + SemaStmtAsm.cpp SemaStmtAttr.cpp SemaTemplate.cpp SemaTemplateDeduction.cpp diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index a835725..0a23601 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -193,11 +193,10 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks, CXAvailabilityKind Availability, const char **Annotations, unsigned NumAnnotations, - CXCursorKind ParentKind, StringRef ParentName, const char *BriefComment) : NumChunks(NumChunks), NumAnnotations(NumAnnotations), - Priority(Priority), Availability(Availability), ParentKind(ParentKind), + Priority(Priority), Availability(Availability), ParentName(ParentName), BriefComment(BriefComment) { assert(NumChunks <= 0xffff); @@ -339,7 +338,7 @@ CodeCompletionString *CodeCompletionBuilder::TakeString() { = new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(), Priority, Availability, Annotations.data(), Annotations.size(), - ParentKind, ParentName, BriefComment); + ParentName, BriefComment); Chunks.clear(); return Result; } @@ -380,7 +379,6 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK, void CodeCompletionBuilder::addParentContext(DeclContext *DC) { if (DC->isTranslationUnit()) { - ParentKind = CXCursor_TranslationUnit; return; } @@ -391,7 +389,6 @@ void CodeCompletionBuilder::addParentContext(DeclContext *DC) { if (!ND) return; - ParentKind = getCursorKindForDecl(ND); ParentName = getCodeCompletionTUInfo().getParentName(DC); } diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index d12ca78..b3066eb 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -144,11 +144,13 @@ CXXScopeSpec::getWithLocInContext(ASTContext &Context) const { /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. -DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, +DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isAmbiguous, - SourceLocation EllipsisLoc, + SourceLocation LParenLoc, ParamInfo *ArgInfo, unsigned NumArgs, + SourceLocation EllipsisLoc, + SourceLocation RParenLoc, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, @@ -173,9 +175,11 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic, I.EndLoc = LocalRangeEnd; I.Fun.AttrList = 0; I.Fun.hasPrototype = hasProto; - I.Fun.isVariadic = isVariadic; + I.Fun.isVariadic = EllipsisLoc.isValid(); I.Fun.isAmbiguous = isAmbiguous; + I.Fun.LParenLoc = LParenLoc.getRawEncoding(); I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding(); + I.Fun.RParenLoc = RParenLoc.getRawEncoding(); I.Fun.DeleteArgInfo = false; I.Fun.TypeQuals = TypeQuals; I.Fun.NumArgs = NumArgs; @@ -270,6 +274,7 @@ bool Declarator::isDeclarationOfFunction() const { case TST_int: case TST_int128: case TST_struct: + case TST_interface: case TST_union: case TST_unknown_anytype: case TST_unspecified: @@ -325,10 +330,14 @@ unsigned DeclSpec::getParsedSpecifiers() const { template <class T> static bool BadSpecifier(T TNew, T TPrev, const char *&PrevSpec, - unsigned &DiagID) { + unsigned &DiagID, + bool IsExtension = true) { PrevSpec = DeclSpec::getSpecifierName(TPrev); - DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec - : diag::err_invalid_decl_spec_combination); + if (TNew != TPrev) + DiagID = diag::err_invalid_decl_spec_combination; + else + DiagID = IsExtension ? diag::ext_duplicate_declspec : + diag::warn_duplicate_declspec; return true; } @@ -396,6 +405,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_class: return "class"; case DeclSpec::TST_union: return "union"; case DeclSpec::TST_struct: return "struct"; + case DeclSpec::TST_interface: return "__interface"; case DeclSpec::TST_typename: return "type-name"; case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; @@ -670,12 +680,16 @@ bool DeclSpec::SetTypeSpecError() { } bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID, const LangOptions &Lang, - bool IsTypeSpec) { - // Duplicates are permitted in C99, and are permitted in C++11 unless the - // cv-qualifier appears as a type-specifier. - if ((TypeQualifiers & T) && !Lang.C99 && (!Lang.CPlusPlus0x || IsTypeSpec)) - return BadSpecifier(T, T, PrevSpec, DiagID); + unsigned &DiagID, const LangOptions &Lang) { + // Duplicates are permitted in C99, but are not permitted in C++. However, + // since this is likely not what the user intended, we will always warn. We + // do not need to set the qualifier's location since we already have it. + if (TypeQualifiers & T) { + bool IsExtension = true; + if (Lang.C99) + IsExtension = false; + return BadSpecifier(T, T, PrevSpec, DiagID, IsExtension); + } TypeQualifiers |= T; switch (T) { diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp index 876f9d7..3100432 100644 --- a/lib/Sema/DelayedDiagnostic.cpp +++ b/lib/Sema/DelayedDiagnostic.cpp @@ -22,6 +22,7 @@ using namespace sema; DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, const NamedDecl *D, const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, StringRef Msg) { DelayedDiagnostic DD; DD.Kind = Deprecation; @@ -29,6 +30,7 @@ DelayedDiagnostic DelayedDiagnostic::makeDeprecation(SourceLocation Loc, DD.Loc = Loc; DD.DeprecationData.Decl = D; DD.DeprecationData.UnknownObjCClass = UnknownObjCClass; + DD.DeprecationData.ObjCProperty = ObjCProperty; char *MessageData = 0; if (Msg.size()) { MessageData = new char [Msg.size()]; diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 4d62cab..0093915 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -135,8 +135,16 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx, // of the controlled statement. // assert(S->getParent() && "No TUScope?"); - if (S->getParent()->getFlags() & Scope::ControlScope) + if (S->getFlags() & Scope::FnTryScope) return S->getParent()->isDeclScope(D); + if (S->getParent()->getFlags() & Scope::ControlScope) { + if (S->getParent()->getFlags() & Scope::FnCatchScope) { + S = S->getParent(); + if (S->isDeclScope(D)) + return true; + } + return S->getParent()->isDeclScope(D); + } } return false; } diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index ab786c6..e2ec1cc 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -123,7 +123,7 @@ typedef std::pair<unsigned,unsigned> ScopePair; /// diagnostic that should be emitted if control goes over it. If not, return 0. static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - unsigned InDiag = 0, OutDiag = 0; + unsigned InDiag = 0; if (VD->getType()->isVariablyModifiedType()) InDiag = diag::note_protected_by_vla; @@ -164,43 +164,53 @@ static ScopePair GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { // where it is in scope is ill-formed unless the variable has // POD type and is declared without an initializer. - if (const Expr *init = VD->getInit()) { - // We actually give variables of record type (or array thereof) - // an initializer even if that initializer only calls a trivial - // ctor. Detect that case. - // FIXME: With generalized initializer lists, this may - // classify "X x{};" as having no initializer. - unsigned inDiagToUse = diag::note_protected_by_variable_init; - - const CXXRecordDecl *record = 0; - - if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(init)) { - const CXXConstructorDecl *ctor = cce->getConstructor(); - record = ctor->getParent(); - - if (ctor->isTrivial() && ctor->isDefaultConstructor()) { - if (!record->hasTrivialDestructor()) - inDiagToUse = diag::note_protected_by_variable_nontriv_destructor; - else if (!record->isPOD()) - inDiagToUse = diag::note_protected_by_variable_non_pod; - else - inDiagToUse = 0; - } - } else if (VD->getType()->isArrayType()) { - record = VD->getType()->getBaseElementTypeUnsafe() - ->getAsCXXRecordDecl(); + const Expr *Init = VD->getInit(); + if (!Init) + return ScopePair(InDiag, 0); + + const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Init); + if (EWC) + Init = EWC->getSubExpr(); + + const MaterializeTemporaryExpr *M = NULL; + Init = Init->findMaterializedTemporary(M); + + SmallVector<SubobjectAdjustment, 2> Adjustments; + Init = Init->skipRValueSubobjectAdjustments(Adjustments); + + QualType QT = Init->getType(); + if (QT.isNull()) + return ScopePair(diag::note_protected_by_variable_init, 0); + + const Type *T = QT.getTypePtr(); + if (T->isArrayType()) + T = T->getBaseElementTypeUnsafe(); + + const CXXRecordDecl *Record = T->getAsCXXRecordDecl(); + if (!Record) + return ScopePair(diag::note_protected_by_variable_init, 0); + + // If we need to call a non trivial destructor for this variable, + // record an out diagnostic. + unsigned OutDiag = 0; + if (!Init->isGLValue() && !Record->hasTrivialDestructor()) + OutDiag = diag::note_exits_dtor; + + if (const CXXConstructExpr *cce = dyn_cast<CXXConstructExpr>(Init)) { + const CXXConstructorDecl *ctor = cce->getConstructor(); + if (ctor->isTrivial() && ctor->isDefaultConstructor()) { + if (OutDiag) + InDiag = diag::note_protected_by_variable_nontriv_destructor; + else if (!Record->isPOD()) + InDiag = diag::note_protected_by_variable_non_pod; + return ScopePair(InDiag, OutDiag); } - - if (inDiagToUse) - InDiag = inDiagToUse; - - // Also object to indirect jumps which leave scopes with dtors. - if (record && !record->hasTrivialDestructor()) - OutDiag = diag::note_exits_dtor; } + + return ScopePair(diag::note_protected_by_variable_init, OutDiag); } - - return ScopePair(InDiag, OutDiag); + + return ScopePair(InDiag, 0); } if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { @@ -322,6 +332,29 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) Jumps.push_back(S); break; + case Stmt::CXXTryStmtClass: { + CXXTryStmt *TS = cast<CXXTryStmt>(S); + unsigned newParentScope; + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_try, + diag::note_exits_cxx_try, + TS->getSourceRange().getBegin())); + if (Stmt *TryBlock = TS->getTryBlock()) + BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1)); + + // Jump from the catch into the try is not allowed either. + for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { + CXXCatchStmt *CS = TS->getHandler(I); + Scopes.push_back(GotoScope(ParentScope, + diag::note_protected_by_cxx_catch, + diag::note_exits_cxx_catch, + CS->getSourceRange().getBegin())); + BuildScopeInformation(CS->getHandlerBlock(), + (newParentScope = Scopes.size()-1)); + } + return; + } + default: break; } @@ -418,30 +451,6 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) continue; } - // Disallow jumps into any part of a C++ try statement. This is pretty - // much the same as for Obj-C. - if (CXXTryStmt *TS = dyn_cast<CXXTryStmt>(SubStmt)) { - Scopes.push_back(GotoScope(ParentScope, - diag::note_protected_by_cxx_try, - diag::note_exits_cxx_try, - TS->getSourceRange().getBegin())); - if (Stmt *TryBlock = TS->getTryBlock()) - BuildScopeInformation(TryBlock, (newParentScope = Scopes.size()-1)); - - // Jump from the catch into the try is not allowed either. - for (unsigned I = 0, E = TS->getNumHandlers(); I != E; ++I) { - CXXCatchStmt *CS = TS->getHandler(I); - Scopes.push_back(GotoScope(ParentScope, - diag::note_protected_by_cxx_catch, - diag::note_exits_cxx_catch, - CS->getSourceRange().getBegin())); - BuildScopeInformation(CS->getHandlerBlock(), - (newParentScope = Scopes.size()-1)); - } - - continue; - } - // Disallow jumps into the protected statement of an @autoreleasepool. if (ObjCAutoreleasePoolStmt *AS = dyn_cast<ObjCAutoreleasePoolStmt>(SubStmt)){ // Recursively walk the AST for the @autoreleasepool part, protected by a new @@ -453,14 +462,19 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned &origParentScope) BuildScopeInformation(AS->getSubStmt(), (newParentScope = Scopes.size()-1)); continue; } - - if (const BlockExpr *BE = dyn_cast<BlockExpr>(SubStmt)) { - const BlockDecl *BDecl = BE->getBlockDecl(); + + // Disallow jumps past full-expressions that use blocks with + // non-trivial cleanups of their captures. This is theoretically + // implementable but a lot of work which we haven't felt up to doing. + if (ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(SubStmt)) { + for (unsigned i = 0, e = EWC->getNumObjects(); i != e; ++i) { + const BlockDecl *BDecl = EWC->getObject(i); for (BlockDecl::capture_const_iterator ci = BDecl->capture_begin(), ce = BDecl->capture_end(); ci != ce; ++ci) { VarDecl *variable = ci->getVariable(); BuildScopeInformation(variable, BDecl, ParentScope); } + } } // Recursively walk the AST. diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp new file mode 100644 index 0000000..f930fb3 --- /dev/null +++ b/lib/Sema/MultiplexExternalSemaSource.cpp @@ -0,0 +1,271 @@ +//===--- MultiplexExternalSemaSource.cpp ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the event dispatching to the subscribed clients. +// +//===----------------------------------------------------------------------===// +#include "clang/Sema/MultiplexExternalSemaSource.h" + +#include "clang/AST/DeclContextInternals.h" +#include "clang/Sema/Lookup.h" + +using namespace clang; + +///\brief Constructs a new multiplexing external sema source and appends the +/// given element to it. +/// +///\param[in] source - An ExternalSemaSource. +/// +MultiplexExternalSemaSource::MultiplexExternalSemaSource(ExternalSemaSource &s1, + ExternalSemaSource &s2){ + Sources.push_back(&s1); + Sources.push_back(&s2); +} + +// pin the vtable here. +MultiplexExternalSemaSource::~MultiplexExternalSemaSource() {} + +///\brief Appends new source to the source list. +/// +///\param[in] source - An ExternalSemaSource. +/// +void MultiplexExternalSemaSource::addSource(ExternalSemaSource &source) { + Sources.push_back(&source); +} + +//===----------------------------------------------------------------------===// +// ExternalASTSource. +//===----------------------------------------------------------------------===// + +Decl *MultiplexExternalSemaSource::GetExternalDecl(uint32_t ID) { + for(size_t i = 0; i < Sources.size(); ++i) + if (Decl *Result = Sources[i]->GetExternalDecl(ID)) + return Result; + return 0; +} + +Selector MultiplexExternalSemaSource::GetExternalSelector(uint32_t ID) { + Selector Sel; + for(size_t i = 0; i < Sources.size(); ++i) { + Sel = Sources[i]->GetExternalSelector(ID); + if (!Sel.isNull()) + return Sel; + } + return Sel; +} + +uint32_t MultiplexExternalSemaSource::GetNumExternalSelectors() { + uint32_t total = 0; + for(size_t i = 0; i < Sources.size(); ++i) + total += Sources[i]->GetNumExternalSelectors(); + return total; +} + +Stmt *MultiplexExternalSemaSource::GetExternalDeclStmt(uint64_t Offset) { + for(size_t i = 0; i < Sources.size(); ++i) + if (Stmt *Result = Sources[i]->GetExternalDeclStmt(Offset)) + return Result; + return 0; +} + +CXXBaseSpecifier *MultiplexExternalSemaSource::GetExternalCXXBaseSpecifiers( + uint64_t Offset){ + for(size_t i = 0; i < Sources.size(); ++i) + if (CXXBaseSpecifier *R = Sources[i]->GetExternalCXXBaseSpecifiers(Offset)) + return R; + return 0; +} + +DeclContextLookupResult 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(); +} + +void MultiplexExternalSemaSource::completeVisibleDeclsMap(const DeclContext *DC){ + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->completeVisibleDeclsMap(DC); +} + +ExternalLoadResult MultiplexExternalSemaSource:: +FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + SmallVectorImpl<Decl*> &Result) { + for(size_t i = 0; i < Sources.size(); ++i) + // FIXME: The semantics of the return result is unclear to me... + Sources[i]->FindExternalLexicalDecls(DC, isKindWeWant, Result); + + return ELR_Success; +} + +void MultiplexExternalSemaSource::FindFileRegionDecls(FileID File, + unsigned Offset, + unsigned Length, + SmallVectorImpl<Decl *> &Decls){ + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->FindFileRegionDecls(File, Offset, Length, Decls); +} + +void MultiplexExternalSemaSource::CompleteType(TagDecl *Tag) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->CompleteType(Tag); +} + +void MultiplexExternalSemaSource::CompleteType(ObjCInterfaceDecl *Class) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->CompleteType(Class); +} + +void MultiplexExternalSemaSource::ReadComments() { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadComments(); +} + +void MultiplexExternalSemaSource::StartedDeserializing() { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->StartedDeserializing(); +} + +void MultiplexExternalSemaSource::FinishedDeserializing() { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->FinishedDeserializing(); +} + +void MultiplexExternalSemaSource::StartTranslationUnit(ASTConsumer *Consumer) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->StartTranslationUnit(Consumer); +} + +void MultiplexExternalSemaSource::PrintStats() { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->PrintStats(); +} + +bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, + llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets){ + for(size_t i = 0; i < Sources.size(); ++i) + if (Sources[i]->layoutRecordType(Record, Size, Alignment, FieldOffsets, + BaseOffsets, VirtualBaseOffsets)) + return true; + return false; +} + +void MultiplexExternalSemaSource:: +getMemoryBufferSizes(MemoryBufferSizes &sizes) const { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->getMemoryBufferSizes(sizes); + +} + +//===----------------------------------------------------------------------===// +// ExternalSemaSource. +//===----------------------------------------------------------------------===// + + +void MultiplexExternalSemaSource::InitializeSema(Sema &S) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->InitializeSema(S); +} + +void MultiplexExternalSemaSource::ForgetSema() { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ForgetSema(); +} + +void MultiplexExternalSemaSource::ReadMethodPool(Selector Sel) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadMethodPool(Sel); +} + +void MultiplexExternalSemaSource::ReadKnownNamespaces( + SmallVectorImpl<NamespaceDecl*> &Namespaces){ + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadKnownNamespaces(Namespaces); +} + +bool MultiplexExternalSemaSource::LookupUnqualified(LookupResult &R, Scope *S){ + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->LookupUnqualified(R, S); + + return !R.empty(); +} + +void MultiplexExternalSemaSource::ReadTentativeDefinitions( + SmallVectorImpl<VarDecl*> &TentativeDefs) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadTentativeDefinitions(TentativeDefs); +} + +void MultiplexExternalSemaSource::ReadUnusedFileScopedDecls( + SmallVectorImpl<const DeclaratorDecl*> &Decls) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadUnusedFileScopedDecls(Decls); +} + +void MultiplexExternalSemaSource::ReadDelegatingConstructors( + SmallVectorImpl<CXXConstructorDecl*> &Decls) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadDelegatingConstructors(Decls); +} + +void MultiplexExternalSemaSource::ReadExtVectorDecls( + SmallVectorImpl<TypedefNameDecl*> &Decls) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadExtVectorDecls(Decls); +} + +void MultiplexExternalSemaSource::ReadDynamicClasses( + SmallVectorImpl<CXXRecordDecl*> &Decls) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadDynamicClasses(Decls); +} + +void MultiplexExternalSemaSource::ReadLocallyScopedExternalDecls( + SmallVectorImpl<NamedDecl*> &Decls) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadLocallyScopedExternalDecls(Decls); +} + +void MultiplexExternalSemaSource::ReadReferencedSelectors( + SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadReferencedSelectors(Sels); +} + +void MultiplexExternalSemaSource::ReadWeakUndeclaredIdentifiers( + SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadWeakUndeclaredIdentifiers(WI); +} + +void MultiplexExternalSemaSource::ReadUsedVTables( + SmallVectorImpl<ExternalVTableUse> &VTables) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadUsedVTables(VTables); +} + +void MultiplexExternalSemaSource::ReadPendingInstantiations( + SmallVectorImpl<std::pair<ValueDecl*, + SourceLocation> > &Pending) { + for(size_t i = 0; i < Sources.size(); ++i) + Sources[i]->ReadPendingInstantiations(Pending); +} diff --git a/lib/Sema/ScopeInfo.cpp b/lib/Sema/ScopeInfo.cpp new file mode 100644 index 0000000..4d29a34 --- /dev/null +++ b/lib/Sema/ScopeInfo.cpp @@ -0,0 +1,189 @@ +//===--- ScopeInfo.cpp - Information about a semantic context -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements FunctionScopeInfo and its subclasses, which contain +// information about a single function, block, lambda, or method body. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/ScopeInfo.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" + +using namespace clang; +using namespace sema; + +void FunctionScopeInfo::Clear() { + HasBranchProtectedScope = false; + HasBranchIntoScope = false; + HasIndirectGoto = false; + + SwitchStack.clear(); + Returns.clear(); + ErrorTrap.reset(); + PossiblyUnreachableDiags.clear(); + WeakObjectUses.clear(); +} + +static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) { + if (PropE->isExplicitProperty()) + return PropE->getExplicitProperty(); + + return PropE->getImplicitPropertyGetter(); +} + +FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy +FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) { + E = E->IgnoreParenCasts(); + + const NamedDecl *D = 0; + bool IsExact = false; + + switch (E->getStmtClass()) { + case Stmt::DeclRefExprClass: + D = cast<DeclRefExpr>(E)->getDecl(); + IsExact = isa<VarDecl>(D); + break; + case Stmt::MemberExprClass: { + const MemberExpr *ME = cast<MemberExpr>(E); + D = ME->getMemberDecl(); + IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()); + break; + } + case Stmt::ObjCIvarRefExprClass: { + const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E); + D = IE->getDecl(); + IsExact = IE->getBase()->isObjCSelfExpr(); + break; + } + case Stmt::PseudoObjectExprClass: { + const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E); + const ObjCPropertyRefExpr *BaseProp = + dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); + if (BaseProp) { + D = getBestPropertyDecl(BaseProp); + + const Expr *DoubleBase = BaseProp->getBase(); + if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase)) + DoubleBase = OVE->getSourceExpr(); + + IsExact = DoubleBase->isObjCSelfExpr(); + } + break; + } + default: + break; + } + + return BaseInfoTy(D, IsExact); +} + + +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( + const ObjCPropertyRefExpr *PropE) + : Base(0, true), Property(getBestPropertyDecl(PropE)) { + + if (PropE->isObjectReceiver()) { + const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase()); + const Expr *E = OVE->getSourceExpr(); + Base = getBaseInfo(E); + } else if (PropE->isClassReceiver()) { + Base.setPointer(PropE->getClassReceiver()); + } else { + assert(PropE->isSuperReceiver()); + } +} + +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE, + const ObjCPropertyDecl *Prop) + : Base(0, true), Property(Prop) { + if (BaseE) + Base = getBaseInfo(BaseE); + // else, this is a message accessing a property on super. +} + +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( + const DeclRefExpr *DRE) + : Base(0, true), Property(DRE->getDecl()) { + assert(isa<VarDecl>(Property)); +} + +FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy( + const ObjCIvarRefExpr *IvarE) + : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) { +} + +void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg, + const ObjCPropertyDecl *Prop) { + assert(Msg && Prop); + WeakUseVector &Uses = + WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)]; + Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0)); +} + +void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { + E = E->IgnoreParenCasts(); + + if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) { + markSafeWeakUse(POE->getSyntacticForm()); + return; + } + + if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) { + markSafeWeakUse(Cond->getTrueExpr()); + markSafeWeakUse(Cond->getFalseExpr()); + return; + } + + if (const BinaryConditionalOperator *Cond = + dyn_cast<BinaryConditionalOperator>(E)) { + markSafeWeakUse(Cond->getCommon()); + markSafeWeakUse(Cond->getFalseExpr()); + return; + } + + // Has this weak object been seen before? + FunctionScopeInfo::WeakObjectUseMap::iterator Uses; + if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) + Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr)); + else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E)) + Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE)); + else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) + Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE)); + else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) { + Uses = WeakObjectUses.end(); + if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) { + if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) { + Uses = + WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(), + Prop)); + } + } + } + else + return; + + if (Uses == WeakObjectUses.end()) + return; + + // Has there been a read from the object using this Expr? + FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse = + std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true)); + if (ThisUse == Uses->second.rend()) + return; + + ThisUse->markSafe(); +} + +FunctionScopeInfo::~FunctionScopeInfo() { } +BlockScopeInfo::~BlockScopeInfo() { } +LambdaScopeInfo::~LambdaScopeInfo() { } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 7f79f0c..13a33b7 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -22,6 +22,7 @@ #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" @@ -43,22 +44,6 @@ using namespace clang; using namespace sema; -FunctionScopeInfo::~FunctionScopeInfo() { } - -void FunctionScopeInfo::Clear() { - HasBranchProtectedScope = false; - HasBranchIntoScope = false; - HasIndirectGoto = false; - - SwitchStack.clear(); - Returns.clear(); - ErrorTrap.reset(); - PossiblyUnreachableDiags.clear(); -} - -BlockScopeInfo::~BlockScopeInfo() { } -LambdaScopeInfo::~LambdaScopeInfo() { } - PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context, const Preprocessor &PP) { PrintingPolicy Policy = Context.getPrintingPolicy(); @@ -84,12 +69,14 @@ void Sema::ActOnTranslationUnitScope(Scope *S) { Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, TranslationUnitKind TUKind, CodeCompleteConsumer *CodeCompleter) - : TheTargetAttributesSema(0), FPFeatures(pp.getLangOpts()), + : TheTargetAttributesSema(0), ExternalSource(0), + isMultiplexExternalSource(false), FPFeatures(pp.getLangOpts()), LangOpts(pp.getLangOpts()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), - CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter), + CollectStats(false), CodeCompleter(CodeCompleter), CurContext(0), OriginalLexicalContext(0), PackContext(0), MSStructPragmaOn(false), VisContext(0), + IsBuildingRecoveryCallExpr(false), ExprNeedsCleanups(false), LateTemplateParser(0), OpaqueParser(0), IdResolver(pp), StdInitializerList(0), CXXTypeInfoDecl(0), MSVCGuidDecl(0), NSNumberDecl(0), @@ -203,6 +190,10 @@ Sema::~Sema() { if (ExternalSemaSource *ExternalSema = dyn_cast_or_null<ExternalSemaSource>(Context.getExternalSource())) ExternalSema->ForgetSema(); + + // If Sema's ExternalSource is the multiplexer - we own it. + if (isMultiplexExternalSource) + delete ExternalSource; } /// makeUnavailableInSystemHeader - There is an error in the current @@ -234,6 +225,27 @@ ASTMutationListener *Sema::getASTMutationListener() const { return getASTConsumer().GetASTMutationListener(); } +///\brief Registers an external source. If an external source already exists, +/// creates a multiplex external source and appends to it. +/// +///\param[in] E - A non-null external sema source. +/// +void Sema::addExternalSource(ExternalSemaSource *E) { + assert(E && "Cannot use with NULL ptr"); + + if (!ExternalSource) { + ExternalSource = E; + return; + } + + if (isMultiplexExternalSource) + static_cast<MultiplexExternalSemaSource*>(ExternalSource)->addSource(*E); + else { + ExternalSource = new MultiplexExternalSemaSource(*ExternalSource, *E); + isMultiplexExternalSource = true; + } +} + /// \brief Print out statistics about the semantic analysis. void Sema::PrintStats() const { llvm::errs() << "\n*** Semantic Analysis Stats:\n"; @@ -507,6 +519,11 @@ void Sema::ActOnEndOfTranslationUnit() { assert(DelayedDiagnostics.getCurrentPool() == NULL && "reached end of translation unit with a pool attached?"); + // If code completion is enabled, don't perform any end-of-translation-unit + // work. + if (PP.isCodeCompletionEnabled()) + return; + // Only complete translation units define vtables and perform implicit // instantiations. if (TUKind == TU_Complete) { @@ -648,6 +665,8 @@ void Sema::ActOnEndOfTranslationUnit() { diag::err_tentative_def_incomplete_type)) VD->setInvalidDecl(); + CheckCompleteVariableDeclaration(VD); + // Notify the consumer that we've completed a tentative definition. if (!VD->isInvalidDecl()) Consumer.CompleteTentativeDefinition(VD); @@ -1021,6 +1040,9 @@ LambdaScopeInfo *Sema::getCurLambda() { } void Sema::ActOnComment(SourceRange Comment) { + if (!LangOpts.RetainCommentsFromSystemHeaders && + SourceMgr.isInSystemHeader(Comment.getBegin())) + return; RawComment RC(SourceMgr, Comment); if (RC.isAlmostTrailingComment()) { SourceRange MagicMarkerRange(Comment.getBegin(), @@ -1165,8 +1187,7 @@ static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { // FIXME: Magic number for max shown overloads stolen from // OverloadCandidateSet::NoteCandidates. - if (ShownOverloads >= 4 && - S.Diags.getShowOverloads() == DiagnosticsEngine::Ovl_Best) { + if (ShownOverloads >= 4 && S.Diags.getShowOverloads() == Ovl_Best) { ++SuppressedOverloads; continue; } @@ -1237,8 +1258,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, // FIXME: Try this before emitting the fixit, and suppress diagnostics // while doing so. E = ActOnCallExpr(0, E.take(), ParenInsertionLoc, - MultiExprArg(*this, 0, 0), - ParenInsertionLoc.getLocWithOffset(1)); + MultiExprArg(), ParenInsertionLoc.getLocWithOffset(1)); return true; } diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 3481171..58b1a51 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -97,14 +97,19 @@ struct EffectiveContext { // functions (which can gain privileges through friendship), but we // take that as an oversight. while (true) { + // We want to add canonical declarations to the EC lists for + // simplicity of checking, but we need to walk up through the + // actual current DC chain. Otherwise, something like a local + // extern or friend which happens to be the canonical + // declaration will really mess us up. + if (isa<CXXRecordDecl>(DC)) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); - Records.push_back(Record); + CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); + Records.push_back(Record->getCanonicalDecl()); DC = Record->getDeclContext(); } else if (isa<FunctionDecl>(DC)) { - FunctionDecl *Function = cast<FunctionDecl>(DC)->getCanonicalDecl(); - Functions.push_back(Function); - + FunctionDecl *Function = cast<FunctionDecl>(DC); + Functions.push_back(Function->getCanonicalDecl()); if (Function->getFriendObjectKind()) DC = Function->getLexicalDeclContext(); else @@ -1791,7 +1796,7 @@ void Sema::CheckLookupAccess(const LookupResult &R) { /// specifiers into account, but no member access expressions and such. /// /// \param Decl the declaration to check if it can be accessed -/// \param Class the class/context from which to start the search +/// \param Ctx the class/context from which to start the search /// \return true if the Decl is accessible from the Class, false otherwise. bool Sema::IsSimplyAccessible(NamedDecl *Decl, DeclContext *Ctx) { if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) { diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index e935fc7..f1154c1 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -136,23 +136,12 @@ void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { } void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, - SourceLocation PragmaLoc, - SourceLocation KindLoc) { + SourceLocation PragmaLoc) { if (PackContext == 0) PackContext = new PragmaPackStack(); PragmaPackStack *Context = static_cast<PragmaPackStack*>(PackContext); - // Reset just pops the top of the stack, or resets the current alignment to - // default. - if (Kind == Sema::POAK_Reset) { - if (!Context->pop(0, /*IsReset=*/true)) { - Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) - << "stack empty"; - } - return; - } - switch (Kind) { // For all targets we support native and natural are the same. // @@ -181,9 +170,13 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, Context->setAlignment(PackStackEntry::kMac68kAlignmentSentinel); break; - default: - Diag(PragmaLoc, diag::warn_pragma_options_align_unsupported_option) - << KindLoc; + case POAK_Reset: + // Reset just pops the top of the stack, or resets the current alignment to + // default. + if (!Context->pop(0, /*IsReset=*/true)) { + Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) + << "stack empty"; + } break; } } diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 0de9dd5..15bfd1c 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -520,7 +520,8 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_suggest) << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); else Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest) << Name << CorrectedQuotedStr diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index d8d51e7..bf25c61 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -227,7 +227,7 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, CheckExtraCXXDefaultArguments(D); } - return BuildCXXNamedCast(OpLoc, Kind, TInfo, move(E), + return BuildCXXNamedCast(OpLoc, Kind, TInfo, E, SourceRange(LAngleBracketLoc, RAngleBracketLoc), SourceRange(LParenLoc, RParenLoc)); } @@ -1331,8 +1331,7 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, if (InitSeq.Failed() && (CStyle || !DestType->isReferenceType())) return TC_NotApplicable; - ExprResult Result - = InitSeq.Perform(Self, Entity, InitKind, MultiExprArg(Self, &SrcExprRaw, 1)); + ExprResult Result = InitSeq.Perform(Self, Entity, InitKind, SrcExprRaw); if (Result.isInvalid()) { msg = 0; return TC_Failed; @@ -1343,7 +1342,7 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, else Kind = CK_NoOp; - SrcExpr = move(Result); + SrcExpr = Result; return TC_Success; } @@ -1492,6 +1491,22 @@ static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr, } } +static void checkIntToPointerCast(bool CStyle, SourceLocation Loc, + const Expr *SrcExpr, QualType DestType, + Sema &Self) { + QualType SrcType = SrcExpr->getType(); + + // Not warning on reinterpret_cast, boolean, constant expressions, etc + // are not explicit design choices, but consistent with GCC's behavior. + // Feel free to modify them if you've reason/evidence for an alternative. + if (CStyle && SrcType->isIntegralType(Self.Context) + && !SrcType->isBooleanType() + && !SrcType->isEnumeralType() + && !SrcExpr->isIntegerConstantExpr(Self.Context) + && Self.Context.getTypeSize(DestType) > Self.Context.getTypeSize(SrcType)) + Self.Diag(Loc, diag::warn_int_to_pointer_cast) << SrcType << DestType; +} + static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, @@ -1513,7 +1528,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, SingleFunctionExpr, Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr ) && SingleFunctionExpr.isUsable()) { - SrcExpr = move(SingleFunctionExpr); + SrcExpr = SingleFunctionExpr; SrcType = SrcExpr.get()->getType(); } else { return TC_NotApplicable; @@ -1690,6 +1705,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, if (SrcType->isIntegralOrEnumerationType()) { assert(destIsPtr && "One type must be a pointer"); + checkIntToPointerCast(CStyle, OpRange.getBegin(), SrcExpr.get(), DestType, + Self); // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly // converted to a pointer. // C++ 5.2.10p9: [Note: ...a null pointer constant of integral type is not @@ -1903,6 +1920,43 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, SrcExpr = ExprError(); } +/// DiagnoseBadFunctionCast - Warn whenever a function call is cast to a +/// non-matching type. Such as enum function call to int, int call to +/// pointer; etc. Cast to 'void' is an exception. +static void DiagnoseBadFunctionCast(Sema &Self, const ExprResult &SrcExpr, + QualType DestType) { + if (Self.Diags.getDiagnosticLevel(diag::warn_bad_function_cast, + SrcExpr.get()->getExprLoc()) + == DiagnosticsEngine::Ignored) + return; + + if (!isa<CallExpr>(SrcExpr.get())) + return; + + QualType SrcType = SrcExpr.get()->getType(); + if (DestType.getUnqualifiedType()->isVoidType()) + return; + if ((SrcType->isAnyPointerType() || SrcType->isBlockPointerType()) + && (DestType->isAnyPointerType() || DestType->isBlockPointerType())) + return; + if (SrcType->isIntegerType() && DestType->isIntegerType() && + (SrcType->isBooleanType() == DestType->isBooleanType()) && + (SrcType->isEnumeralType() == DestType->isEnumeralType())) + return; + if (SrcType->isRealFloatingType() && DestType->isRealFloatingType()) + return; + if (SrcType->isEnumeralType() && DestType->isEnumeralType()) + return; + if (SrcType->isComplexType() && DestType->isComplexType()) + return; + if (SrcType->isComplexIntegerType() && DestType->isComplexIntegerType()) + return; + + Self.Diag(SrcExpr.get()->getExprLoc(), + diag::warn_bad_function_cast) + << SrcType << DestType << SrcExpr.get()->getSourceRange(); +} + /// Check the semantics of a C-style cast operation, in C. void CastOperation::CheckCStyleCast() { assert(!Self.getLangOpts().CPlusPlus); @@ -2035,6 +2089,8 @@ void CastOperation::CheckCStyleCast() { SrcExpr = ExprError(); return; } + checkIntToPointerCast(/* CStyle */ true, OpRange.getBegin(), SrcExpr.get(), + DestType, Self); } else if (!SrcType->isArithmeticType()) { if (!DestType->isIntegralType(Self.Context) && DestType->isArithmeticType()) { @@ -2076,7 +2132,7 @@ void CastOperation::CheckCStyleCast() { } } DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType); - + DiagnoseBadFunctionCast(Self, SrcExpr, DestType); Kind = Self.PrepareScalarCast(SrcExpr, DestType); if (SrcExpr.isInvalid()) return; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 2559f00..692a210 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -266,11 +266,11 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Builtin::BI__sync_swap_4: case Builtin::BI__sync_swap_8: case Builtin::BI__sync_swap_16: - return SemaBuiltinAtomicOverloaded(move(TheCallResult)); + return SemaBuiltinAtomicOverloaded(TheCallResult); #define BUILTIN(ID, TYPE, ATTRS) #define ATOMIC_BUILTIN(ID, TYPE, ATTRS) \ case Builtin::BI##ID: \ - return SemaAtomicOpsOverloaded(move(TheCallResult), AtomicExpr::AO##ID); + return SemaAtomicOpsOverloaded(TheCallResult, AtomicExpr::AO##ID); #include "clang/Basic/Builtins.def" case Builtin::BI__builtin_annotation: if (SemaBuiltinAnnotation(*this, TheCall)) @@ -299,7 +299,7 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { } } - return move(TheCallResult); + return TheCallResult; } // Get the valid immediate range for the specified NEON type code. @@ -437,6 +437,11 @@ bool Sema::CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { default: return false; case Mips::BI__builtin_mips_wrdsp: i = 1; l = 0; u = 63; break; case Mips::BI__builtin_mips_rddsp: i = 0; l = 0; u = 63; break; + case Mips::BI__builtin_mips_append: i = 2; l = 0; u = 31; break; + case Mips::BI__builtin_mips_balign: i = 2; l = 0; u = 3; break; + case Mips::BI__builtin_mips_precr_sra_ph_w: i = 2; l = 0; u = 31; break; + case Mips::BI__builtin_mips_precr_sra_r_ph_w: i = 2; l = 0; u = 31; break; + case Mips::BI__builtin_mips_prepend: i = 2; l = 0; u = 31; break; }; // We can't check the value of a dependent argument. @@ -490,9 +495,8 @@ void Sema::checkCall(NamedDecl *FDecl, Expr **Args, SourceLocation Loc, SourceRange Range, VariadicCallType CallType) { - // FIXME: This mechanism should be abstracted to be less fragile and - // more efficient. For example, just map function ids to custom - // handlers. + if (CurContext->isDependentContext()) + return; // Printf and scanf checking. bool HandledFormatString = false; @@ -506,8 +510,11 @@ void Sema::checkCall(NamedDecl *FDecl, Expr **Args, // Refuse POD arguments that weren't caught by the format string // checks above. if (!HandledFormatString && CallType != VariadicDoesNotApply) - for (unsigned ArgIdx = NumProtoArgs; ArgIdx < NumArgs; ++ArgIdx) - variadicArgumentPODCheck(Args[ArgIdx], CallType); + for (unsigned ArgIdx = NumProtoArgs; ArgIdx < NumArgs; ++ArgIdx) { + // Args[ArgIdx] can be null in malformed code. + if (Expr *Arg = Args[ArgIdx]) + variadicArgumentPODCheck(Arg, CallType); + } for (specific_attr_iterator<NonNullAttr> I = FDecl->specific_attr_begin<NonNullAttr>(), @@ -538,11 +545,23 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl, Expr **Args, /// and safety properties not strictly enforced by the C type system. bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, const FunctionProtoType *Proto) { - bool IsMemberFunction = isa<CXXMemberCallExpr>(TheCall); + bool IsMemberOperatorCall = isa<CXXOperatorCallExpr>(TheCall) && + isa<CXXMethodDecl>(FDecl); + bool IsMemberFunction = isa<CXXMemberCallExpr>(TheCall) || + IsMemberOperatorCall; VariadicCallType CallType = getVariadicCallType(FDecl, Proto, TheCall->getCallee()); unsigned NumProtoArgs = Proto ? Proto->getNumArgs() : 0; - checkCall(FDecl, TheCall->getArgs(), TheCall->getNumArgs(), NumProtoArgs, + Expr** Args = TheCall->getArgs(); + unsigned NumArgs = TheCall->getNumArgs(); + if (IsMemberOperatorCall) { + // If this is a call to a member operator, hide the first argument + // from checkCall. + // FIXME: Our choice of AST representation here is less than ideal. + ++Args; + --NumArgs; + } + checkCall(FDecl, Args, NumArgs, NumProtoArgs, IsMemberFunction, TheCall->getRParenLoc(), TheCall->getCallee()->getSourceRange(), CallType); @@ -737,6 +756,11 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } + if (AtomTy.isConstQualified()) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_non_const_atomic) + << Ptr->getType() << Ptr->getSourceRange(); + return ExprError(); + } ValType = AtomTy->getAs<AtomicType>()->getValueType(); } @@ -885,8 +909,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded(ExprResult TheCallResult, } return Owned(new (Context) AtomicExpr(TheCall->getCallee()->getLocStart(), - SubExprs.data(), SubExprs.size(), - ResultType, Op, + SubExprs, ResultType, Op, TheCall->getRParenLoc())); } @@ -1189,10 +1212,19 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // concrete integer type we should convert to is. unsigned NewBuiltinID = BuiltinIndices[BuiltinIndex][SizeIndex]; const char *NewBuiltinName = Context.BuiltinInfo.GetName(NewBuiltinID); - IdentifierInfo *NewBuiltinII = PP.getIdentifierInfo(NewBuiltinName); - FunctionDecl *NewBuiltinDecl = - cast<FunctionDecl>(LazilyCreateBuiltin(NewBuiltinII, NewBuiltinID, - TUScope, false, DRE->getLocStart())); + FunctionDecl *NewBuiltinDecl; + if (NewBuiltinID == BuiltinID) + NewBuiltinDecl = FDecl; + else { + // Perform builtin lookup to avoid redeclaring it. + DeclarationName DN(&Context.Idents.get(NewBuiltinName)); + LookupResult Res(*this, DN, DRE->getLocStart(), LookupOrdinaryName); + LookupName(Res, TUScope, /*AllowBuiltinCreation=*/true); + assert(Res.getFoundDecl()); + NewBuiltinDecl = dyn_cast<FunctionDecl>(Res.getFoundDecl()); + if (NewBuiltinDecl == 0) + return ExprError(); + } // The first argument --- the pointer --- has a fixed type; we // deduce the types of the rest of the arguments accordingly. Walk @@ -1228,14 +1260,14 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { NewBuiltinDecl, /*enclosing*/ false, DRE->getLocation(), - NewBuiltinDecl->getType(), + Context.BuiltinFnTy, DRE->getValueKind()); // Set the callee in the CallExpr. - // FIXME: This leaks the original parens and implicit casts. - ExprResult PromotedCall = UsualUnaryConversions(NewDRE); - if (PromotedCall.isInvalid()) - return ExprError(); + // FIXME: This loses syntactic information. + QualType CalleePtrTy = Context.getPointerType(NewBuiltinDecl->getType()); + ExprResult PromotedCall = ImpCastExprToType(NewDRE, CalleePtrTy, + CK_BuiltinFnToFnPtr); TheCall->setCallee(PromotedCall.take()); // Change the result type of the call to match the original value type. This @@ -1243,7 +1275,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) { // gracefully. TheCall->setType(ResultType); - return move(TheCallResult); + return TheCallResult; } /// CheckObjCString - Checks that the argument to the builtin @@ -1264,7 +1296,7 @@ bool Sema::CheckObjCString(Expr *Arg) { StringRef String = Literal->getString(); unsigned NumBytes = String.size(); SmallVector<UTF16, 128> ToBuf(NumBytes); - const UTF8 *FromPtr = (UTF8 *)String.data(); + const UTF8 *FromPtr = (const UTF8 *)String.data(); UTF16 *ToPtr = &ToBuf[0]; ConversionResult Result = ConvertUTF8toUTF16(&FromPtr, FromPtr + NumBytes, @@ -1503,8 +1535,7 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->setArg(i, 0); } - return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(), - exprs.size(), resType, + return Owned(new (Context) ShuffleVectorExpr(Context, exprs, resType, TheCall->getCallee()->getLocStart(), TheCall->getRParenLoc())); } @@ -1935,19 +1966,19 @@ public: void HandleIncompleteSpecifier(const char *startSpecifier, unsigned specifierLen); + void HandleInvalidLengthModifier( + const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, unsigned DiagID); + void HandleNonStandardLengthModifier( - const analyze_format_string::LengthModifier &LM, + const analyze_format_string::FormatSpecifier &FS, const char *startSpecifier, unsigned specifierLen); void HandleNonStandardConversionSpecifier( const analyze_format_string::ConversionSpecifier &CS, const char *startSpecifier, unsigned specifierLen); - void HandleNonStandardConversionSpecification( - const analyze_format_string::LengthModifier &LM, - const analyze_format_string::ConversionSpecifier &CS, - const char *startSpecifier, unsigned specifierLen); - virtual void HandlePosition(const char *startPos, unsigned posLen); virtual void HandleInvalidPosition(const char *startSpecifier, @@ -1964,7 +1995,7 @@ public: PartialDiagnostic PDiag, SourceLocation StringLoc, bool IsStringLocation, Range StringRange, - FixItHint Fixit = FixItHint()); + ArrayRef<FixItHint> Fixit = ArrayRef<FixItHint>()); protected: bool HandleInvalidConversionSpecifier(unsigned argIndex, SourceLocation Loc, @@ -1991,7 +2022,7 @@ protected: template <typename Range> void EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation StringLoc, bool IsStringLocation, Range StringRange, - FixItHint Fixit = FixItHint()); + ArrayRef<FixItHint> Fixit = ArrayRef<FixItHint>()); void CheckPositionalAndNonpositionalArgs( const analyze_format_string::FormatSpecifier *FS); @@ -2025,35 +2056,95 @@ void CheckFormatHandler::HandleIncompleteSpecifier(const char *startSpecifier, getSpecifierRange(startSpecifier, specifierLen)); } +void CheckFormatHandler::HandleInvalidLengthModifier( + const analyze_format_string::FormatSpecifier &FS, + const analyze_format_string::ConversionSpecifier &CS, + const char *startSpecifier, unsigned specifierLen, unsigned DiagID) { + using namespace analyze_format_string; + + const LengthModifier &LM = FS.getLengthModifier(); + CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength()); + + // See if we know how to fix this length modifier. + llvm::Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier(); + if (FixedLM) { + EmitFormatDiagnostic(S.PDiag(DiagID) << LM.toString() << CS.toString(), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + + S.Diag(getLocationOfByte(LM.getStart()), diag::note_format_fix_specifier) + << FixedLM->toString() + << FixItHint::CreateReplacement(LMRange, FixedLM->toString()); + + } else { + FixItHint Hint; + if (DiagID == diag::warn_format_nonsensical_length) + Hint = FixItHint::CreateRemoval(LMRange); + + EmitFormatDiagnostic(S.PDiag(DiagID) << LM.toString() << CS.toString(), + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen), + Hint); + } +} + void CheckFormatHandler::HandleNonStandardLengthModifier( - const analyze_format_string::LengthModifier &LM, + const analyze_format_string::FormatSpecifier &FS, const char *startSpecifier, unsigned specifierLen) { - EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << LM.toString() - << 0, - getLocationOfByte(LM.getStart()), - /*IsStringLocation*/true, - getSpecifierRange(startSpecifier, specifierLen)); + using namespace analyze_format_string; + + const LengthModifier &LM = FS.getLengthModifier(); + CharSourceRange LMRange = getSpecifierRange(LM.getStart(), LM.getLength()); + + // See if we know how to fix this length modifier. + llvm::Optional<LengthModifier> FixedLM = FS.getCorrectedLengthModifier(); + if (FixedLM) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) + << LM.toString() << 0, + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + + S.Diag(getLocationOfByte(LM.getStart()), diag::note_format_fix_specifier) + << FixedLM->toString() + << FixItHint::CreateReplacement(LMRange, FixedLM->toString()); + + } else { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) + << LM.toString() << 0, + getLocationOfByte(LM.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + } } void CheckFormatHandler::HandleNonStandardConversionSpecifier( const analyze_format_string::ConversionSpecifier &CS, const char *startSpecifier, unsigned specifierLen) { - EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) << CS.toString() - << 1, - getLocationOfByte(CS.getStart()), - /*IsStringLocation*/true, - getSpecifierRange(startSpecifier, specifierLen)); -} + using namespace analyze_format_string; -void CheckFormatHandler::HandleNonStandardConversionSpecification( - const analyze_format_string::LengthModifier &LM, - const analyze_format_string::ConversionSpecifier &CS, - const char *startSpecifier, unsigned specifierLen) { - EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard_conversion_spec) - << LM.toString() << CS.toString(), - getLocationOfByte(LM.getStart()), - /*IsStringLocation*/true, - getSpecifierRange(startSpecifier, specifierLen)); + // See if we know how to fix this conversion specifier. + llvm::Optional<ConversionSpecifier> FixedCS = CS.getStandardSpecifier(); + if (FixedCS) { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) + << CS.toString() << /*conversion specifier*/1, + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + + CharSourceRange CSRange = getSpecifierRange(CS.getStart(), CS.getLength()); + S.Diag(getLocationOfByte(CS.getStart()), diag::note_format_fix_specifier) + << FixedCS->toString() + << FixItHint::CreateReplacement(CSRange, FixedCS->toString()); + } else { + EmitFormatDiagnostic(S.PDiag(diag::warn_format_non_standard) + << CS.toString() << /*conversion specifier*/1, + getLocationOfByte(CS.getStart()), + /*IsStringLocation*/true, + getSpecifierRange(startSpecifier, specifierLen)); + } } void CheckFormatHandler::HandlePosition(const char *startPos, @@ -2182,7 +2273,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag, SourceLocation Loc, bool IsStringLocation, Range StringRange, - FixItHint FixIt) { + ArrayRef<FixItHint> FixIt) { EmitFormatDiagnostic(S, inFunctionCall, Args[FormatIdx], PDiag, Loc, IsStringLocation, StringRange, FixIt); } @@ -2190,7 +2281,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag, /// \brief If the format string is not within the funcion call, emit a note /// so that the function call and string are in diagnostic messages. /// -/// \param inFunctionCall if true, the format string is within the function +/// \param InFunctionCall if true, the format string is within the function /// call and only one diagnostic message will be produced. Otherwise, an /// extra note will be emitted pointing to location of the format string. /// @@ -2213,7 +2304,7 @@ void CheckFormatHandler::EmitFormatDiagnostic(PartialDiagnostic PDiag, /// \param StringRange some or all of the string to highlight. This is /// templated so it can accept either a CharSourceRange or a SourceRange. /// -/// \param Fixit optional fix it hint for the format string. +/// \param FixIt optional fix it hint for the format string. template<typename Range> void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, const Expr *ArgumentExpr, @@ -2221,15 +2312,27 @@ void CheckFormatHandler::EmitFormatDiagnostic(Sema &S, bool InFunctionCall, SourceLocation Loc, bool IsStringLocation, Range StringRange, - FixItHint FixIt) { - if (InFunctionCall) - S.Diag(Loc, PDiag) << StringRange << FixIt; - else { + ArrayRef<FixItHint> FixIt) { + if (InFunctionCall) { + const Sema::SemaDiagnosticBuilder &D = S.Diag(Loc, PDiag); + D << StringRange; + for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end(); + I != E; ++I) { + D << *I; + } + } else { S.Diag(IsStringLocation ? ArgumentExpr->getExprLoc() : Loc, PDiag) << ArgumentExpr->getSourceRange(); - S.Diag(IsStringLocation ? Loc : StringRange.getBegin(), - diag::note_format_string_defined) - << StringRange << FixIt; + + const Sema::SemaDiagnosticBuilder &Note = + S.Diag(IsStringLocation ? Loc : StringRange.getBegin(), + diag::note_format_string_defined); + + Note << StringRange; + for (ArrayRef<FixItHint>::iterator I = FixIt.begin(), E = FixIt.end(); + I != E; ++I) { + Note << *I; + } } } @@ -2550,23 +2653,17 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier startSpecifier, specifierLen); // Check the length modifier is valid with the given conversion specifier. - const LengthModifier &LM = FS.getLengthModifier(); - if (!FS.hasValidLengthModifier()) - EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length) - << LM.toString() << CS.toString(), - getLocationOfByte(LM.getStart()), - /*IsStringLocation*/true, - getSpecifierRange(startSpecifier, specifierLen), - FixItHint::CreateRemoval( - getSpecifierRange(LM.getStart(), - LM.getLength()))); - if (!FS.hasStandardLengthModifier()) - HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); + if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo())) + HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, + diag::warn_format_nonsensical_length); + else if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen); + else if (!FS.hasStandardLengthConversionCombination()) + HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, + diag::warn_format_non_standard_conversion_spec); + if (!FS.hasStandardConversionSpecifier(S.getLangOpts())) HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); - if (!FS.hasStandardLengthConversionCombination()) - HandleNonStandardConversionSpecification(LM, CS, startSpecifier, - specifierLen); // The remaining checks depend on the data arguments. if (HasVAListArg) @@ -2582,6 +2679,30 @@ CheckPrintfHandler::HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier return checkFormatExpr(FS, startSpecifier, specifierLen, Arg); } +static bool requiresParensToAddCast(const Expr *E) { + // FIXME: We should have a general way to reason about operator + // precedence and whether parens are actually needed here. + // Take care of a few common cases where they aren't. + const Expr *Inside = E->IgnoreImpCasts(); + if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(Inside)) + Inside = POE->getSyntacticForm()->IgnoreImpCasts(); + + switch (Inside->getStmtClass()) { + case Stmt::ArraySubscriptExprClass: + case Stmt::CallExprClass: + case Stmt::DeclRefExprClass: + case Stmt::MemberExprClass: + case Stmt::ObjCIvarRefExprClass: + case Stmt::ObjCMessageExprClass: + case Stmt::ObjCPropertyRefExprClass: + case Stmt::ParenExprClass: + case Stmt::UnaryOperatorClass: + return false; + default: + return true; + } +} + bool CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, const char *StartSpecifier, @@ -2593,81 +2714,151 @@ CheckPrintfHandler::checkFormatExpr(const analyze_printf::PrintfSpecifier &FS, // format specifier. const analyze_printf::ArgType &AT = FS.getArgType(S.Context, ObjCContext); - if (AT.isValid() && !AT.matchesType(S.Context, E->getType())) { - // Look through argument promotions for our error message's reported type. - // This includes the integral and floating promotions, but excludes array - // and function pointer decay; seeing that an argument intended to be a - // string has type 'char [6]' is probably more confusing than 'char *'. - if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { - if (ICE->getCastKind() == CK_IntegralCast || - ICE->getCastKind() == CK_FloatingCast) { - E = ICE->getSubExpr(); - - // Check if we didn't match because of an implicit cast from a 'char' - // or 'short' to an 'int'. This is done because printf is a varargs - // function. - if (ICE->getType() == S.Context.IntTy || - ICE->getType() == S.Context.UnsignedIntTy) { - // All further checking is done on the subexpression. - if (AT.matchesType(S.Context, E->getType())) - return true; - } + if (!AT.isValid()) + return true; + + QualType IntendedTy = E->getType(); + if (AT.matchesType(S.Context, IntendedTy)) + return true; + + // Look through argument promotions for our error message's reported type. + // This includes the integral and floating promotions, but excludes array + // and function pointer decay; seeing that an argument intended to be a + // string has type 'char [6]' is probably more confusing than 'char *'. + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + if (ICE->getCastKind() == CK_IntegralCast || + ICE->getCastKind() == CK_FloatingCast) { + E = ICE->getSubExpr(); + IntendedTy = 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 + // function. + 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)) + return true; } } + } - // We may be able to offer a FixItHint if it is a supported type. - PrintfSpecifier fixedFS = FS; - bool success = fixedFS.fixType(E->getType(), S.getLangOpts(), - S.Context, ObjCContext); + if (S.Context.getTargetInfo().getTriple().isOSDarwin()) { + // Special-case some of Darwin's platform-independence types. + if (const TypedefType *UserTy = IntendedTy->getAs<TypedefType>()) { + StringRef Name = UserTy->getDecl()->getName(); + IntendedTy = 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); + } + } - if (success) { - // Get the fix string from the fixed format specifier - SmallString<16> buf; - llvm::raw_svector_ostream os(buf); - fixedFS.toString(os); + // We may be able to offer a FixItHint if it is a supported type. + PrintfSpecifier fixedFS = FS; + bool success = fixedFS.fixType(IntendedTy, S.getLangOpts(), + S.Context, ObjCContext); + + if (success) { + // Get the fix string from the fixed format specifier + SmallString<16> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + CharSourceRange SpecRange = getSpecifierRange(StartSpecifier, SpecifierLen); + + if (IntendedTy != E->getType()) { + // 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 + // should be printed as 'long' for 64-bit compatibility.) + // Rather than emitting a normal format/argument mismatch, we want to + // add a cast to the recommended type (and correct the format string + // if necessary). + SmallString<16> CastBuf; + llvm::raw_svector_ostream CastFix(CastBuf); + CastFix << "("; + IntendedTy.print(CastFix, S.Context.getPrintingPolicy()); + CastFix << ")"; + + SmallVector<FixItHint,4> Hints; + if (!AT.matchesType(S.Context, IntendedTy)) + Hints.push_back(FixItHint::CreateReplacement(SpecRange, os.str())); + + if (const CStyleCastExpr *CCast = dyn_cast<CStyleCastExpr>(E)) { + // If there's already a cast present, just replace it. + SourceRange CastRange(CCast->getLParenLoc(), CCast->getRParenLoc()); + Hints.push_back(FixItHint::CreateReplacement(CastRange, CastFix.str())); + + } else if (!requiresParensToAddCast(E)) { + // If the expression has high enough precedence, + // just write the C-style cast. + Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(), + CastFix.str())); + } else { + // Otherwise, add parens around the expression as well as the cast. + CastFix << "("; + Hints.push_back(FixItHint::CreateInsertion(E->getLocStart(), + CastFix.str())); + + SourceLocation After = S.PP.getLocForEndOfToken(E->getLocEnd()); + 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) << E->getType() + << AT.getRepresentativeTypeName(S.Context) << IntendedTy << E->getSourceRange(), E->getLocStart(), /*IsStringLocation*/false, - getSpecifierRange(StartSpecifier, SpecifierLen), - FixItHint::CreateReplacement( - getSpecifierRange(StartSpecifier, SpecifierLen), - os.str())); - } else { - const CharSourceRange &CSR = getSpecifierRange(StartSpecifier, - SpecifierLen); - // 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) { - unsigned DiagKind; - if (E->getType()->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() - << CallType - << AT.getRepresentativeTypeName(S.Context) - << CSR - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, CSR); - - checkForCStrMembers(AT, E, CSR); - } else - EmitFormatDiagnostic( - S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) - << AT.getRepresentativeTypeName(S.Context) << E->getType() - << CSR - << E->getSourceRange(), - E->getLocStart(), /*IsStringLocation*/false, CSR); + SpecRange, + FixItHint::CreateReplacement(SpecRange, os.str())); } + } else { + const CharSourceRange &CSR = getSpecifierRange(StartSpecifier, + SpecifierLen); + // 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) { + unsigned DiagKind; + if (E->getType()->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() + << CallType + << AT.getRepresentativeTypeName(S.Context) + << CSR + << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation*/false, CSR); + + checkForCStrMembers(AT, E, CSR); + } else + EmitFormatDiagnostic( + S.PDiag(diag::warn_printf_conversion_argument_type_mismatch) + << AT.getRepresentativeTypeName(S.Context) << E->getType() + << CSR + << E->getSourceRange(), + E->getLocStart(), /*IsStringLocation*/false, CSR); } return true; @@ -2776,24 +2967,17 @@ bool CheckScanfHandler::HandleScanfSpecifier( } // Check the length modifier is valid with the given conversion specifier. - const LengthModifier &LM = FS.getLengthModifier(); - if (!FS.hasValidLengthModifier()) { - const CharSourceRange &R = getSpecifierRange(LM.getStart(), LM.getLength()); - EmitFormatDiagnostic(S.PDiag(diag::warn_format_nonsensical_length) - << LM.toString() << CS.toString() - << getSpecifierRange(startSpecifier, specifierLen), - getLocationOfByte(LM.getStart()), - /*IsStringLocation*/true, R, - FixItHint::CreateRemoval(R)); - } + if (!FS.hasValidLengthModifier(S.getASTContext().getTargetInfo())) + HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, + diag::warn_format_nonsensical_length); + else if (!FS.hasStandardLengthModifier()) + HandleNonStandardLengthModifier(FS, startSpecifier, specifierLen); + else if (!FS.hasStandardLengthConversionCombination()) + HandleInvalidLengthModifier(FS, CS, startSpecifier, specifierLen, + diag::warn_format_non_standard_conversion_spec); - if (!FS.hasStandardLengthModifier()) - HandleNonStandardLengthModifier(LM, startSpecifier, specifierLen); if (!FS.hasStandardConversionSpecifier(S.getLangOpts())) HandleNonStandardConversionSpecifier(CS, startSpecifier, specifierLen); - if (!FS.hasStandardLengthConversionCombination()) - HandleNonStandardConversionSpecification(LM, CS, startSpecifier, - specifierLen); // The remaining checks depend on the data arguments. if (HasVAListArg) @@ -2881,7 +3065,8 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, inFunctionCall, CallType); if (!analyze_format_string::ParsePrintfString(H, Str, Str + StrLen, - getLangOpts())) + getLangOpts(), + Context.getTargetInfo())) H.DoneProcessing(); } else if (Type == FST_Scanf) { CheckScanfHandler H(*this, FExpr, OrigFormatExpr, firstDataArg, numDataArgs, @@ -2889,7 +3074,8 @@ void Sema::CheckFormatString(const StringLiteral *FExpr, inFunctionCall, CallType); if (!analyze_format_string::ParseScanfString(H, Str, Str + StrLen, - getLangOpts())) + getLangOpts(), + Context.getTargetInfo())) H.DoneProcessing(); } // TODO: handle other formats } @@ -4138,6 +4324,44 @@ static void CheckTrivialUnsignedComparison(Sema &S, BinaryOperator *E) { } } +static void DiagnoseOutOfRangeComparison(Sema &S, BinaryOperator *E, + Expr *Constant, Expr *Other, + llvm::APSInt Value, + bool RhsConstant) { + BinaryOperatorKind op = E->getOpcode(); + QualType OtherT = Other->getType(); + QualType ConstantT = Constant->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 + IntRange OtherRange = IntRange::forValueOfType(S.Context, OtherT); + IntRange LitRange = GetValueRange(S.Context, Value, Value.getBitWidth()); + if (OtherRange.Width >= LitRange.Width) + return; + bool IsTrue = true; + if (op == BO_EQ) + IsTrue = false; + else if (op == BO_NE) + IsTrue = true; + else if (RhsConstant) { + if (op == BO_GT || op == BO_GE) + IsTrue = !LitRange.NonNegative; + else // op == BO_LT || op == BO_LE + IsTrue = LitRange.NonNegative; + } else { + if (op == BO_LT || op == BO_LE) + IsTrue = !LitRange.NonNegative; + else // op == BO_GT || op == BO_GE + IsTrue = LitRange.NonNegative; + } + SmallString<16> PrettySourceValue(Value.toString(10)); + S.Diag(E->getOperatorLoc(), diag::warn_out_of_range_compare) + << PrettySourceValue << OtherT << IsTrue + << E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange(); +} + /// Analyze the operands of the given comparison. Implements the /// fallback case from AnalyzeComparison. static void AnalyzeImpConvsInComparison(Sema &S, BinaryOperator *E) { @@ -4153,20 +4377,42 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { QualType T = E->getLHS()->getType(); assert(S.Context.hasSameUnqualifiedType(T, E->getRHS()->getType()) && "comparison with mismatched types"); + if (E->isValueDependent()) + return AnalyzeImpConvsInComparison(S, E); + Expr *LHS = E->getLHS()->IgnoreParenImpCasts(); + Expr *RHS = E->getRHS()->IgnoreParenImpCasts(); + + bool IsComparisonConstant = false; + + // Check whether an integer constant comparison results in a value + // of 'true' or 'false'. + if (T->isIntegralType(S.Context)) { + llvm::APSInt RHSValue; + bool IsRHSIntegralLiteral = + RHS->isIntegerConstantExpr(RHSValue, S.Context); + llvm::APSInt LHSValue; + bool IsLHSIntegralLiteral = + LHS->isIntegerConstantExpr(LHSValue, S.Context); + if (IsRHSIntegralLiteral && !IsLHSIntegralLiteral) + DiagnoseOutOfRangeComparison(S, E, RHS, LHS, RHSValue, true); + else if (!IsRHSIntegralLiteral && IsLHSIntegralLiteral) + DiagnoseOutOfRangeComparison(S, E, LHS, RHS, LHSValue, false); + else + IsComparisonConstant = + (IsRHSIntegralLiteral && IsLHSIntegralLiteral); + } else if (!T->hasUnsignedIntegerRepresentation()) + IsComparisonConstant = E->isIntegerConstantExpr(S.Context); + // We don't do anything special if this isn't an unsigned integral // comparison: we're only interested in integral comparisons, and // signed comparisons only happen in cases we don't care to warn about. // // We also don't care about value-dependent expressions or expressions // whose result is a constant. - if (!T->hasUnsignedIntegerRepresentation() - || E->isValueDependent() || E->isIntegerConstantExpr(S.Context)) + if (!T->hasUnsignedIntegerRepresentation() || IsComparisonConstant) return AnalyzeImpConvsInComparison(S, E); - - Expr *LHS = E->getLHS()->IgnoreParenImpCasts(); - Expr *RHS = E->getRHS()->IgnoreParenImpCasts(); - + // Check to see if one of the (unmodified) operands is of different // signedness. Expr *signedOperand, *unsignedOperand; @@ -4353,6 +4599,46 @@ std::string PrettyPrintInRange(const llvm::APSInt &Value, IntRange Range) { return ValueInRange.toString(10); } +static bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) { + if (!isa<ImplicitCastExpr>(Ex)) + return false; + + Expr *InnerE = Ex->IgnoreParenImpCasts(); + const Type *Target = S.Context.getCanonicalType(Ex->getType()).getTypePtr(); + const Type *Source = + S.Context.getCanonicalType(InnerE->getType()).getTypePtr(); + if (Target->isDependentType()) + return false; + + const BuiltinType *FloatCandidateBT = + dyn_cast<BuiltinType>(ToBool ? Source : Target); + const Type *BoolCandidateType = ToBool ? Target : Source; + + return (BoolCandidateType->isSpecificBuiltinType(BuiltinType::Bool) && + FloatCandidateBT && (FloatCandidateBT->isFloatingPoint())); +} + +void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, + SourceLocation CC) { + unsigned NumArgs = TheCall->getNumArgs(); + for (unsigned i = 0; i < NumArgs; ++i) { + Expr *CurrA = TheCall->getArg(i); + if (!IsImplicitBoolFloatConversion(S, CurrA, true)) + continue; + + bool IsSwapped = ((i > 0) && + IsImplicitBoolFloatConversion(S, TheCall->getArg(i - 1), false)); + IsSwapped |= ((i < (NumArgs - 1)) && + IsImplicitBoolFloatConversion(S, TheCall->getArg(i + 1), false)); + if (IsSwapped) { + // Warn on this floating-point to bool conversion. + DiagnoseImpCast(S, CurrA->IgnoreParenImpCasts(), + CurrA->getType(), CC, + diag::warn_impcast_floating_point_to_bool); + } + } +} + void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = 0) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -4488,12 +4774,33 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, } } + // If the target is bool, warn if expr is a function or method call. + if (Target->isSpecificBuiltinType(BuiltinType::Bool) && + isa<CallExpr>(E)) { + // Check last argument of function call to see if it is an + // implicit cast from a type matching the type the result + // is being cast to. + CallExpr *CEx = cast<CallExpr>(E); + unsigned NumArgs = CEx->getNumArgs(); + if (NumArgs > 0) { + Expr *LastA = CEx->getArg(NumArgs - 1); + Expr *InnerE = LastA->IgnoreParenImpCasts(); + const Type *InnerType = + S.Context.getCanonicalType(InnerE->getType()).getTypePtr(); + if (isa<ImplicitCastExpr>(LastA) && (InnerType == Target)) { + // Warn on this floating-point to bool conversion + DiagnoseImpCast(S, E, T, CC, + diag::warn_impcast_floating_point_to_bool); + } + } + } return; } if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) == Expr::NPCK_GNUNull) && !Target->isAnyPointerType() - && !Target->isBlockPointerType() && !Target->isMemberPointerType()) { + && !Target->isBlockPointerType() && !Target->isMemberPointerType() + && Target->isScalarType()) { SourceLocation Loc = E->getSourceRange().getBegin(); if (Loc.isMacroID()) Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; @@ -4658,6 +4965,10 @@ void AnalyzeImplicitConversions(Sema &S, Expr *OrigE, SourceLocation CC) { return; } + // Check implicit argument conversions for function calls. + if (CallExpr *Call = dyn_cast<CallExpr>(E)) + CheckImplicitArgumentConversions(S, Call, CC); + // Go ahead and check any implicit conversions we might have skipped. // The non-canonical typecheck is just an optimization; // CheckImplicitConversion will filter out dead implicit conversions. @@ -5077,7 +5388,8 @@ static bool considerVariable(VarDecl *var, Expr *ref, RetainCycleOwner &owner) { return false; owner.Variable = var; - owner.setLocsFrom(ref); + if (ref) + owner.setLocsFrom(ref); return true; } @@ -5186,6 +5498,12 @@ namespace { if (block->getBlockDecl()->capturesVariable(Variable)) Visit(block->getBlockDecl()->getBody()); } + + void VisitOpaqueValueExpr(OpaqueValueExpr *OVE) { + if (Capturer) return; + if (OVE->getSourceExpr()) + Visit(OVE->getSourceExpr()); + } }; } @@ -5195,6 +5513,28 @@ static Expr *findCapturingExpr(Sema &S, Expr *e, RetainCycleOwner &owner) { assert(owner.Variable && owner.Loc.isValid()); e = e->IgnoreParenCasts(); + + // Look through [^{...} copy] and Block_copy(^{...}). + if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(e)) { + Selector Cmd = ME->getSelector(); + if (Cmd.isUnarySelector() && Cmd.getNameForSlot(0) == "copy") { + e = ME->getInstanceReceiver(); + if (!e) + return 0; + e = e->IgnoreParenCasts(); + } + } else if (CallExpr *CE = dyn_cast<CallExpr>(e)) { + if (CE->getNumArgs() == 1) { + FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(CE->getCalleeDecl()); + if (Fn) { + const IdentifierInfo *FnI = Fn->getIdentifier(); + if (FnI && FnI->isStr("_Block_copy")) { + e = CE->getArg(0)->IgnoreParenCasts(); + } + } + } + } + BlockExpr *block = dyn_cast<BlockExpr>(e); if (!block || !block->getBlockDecl()->capturesVariable(owner.Variable)) return 0; @@ -5271,6 +5611,20 @@ void Sema::checkRetainCycles(Expr *receiver, Expr *argument) { diagnoseRetainCycle(*this, capturer, owner); } +void Sema::checkRetainCycles(VarDecl *Var, Expr *Init) { + RetainCycleOwner Owner; + if (!considerVariable(Var, /*DeclRefExpr=*/0, Owner)) + return; + + // Because we don't have an expression for the variable, we have to set the + // location explicitly here. + Owner.Loc = Var->getLocation(); + Owner.Range = Var->getSourceRange(); + + if (Expr *Capturer = findCapturingExpr(*this, Init, Owner)) + diagnoseRetainCycle(*this, Capturer, Owner); +} + bool Sema::checkUnsafeAssigns(SourceLocation Loc, QualType LHS, Expr *RHS) { Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime(); @@ -5304,9 +5658,19 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc, if (LHSType.isNull()) LHSType = LHS->getType(); + + Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); + + if (LT == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->markSafeWeakUse(LHS); + } + if (checkUnsafeAssigns(Loc, LHSType, RHS)) return; - Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime(); + // FIXME. Check for other life times. if (LT != Qualifiers::OCL_None) return; @@ -5826,7 +6190,8 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, if (IsPointerAttr) { // Skip implicit cast of pointer to `void *' (as a function argument). if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgumentExpr)) - if (ICE->getType()->isVoidPointerType()) + if (ICE->getType()->isVoidPointerType() && + ICE->getCastKind() == CK_BitCast) ArgumentExpr = ICE->getSubExpr(); } QualType ArgumentType = ArgumentExpr->getType(); @@ -5881,4 +6246,3 @@ void Sema::CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, << ArgumentExpr->getSourceRange() << TypeTagExpr->getSourceRange(); } - diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index adf1327..b1aead8 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1059,10 +1059,12 @@ bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const { // Allow us to find class templates, too. if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) ND = ClassTemplate->getTemplatedDecl(); - + + // For purposes of this check, interfaces match too. if (RecordDecl *RD = dyn_cast<RecordDecl>(ND)) return RD->getTagKind() == TTK_Class || - RD->getTagKind() == TTK_Struct; + RD->getTagKind() == TTK_Struct || + RD->getTagKind() == TTK_Interface; return false; } @@ -1422,7 +1424,8 @@ static const char *GetCompletionTypeString(QualType T, if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { switch (Tag->getTagKind()) { case TTK_Struct: return "struct <anonymous>"; - case TTK_Class: return "class <anonymous>"; + case TTK_Interface: return "__interface <anonymous>"; + case TTK_Class: return "class <anonymous>"; case TTK_Union: return "union <anonymous>"; case TTK_Enum: return "enum <anonymous>"; } @@ -1449,7 +1452,7 @@ static void addThisCompletion(Sema &S, ResultBuilder &Results) { Policy, Allocator)); Builder.AddTypedTextChunk("this"); - Results.AddResult(CodeCompletionResult(Builder.TakeString())); + Results.AddResult(CodeCompletionResult(Builder.TakeString())); } /// \brief Add language constructs that show up for "ordinary" names. @@ -2480,7 +2483,6 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, if (Declaration) { Result.addParentContext(Declaration->getDeclContext()); - Pattern->ParentKind = Result.getParentKind(); Pattern->ParentName = Result.getParentName(); } @@ -2493,7 +2495,7 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, } if (Kind == RK_Macro) { - MacroInfo *MI = PP.getMacroInfo(Macro); + MacroInfo *MI = PP.getMacroInfoHistory(Macro); assert(MI && "Not a macro?"); Result.AddTypedTextChunk( @@ -2880,10 +2882,14 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { case ObjCPropertyImplDecl::Synthesize: return CXCursor_ObjCSynthesizeDecl; } + + case Decl::Import: + return CXCursor_ModuleImportDecl; default: if (TagDecl *TD = dyn_cast<TagDecl>(D)) { switch (TD->getTagKind()) { + case TTK_Interface: // fall through case TTK_Struct: return CXCursor_StructDecl; case TTK_Class: return CXCursor_ClassDecl; case TTK_Union: return CXCursor_UnionDecl; @@ -2896,6 +2902,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { } static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, + bool IncludeUndefined, bool TargetTypeIsPointer = false) { typedef CodeCompletionResult Result; @@ -2904,7 +2911,8 @@ static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); M != MEnd; ++M) { - Results.AddResult(Result(M->first, + if (IncludeUndefined || M->first->hasMacroDefinition()) + Results.AddResult(Result(M->first, getMacroUsagePriority(M->first->getName(), PP.getLangOpts(), TargetTypeIsPointer))); @@ -3125,7 +3133,6 @@ void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, void Sema::CodeCompleteOrdinaryName(Scope *S, ParserCompletionContext CompletionContext) { - typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), mapCodeCompletionContext(*this, CompletionContext)); @@ -3204,7 +3211,7 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, } if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results); + AddMacroResults(PP, Results, false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); @@ -3296,7 +3303,6 @@ struct Sema::CodeCompleteExpressionData { /// type we're looking for. void Sema::CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data) { - typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Expression); @@ -3336,7 +3342,7 @@ void Sema::CodeCompleteExpression(Scope *S, AddPrettyFunctionResults(PP.getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results, PreferredTypeIsPointer); + AddMacroResults(PP, Results, false, PreferredTypeIsPointer); HandleCodeCompleteResults(this, CodeCompleter, CodeCompletionContext(CodeCompletionContext::CCC_Expression, Data.PreferredType), @@ -3580,7 +3586,6 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { if (!CodeCompleter) return; - typedef CodeCompletionResult Result; ResultBuilder::LookupFilter Filter = 0; enum CodeCompletionContext::Kind ContextKind = CodeCompletionContext::CCC_Other; @@ -3597,6 +3602,7 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { case DeclSpec::TST_struct: case DeclSpec::TST_class: + case DeclSpec::TST_interface: Filter = &ResultBuilder::IsClassOrStruct; ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; break; @@ -3728,7 +3734,7 @@ void Sema::CodeCompleteCase(Scope *S) { //so only say we include macros if the code completer says we do enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other; if (CodeCompleter->includeMacros()) { - AddMacroResults(PP, Results); + AddMacroResults(PP, Results, false); kind = CodeCompletionContext::CCC_OtherWithMacros; } @@ -3898,7 +3904,6 @@ void Sema::CodeCompleteReturn(Scope *S) { } void Sema::CodeCompleteAfterIf(Scope *S) { - typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), mapCodeCompletionContext(*this, PCC_Statement)); @@ -3952,7 +3957,7 @@ void Sema::CodeCompleteAfterIf(Scope *S) { AddPrettyFunctionResults(PP.getLangOpts(), Results); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results); + AddMacroResults(PP, Results, false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(),Results.size()); @@ -4408,7 +4413,6 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { } void Sema::CodeCompleteObjCAtDirective(Scope *S) { - typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); @@ -4595,26 +4599,23 @@ static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { // Check for collisions with "readonly". if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && - (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | - ObjCDeclSpec::DQ_PR_assign | - ObjCDeclSpec::DQ_PR_unsafe_unretained | - ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_retain | - ObjCDeclSpec::DQ_PR_strong))) + (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) return true; - // Check for more than one of { assign, copy, retain, strong }. + // Check for more than one of { assign, copy, retain, strong, weak }. unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained | ObjCDeclSpec::DQ_PR_copy | - ObjCDeclSpec::DQ_PR_retain| - ObjCDeclSpec::DQ_PR_strong); + ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong | + ObjCDeclSpec::DQ_PR_weak); if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain && - AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong) + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong && + AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak) return true; return false; @@ -4626,7 +4627,6 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { unsigned Attributes = ODS.getPropertyAttributes(); - typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); @@ -4650,6 +4650,12 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { Results.AddResult(CodeCompletionResult("nonatomic")); if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) Results.AddResult(CodeCompletionResult("atomic")); + + // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC. + if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC) + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak)) + Results.AddResult(CodeCompletionResult("weak")); + if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { CodeCompletionBuilder Setter(Results.getAllocator(), Results.getCodeCompletionTUInfo()); @@ -4837,8 +4843,6 @@ static void AddObjCMethods(ObjCContainerDecl *Container, void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { - typedef CodeCompletionResult Result; - // Try to find the interface where getters might live. ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); if (!Class) { @@ -4866,8 +4870,6 @@ void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { } void Sema::CodeCompleteObjCPropertySetter(Scope *S) { - typedef CodeCompletionResult Result; - // Try to find the interface where setters might live. ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); @@ -4898,7 +4900,6 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S) { void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, bool IsParameter) { - typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Type); @@ -4957,7 +4958,7 @@ void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, CodeCompleter->includeGlobals()); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results); + AddMacroResults(PP, Results, false); HandleCodeCompleteResults(this, CodeCompleter, CodeCompletionContext::CCC_Type, @@ -5041,7 +5042,7 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { /// /// \param S The semantic analysis object. /// -/// \param S NeedSuperKeyword Whether we need to prefix this completion with +/// \param NeedSuperKeyword Whether we need to prefix this completion with /// the "super" keyword. Otherwise, we just need to provide the arguments. /// /// \param SelIdents The identifiers in the selector that have already been @@ -5187,7 +5188,7 @@ void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { Results.ExitScope(); if (CodeCompleter->includeMacros()) - AddMacroResults(PP, Results); + AddMacroResults(PP, Results, false); HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), Results.data(), Results.size()); @@ -5339,11 +5340,11 @@ static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, // If we have an external source, load the entire class method // pool from the AST file. - if (SemaRef.ExternalSource) { + if (SemaRef.getExternalSource()) { for (uint32_t I = 0, - N = SemaRef.ExternalSource->GetNumExternalSelectors(); + N = SemaRef.getExternalSource()->GetNumExternalSelectors(); I != N; ++I) { - Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I); + Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I); if (Sel.isNull() || SemaRef.MethodPool.count(Sel)) continue; @@ -5868,7 +5869,6 @@ void Sema::CodeCompleteObjCImplementationCategory(Scope *S, } void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { - typedef CodeCompletionResult Result; ResultBuilder Results(*this, CodeCompleter->getAllocator(), CodeCompleter->getCodeCompletionTUInfo(), CodeCompletionContext::CCC_Other); @@ -7169,7 +7169,9 @@ void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { M != MEnd; ++M) { Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( M->first->getName())); - Results.AddResult(Builder.TakeString()); + Results.AddResult(CodeCompletionResult(Builder.TakeString(), + CCP_CodePattern, + CXCursor_MacroDefinition)); } Results.ExitScope(); } else if (IsDefinition) { @@ -7186,7 +7188,7 @@ void Sema::CodeCompletePreprocessorExpression() { CodeCompletionContext::CCC_PreprocessorExpression); if (!CodeCompleter || CodeCompleter->includeMacros()) - AddMacroResults(PP, Results); + AddMacroResults(PP, Results, true); // defined (<macro>) Results.EnterNewScope(); @@ -7235,7 +7237,7 @@ void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, } if (!CodeCompleter || CodeCompleter->includeMacros()) - AddMacroResults(PP, Builder); + AddMacroResults(PP, Builder, true); Results.clear(); Results.insert(Results.end(), diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ea181de..0092d5d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -350,8 +350,8 @@ ParsedType Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, /// isTagName() - This method is called *for error recovery purposes only* /// to determine if the specified name is a valid tag name ("struct foo"). If /// so, this returns the TST for the tag corresponding to it (TST_enum, -/// TST_union, TST_struct, TST_class). This is used to diagnose cases in C -/// where the user forgot to specify the tag. +/// TST_union, TST_struct, TST_interface, TST_class). This is used to diagnose +/// cases in C where the user forgot to specify the tag. DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { // Do a tag name lookup in this scope. LookupResult R(*this, &II, SourceLocation(), LookupTagName); @@ -361,6 +361,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { if (const TagDecl *TD = R.getAsSingle<TagDecl>()) { switch (TD->getTagKind()) { case TTK_Struct: return DeclSpec::TST_struct; + case TTK_Interface: return DeclSpec::TST_interface; case TTK_Union: return DeclSpec::TST_union; case TTK_Class: return DeclSpec::TST_class; case TTK_Enum: return DeclSpec::TST_enum; @@ -434,7 +435,8 @@ bool Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, else if (DeclContext *DC = computeDeclContext(*SS, false)) Diag(IILoc, diag::err_unknown_nested_typename_suggest) << II << DC << CorrectedQuotedStr << SS->getRange() - << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); else llvm_unreachable("could not have corrected a typo here"); @@ -517,9 +519,9 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc) { - Result.clear(Sema::LookupTagName); - SemaRef.LookupParsedName(Result, S, &SS); - if (TagDecl *Tag = Result.getAsSingle<TagDecl>()) { + LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName); + SemaRef.LookupParsedName(R, S, &SS); + if (TagDecl *Tag = R.getAsSingle<TagDecl>()) { const char *TagName = 0; const char *FixItTagName = 0; switch (Tag->getTagKind()) { @@ -538,6 +540,11 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, FixItTagName = "struct "; break; + case TTK_Interface: + TagName = "__interface"; + FixItTagName = "__interface "; + break; + case TTK_Union: TagName = "union"; FixItTagName = "union "; @@ -548,25 +555,42 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result, << Name << TagName << SemaRef.getLangOpts().CPlusPlus << FixItHint::CreateInsertion(NameLoc, FixItTagName); - LookupResult R(SemaRef, Name, NameLoc, Sema::LookupOrdinaryName); - if (SemaRef.LookupParsedName(R, S, &SS)) { - for (LookupResult::iterator I = R.begin(), IEnd = R.end(); - I != IEnd; ++I) - SemaRef.Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type) - << Name << TagName; - } + for (LookupResult::iterator I = Result.begin(), IEnd = Result.end(); + I != IEnd; ++I) + SemaRef.Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type) + << Name << TagName; + + // Replace lookup results with just the tag decl. + Result.clear(Sema::LookupTagName); + SemaRef.LookupParsedName(Result, S, &SS); return true; } - Result.clear(Sema::LookupOrdinaryName); return false; } +/// Build a ParsedType for a simple-type-specifier with a nested-name-specifier. +static ParsedType buildNestedType(Sema &S, CXXScopeSpec &SS, + QualType T, SourceLocation NameLoc) { + ASTContext &Context = S.Context; + + TypeLocBuilder Builder; + Builder.pushTypeSpec(T).setNameLoc(NameLoc); + + T = S.getElaboratedType(ETK_None, SS, T); + ElaboratedTypeLoc ElabTL = Builder.push<ElaboratedTypeLoc>(T); + ElabTL.setElaboratedKeywordLoc(SourceLocation()); + ElabTL.setQualifierLoc(SS.getWithLocInContext(Context)); + return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); +} + Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, SourceLocation NameLoc, - const Token &NextToken) { + const Token &NextToken, + bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC) { DeclarationNameInfo NameInfo(Name, NameLoc); ObjCMethodDecl *CurMethod = getCurMethodDecl(); @@ -632,25 +656,11 @@ Corrected: // Perform typo correction to determine if there is another name that is // close to this name. - if (!SecondTry) { + if (!SecondTry && CCC) { SecondTry = true; - CorrectionCandidateCallback DefaultValidator; - // Try to limit which sets of keywords should be included in typo - // correction based on what the next token is. - DefaultValidator.WantTypeSpecifiers = - NextToken.is(tok::l_paren) || NextToken.is(tok::less) || - NextToken.is(tok::identifier) || NextToken.is(tok::star) || - NextToken.is(tok::amp) || NextToken.is(tok::l_square); - DefaultValidator.WantExpressionKeywords = - NextToken.is(tok::l_paren) || NextToken.is(tok::identifier) || - NextToken.is(tok::arrow) || NextToken.is(tok::period); - DefaultValidator.WantRemainingKeywords = - NextToken.is(tok::l_paren) || NextToken.is(tok::semi) || - NextToken.is(tok::identifier) || NextToken.is(tok::l_brace); - DefaultValidator.WantCXXNamedCasts = false; if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), Result.getLookupKind(), S, - &SS, DefaultValidator)) { + &SS, *CCC)) { unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; std::string CorrectedStr(Corrected.getAsString(getLangOpts())); @@ -675,11 +685,12 @@ Corrected: Diag(NameLoc, UnqualifiedDiag) << Name << CorrectedQuotedStr << FixItHint::CreateReplacement(NameLoc, CorrectedStr); - else + else // FIXME: is this even reachable? Test it. Diag(NameLoc, QualifiedDiag) << Name << computeDeclContext(SS, false) << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(NameLoc, CorrectedStr); + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); // Update the name, so that the caller has the new name. Name = Corrected.getCorrectionAsIdentifierInfo(); @@ -705,7 +716,7 @@ Corrected: if (ObjCIvarDecl *Ivar = Result.getAsSingle<ObjCIvarDecl>()) { Result.clear(); ExprResult E(LookupInObjCMethod(Result, S, Ivar->getIdentifier())); - return move(E); + return E; } goto Corrected; @@ -731,8 +742,9 @@ Corrected: // perform some heroics to see if we actually have a // template-argument-list, which would indicate a missing 'template' // keyword here. - return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/0); + return ActOnDependentIdExpression(SS, /*TemplateKWLoc=*/SourceLocation(), + NameInfo, IsAddressOfOperand, + /*TemplateArgs=*/0); } case LookupResult::Found: @@ -808,14 +820,16 @@ Corrected: return NameClassification::TypeTemplate(Template); } } - + NamedDecl *FirstDecl = (*Result.begin())->getUnderlyingDecl(); if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) { DiagnoseUseOfDecl(Type, NameLoc); QualType T = Context.getTypeDeclType(Type); + if (SS.isNotEmpty()) + return buildNestedType(*this, SS, T, NameLoc); return ParsedType::make(T); } - + ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(FirstDecl); if (!Class) { // FIXME: It's unfortunate that we don't have a Type node for handling this. @@ -838,24 +852,28 @@ Corrected: return ParsedType::make(T); } + // We can have a type template here if we're classifying a template argument. + if (isa<TemplateDecl>(FirstDecl) && !isa<FunctionTemplateDecl>(FirstDecl)) + return NameClassification::TypeTemplate( + TemplateName(cast<TemplateDecl>(FirstDecl))); + // Check for a tag type hidden by a non-type decl in a few cases where it // seems likely a type is wanted instead of the non-type that was found. - if (!getLangOpts().ObjC1 && FirstDecl && !isa<ClassTemplateDecl>(FirstDecl) && - !isa<TypeAliasTemplateDecl>(FirstDecl)) { + if (!getLangOpts().ObjC1) { bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star); if ((NextToken.is(tok::identifier) || (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) && isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { - FirstDecl = (*Result.begin())->getUnderlyingDecl(); - if (TypeDecl *Type = dyn_cast<TypeDecl>(FirstDecl)) { - DiagnoseUseOfDecl(Type, NameLoc); - QualType T = Context.getTypeDeclType(Type); - return ParsedType::make(T); - } + TypeDecl *Type = Result.getAsSingle<TypeDecl>(); + DiagnoseUseOfDecl(Type, NameLoc); + QualType T = Context.getTypeDeclType(Type); + if (SS.isNotEmpty()) + return buildNestedType(*this, SS, T, NameLoc); + return ParsedType::make(T); } } - if (!Result.empty() && (*Result.begin())->isCXXClassMember()) + if (FirstDecl->isCXXClassMember()) return BuildPossibleImplicitMemberExpr(SS, SourceLocation(), Result, 0); bool ADL = UseArgumentDependentLookup(SS, Result, NextToken.is(tok::l_paren)); @@ -1186,8 +1204,14 @@ bool Sema::ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const { Context.DeclMustBeEmitted(FD)) return false; } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + // Don't warn on variables of const-qualified or reference type, since their + // values can be used even if though they're not odr-used, and because const + // qualified variables can appear in headers in contexts where they're not + // intended to be used. + // FIXME: Use more principled rules for these exemptions. if (!VD->isFileVarDecl() || - VD->getType().isConstant(Context) || + VD->getType().isConstQualified() || + VD->getType()->isReferenceType() || Context.DeclMustBeEmitted(VD)) return false; @@ -1248,7 +1272,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { QualType Ty = VD->getType(); // Only look at the outermost level of typedef. - if (const TypedefType *TT = dyn_cast<TypedefType>(Ty)) { + if (const TypedefType *TT = Ty->getAs<TypedefType>()) { if (TT->getDecl()->hasAttr<UnusedAttr>()) return false; } @@ -1268,6 +1292,8 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { return false; if (const Expr *Init = VD->getInit()) { + if (const ExprWithCleanups *Cleanups = dyn_cast<ExprWithCleanups>(Init)) + Init = Cleanups->getSubExpr(); const CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init); if (Construct && !Construct->isElidable()) { @@ -1706,6 +1732,25 @@ DeclHasAttr(const Decl *D, const Attr *A) { if (AA) return false; + // The following thread safety attributes can also be duplicated. + switch (A->getKind()) { + case attr::ExclusiveLocksRequired: + case attr::SharedLocksRequired: + case attr::LocksExcluded: + case attr::ExclusiveLockFunction: + case attr::SharedLockFunction: + case attr::UnlockFunction: + case attr::ExclusiveTrylockFunction: + case attr::SharedTrylockFunction: + case attr::GuardedBy: + case attr::PtGuardedBy: + case attr::AcquiredBefore: + case attr::AcquiredAfter: + return false; + default: + ; + } + const OwnershipAttr *OA = dyn_cast<OwnershipAttr>(A); const AnnotateAttr *Ann = dyn_cast<AnnotateAttr>(A); for (Decl::attr_iterator i = D->attr_begin(), e = D->attr_end(); i != e; ++i) @@ -1908,6 +1953,19 @@ static bool canRedefineFunction(const FunctionDecl *FD, FD->getStorageClass() == SC_Extern); } +/// Is the given calling convention the ABI default for the given +/// declaration? +static bool isABIDefaultCC(Sema &S, CallingConv CC, FunctionDecl *D) { + CallingConv ABIDefaultCC; + if (isa<CXXMethodDecl>(D) && cast<CXXMethodDecl>(D)->isInstance()) { + ABIDefaultCC = S.Context.getDefaultCXXMethodCallConv(D->isVariadic()); + } else { + // Free C function or a static method. + ABIDefaultCC = (S.Context.getLangOpts().MRTD ? CC_X86StdCall : CC_C); + } + return ABIDefaultCC == CC; +} + /// 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, @@ -1976,6 +2034,9 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { // later declared or defined without one, the second decl assumes the // calling convention of the first. // + // It's OK if a function is first declared without a calling convention, + // but is later declared or defined with the default calling convention. + // // For the new decl, we have to look at the NON-canonical type to tell the // difference between a function that really doesn't have a calling // convention and one that is declared cdecl. That's because in @@ -1989,10 +2050,22 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S) { FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo(); FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo(); bool RequiresAdjustment = false; - if (OldTypeInfo.getCC() != CC_Default && - NewTypeInfo.getCC() == CC_Default) { + if (OldTypeInfo.getCC() == NewTypeInfo.getCC()) { + // Fast path: nothing to do. + + // Inherit the CC from the previous declaration if it was specified + // there but not here. + } else if (NewTypeInfo.getCC() == CC_Default) { NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); RequiresAdjustment = true; + + // Don't complain about mismatches when the default CC is + // effectively the same as the explict one. + } else if (OldTypeInfo.getCC() == CC_Default && + isABIDefaultCC(*this, NewTypeInfo.getCC(), New)) { + NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC()); + RequiresAdjustment = true; + } else if (!Context.isSameCallConv(OldTypeInfo.getCC(), NewTypeInfo.getCC())) { // Calling conventions really aren't compatible, so complain. @@ -2398,7 +2471,7 @@ void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { } if (MergedT.isNull()) { Diag(New->getLocation(), diag::err_redefinition_different_type) - << New->getDeclName(); + << New->getDeclName() << New->getType() << Old->getType(); Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); } @@ -2551,8 +2624,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { /// no declarator (e.g. "struct foo;") is parsed. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS) { - return ParsedFreeStandingDeclSpec(S, AS, DS, - MultiTemplateParamsArg(*this, 0, 0)); + return ParsedFreeStandingDeclSpec(S, AS, DS, MultiTemplateParamsArg()); } /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with @@ -2565,6 +2637,7 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, TagDecl *Tag = 0; if (DS.getTypeSpecType() == DeclSpec::TST_class || DS.getTypeSpecType() == DeclSpec::TST_struct || + DS.getTypeSpecType() == DeclSpec::TST_interface || DS.getTypeSpecType() == DeclSpec::TST_union || DS.getTypeSpecType() == DeclSpec::TST_enum) { TagD = DS.getRepAsDecl(); @@ -2603,7 +2676,8 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag) << (DS.getTypeSpecType() == DeclSpec::TST_class ? 0 : DS.getTypeSpecType() == DeclSpec::TST_struct ? 1 : - DS.getTypeSpecType() == DeclSpec::TST_union ? 2 : 3); + DS.getTypeSpecType() == DeclSpec::TST_interface ? 2 : + DS.getTypeSpecType() == DeclSpec::TST_union ? 3 : 4); else Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators); // Don't emit warnings after this error. @@ -2724,16 +2798,17 @@ Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec::TST TypeSpecType = DS.getTypeSpecType(); if (TypeSpecType == DeclSpec::TST_class || TypeSpecType == DeclSpec::TST_struct || + TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { AttributeList* attrs = DS.getAttributes().getList(); while (attrs) { - Diag(attrs->getScopeLoc(), - diag::warn_declspec_attribute_ignored) + Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored) << attrs->getName() << (TypeSpecType == DeclSpec::TST_class ? 0 : TypeSpecType == DeclSpec::TST_struct ? 1 : - TypeSpecType == DeclSpec::TST_union ? 2 : 3); + TypeSpecType == DeclSpec::TST_union ? 2 : + TypeSpecType == DeclSpec::TST_interface ? 3 : 4); attrs = attrs->getNext(); } } @@ -3353,7 +3428,6 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, switch (DS.getTypeSpecType()) { case DeclSpec::TST_typename: case DeclSpec::TST_typeofType: - case DeclSpec::TST_decltype: case DeclSpec::TST_underlyingType: case DeclSpec::TST_atomic: { // Grab the type from the parser. @@ -3377,6 +3451,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, break; } + case DeclSpec::TST_decltype: case DeclSpec::TST_typeofExpr: { Expr *E = DS.getRepAsExpr(); ExprResult Result = S.RebuildExprInCurrentInstantiation(E); @@ -3411,7 +3486,7 @@ static bool RebuildDeclaratorInCurrentInstantiation(Sema &S, Declarator &D, Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { D.setFunctionDefinitionKind(FDK_Declaration); - Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg(*this)); + Decl *Dcl = HandleDeclarator(S, D, MultiTemplateParamsArg()); if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer() && Dcl && Dcl->getDeclContext()->isFileContext()) @@ -3476,7 +3551,8 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, // void X::f(); // }; if (Cur->Equals(DC)) { - Diag(Loc, diag::warn_member_extra_qualification) + Diag(Loc, LangOpts.MicrosoftExt? diag::warn_member_extra_qualification + : diag::err_member_extra_qualification) << Name << FixItHint::CreateRemoval(SS.getRange()); SS.clear(); return false; @@ -3710,11 +3786,11 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, New = ActOnTypedefDeclarator(S, D, DC, TInfo, Previous); } else if (R->isFunctionType()) { New = ActOnFunctionDeclarator(S, D, DC, TInfo, Previous, - move(TemplateParamLists), + TemplateParamLists, AddToScope); } else { New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, - move(TemplateParamLists)); + TemplateParamLists); } if (New == 0) @@ -3729,9 +3805,9 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, return New; } -/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array -/// types into constant array types in certain situations which would otherwise -/// be errors (for GCC compatibility). +/// Helper method to turn variable array types into constant array +/// types in certain situations which would otherwise be errors (for +/// GCC compatibility). static QualType TryToFixInvalidVariablyModifiedType(QualType T, ASTContext &Context, bool &SizeIsNegative, @@ -3799,6 +3875,52 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, Res, ArrayType::Normal, 0); } +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()); + 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()); + return; + } + ArrayTypeLoc* SrcATL = cast<ArrayTypeLoc>(&SrcTL); + ArrayTypeLoc* DstATL = cast<ArrayTypeLoc>(&DstTL); + TypeLoc SrcElemTL = SrcATL->getElementLoc(); + TypeLoc DstElemTL = DstATL->getElementLoc(); + DstElemTL.initializeFullCopy(SrcElemTL); + DstATL->setLBracketLoc(SrcATL->getLBracketLoc()); + DstATL->setSizeExpr(SrcATL->getSizeExpr()); + DstATL->setRBracketLoc(SrcATL->getRBracketLoc()); +} + +/// Helper method to turn variable array types into constant array +/// types in certain situations which would otherwise be errors (for +/// GCC compatibility). +static TypeSourceInfo* +TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, + ASTContext &Context, + bool &SizeIsNegative, + llvm::APSInt &Oversized) { + QualType FixedTy + = TryToFixInvalidVariablyModifiedType(TInfo->getType(), Context, + SizeIsNegative, Oversized); + if (FixedTy.isNull()) + return 0; + TypeSourceInfo *FixedTInfo = Context.getTrivialTypeSourceInfo(FixedTy); + FixInvalidVariablyModifiedTypeLoc(TInfo->getTypeLoc(), + FixedTInfo->getTypeLoc()); + return FixedTInfo; +} + /// \brief Register the given locally-scoped external C declaration so /// that it can be found later for redeclarations void @@ -3926,19 +4048,21 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { // then it shall have block scope. // Note that variably modified types must be fixed before merging the decl so // that redeclarations will match. - QualType T = NewTD->getUnderlyingType(); + TypeSourceInfo *TInfo = NewTD->getTypeSourceInfo(); + QualType T = TInfo->getType(); if (T->isVariablyModifiedType()) { getCurFunction()->setHasBranchProtectedScope(); if (S->getFnParent() == 0) { bool SizeIsNegative; llvm::APSInt Oversized; - QualType FixedTy = - TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, - Oversized); - if (!FixedTy.isNull()) { + TypeSourceInfo *FixedTInfo = + TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, + SizeIsNegative, + Oversized); + if (FixedTInfo) { Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); - NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); + NewTD->setTypeSourceInfo(FixedTInfo); } else { if (SizeIsNegative) Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); @@ -4203,7 +4327,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), - TemplateParamLists.get(), + TemplateParamLists.data(), TemplateParamLists.size(), /*never a friend*/ false, isExplicitSpecialization, @@ -4244,7 +4368,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (TemplateParamLists.size() > 0 && D.getCXXScopeSpec().isSet()) { NewVD->setTemplateParameterListsInfo(Context, TemplateParamLists.size(), - TemplateParamLists.release()); + TemplateParamLists.data()); } if (D.getDeclSpec().isConstexprSpecified()) @@ -4281,6 +4405,14 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); + 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->setStorageClass(SC_Static); + } + // In auto-retain/release, infer strong retension for variables of // retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) @@ -4490,7 +4622,8 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, if (NewVD->isInvalidDecl()) return false; - QualType T = NewVD->getType(); + TypeSourceInfo *TInfo = NewVD->getTypeSourceInfo(); + QualType T = TInfo->getType(); if (T->isObjCObjectType()) { Diag(NewVD->getLocation(), diag::err_statically_allocated_object) @@ -4522,8 +4655,10 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, && !NewVD->hasAttr<BlocksAttr>()) { if (getLangOpts().getGC() != LangOptions::NonGC) Diag(NewVD->getLocation(), diag::warn_gc_attribute_weak_on_local); - else + else { + assert(!getLangOpts().ObjCAutoRefCount); Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); + } } bool isVM = T->isVariablyModifiedType(); @@ -4535,11 +4670,10 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, (T->isVariableArrayType() && NewVD->hasGlobalStorage())) { bool SizeIsNegative; llvm::APSInt Oversized; - QualType FixedTy = - TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, - Oversized); - - if (FixedTy.isNull() && T->isVariableArrayType()) { + TypeSourceInfo *FixedTInfo = + TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, + SizeIsNegative, Oversized); + if (FixedTInfo == 0 && T->isVariableArrayType()) { const VariableArrayType *VAT = Context.getAsVariableArrayType(T); // FIXME: This won't give the correct result for // int a[10][n]; @@ -4558,7 +4692,7 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, return false; } - if (FixedTy.isNull()) { + if (FixedTInfo == 0) { if (NewVD->isFileVarDecl()) Diag(NewVD->getLocation(), diag::err_vm_decl_in_file_scope); else @@ -4568,7 +4702,8 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, } Diag(NewVD->getLocation(), diag::warn_illegal_constant_array_size); - NewVD->setType(FixedTy); + NewVD->setType(FixedTInfo->getType()); + NewVD->setTypeSourceInfo(FixedTInfo); } if (Previous.empty() && NewVD->isExternC()) { @@ -4655,6 +4790,31 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, return false; } +namespace { + enum OverrideErrorKind { OEK_All, OEK_NonDeleted, OEK_Deleted }; +} +/// \brief Report an error regarding overriding, along with any relevant +/// overriden methods. +/// +/// \param DiagID the primary error to report. +/// \param MD the overriding method. +/// \param OEK which overrides to include as notes. +static void ReportOverrides(Sema& S, unsigned DiagID, const CXXMethodDecl *MD, + OverrideErrorKind OEK = OEK_All) { + S.Diag(MD->getLocation(), DiagID) << MD->getDeclName(); + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) { + // This check (& the OEK parameter) could be replaced by a predicate, but + // without lambdas that would be overkill. This is still nicer than writing + // out the diag loop 3 times. + if ((OEK == OEK_All) || + (OEK == OEK_NonDeleted && !(*I)->isDeleted()) || + (OEK == OEK_Deleted && (*I)->isDeleted())) + S.Diag((*I)->getLocation(), diag::note_overridden_virtual_function); + } +} + /// AddOverriddenMethods - See if a method overrides any in the base classes, /// and if so, check that it's a valid override and remember it. bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { @@ -4663,6 +4823,8 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { FindOverriddenMethodData Data; Data.Method = MD; Data.S = this; + bool hasDeletedOverridenMethods = false; + bool hasNonDeletedOverridenMethods = false; bool AddedAny = false; if (DC->lookupInBases(&FindOverriddenMethod, &Data, Paths)) { for (CXXBasePaths::decl_iterator I = Paths.found_decls_begin(), @@ -4672,12 +4834,21 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { if (!CheckOverridingFunctionReturnType(MD, OldMD) && !CheckOverridingFunctionExceptionSpec(MD, OldMD) && !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { + hasDeletedOverridenMethods |= OldMD->isDeleted(); + hasNonDeletedOverridenMethods |= !OldMD->isDeleted(); AddedAny = true; } } } } - + + if (hasDeletedOverridenMethods && !MD->isDeleted()) { + ReportOverrides(*this, diag::err_non_deleted_override, MD, OEK_Deleted); + } + if (hasNonDeletedOverridenMethods && MD->isDeleted()) { + ReportOverrides(*this, diag::err_deleted_override, MD, OEK_NonDeleted); + } + return AddedAny; } @@ -4837,6 +5008,10 @@ static NamedDecl* DiagnoseInvalidRedeclaration( } if (Correction) { + // FIXME: use Correction.getCorrectionRange() instead of computing the range + // here. This requires passing in the CXXScopeSpec to CorrectTypo which in + // turn causes the correction to fully qualify the name. If we fix + // CorrectTypo to minimally qualify then this change should be good. SourceRange FixItLoc(NewFD->getLocation()); CXXScopeSpec &SS = ExtraArgs.D.getCXXScopeSpec(); if (Correction.getCorrectionSpecifier() && SS.isValid()) @@ -5072,6 +5247,22 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, } } +void Sema::checkVoidParamDecl(ParmVarDecl *Param) { + // In C++, the empty parameter-type-list must be spelled "void"; a + // typedef of void is not permitted. + if (getLangOpts().CPlusPlus && + Param->getType().getUnqualifiedType() != Context.VoidTy) { + bool IsTypeAlias = false; + if (const TypedefType *TT = Param->getType()->getAs<TypedefType>()) + IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl()); + else if (const TemplateSpecializationType *TST = + Param->getType()->getAs<TemplateSpecializationType>()) + IsTypeAlias = TST->isTypeAlias(); + Diag(Param->getLocation(), diag::err_param_typedef_of_void) + << IsTypeAlias; + } +} + NamedDecl* Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -5138,6 +5329,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD->setImplicitlyInline(); } + // If this is a method defined in an __interface, and is not a constructor + // or an overloaded operator, then set the pure flag (isVirtual will already + // return true). + if (const CXXRecordDecl *Parent = + dyn_cast<CXXRecordDecl>(NewFD->getDeclContext())) { + if (Parent->isInterface() && cast<CXXMethodDecl>(NewFD)->isUserProvided()) + NewFD->setPure(true); + } + SetNestedNameSpecifier(NewFD, D); isExplicitSpecialization = false; isFunctionTemplateSpecialization = false; @@ -5157,7 +5357,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, D.getDeclSpec().getLocStart(), D.getIdentifierLoc(), D.getCXXScopeSpec(), - TemplateParamLists.get(), + TemplateParamLists.data(), TemplateParamLists.size(), isFriend, isExplicitSpecialization, @@ -5196,7 +5396,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (TemplateParamLists.size() > 1) { NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists.size() - 1, - TemplateParamLists.release()); + TemplateParamLists.data()); } } else { // This is a function template specialization. @@ -5204,7 +5404,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // For source fidelity, store all the template param lists. NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists.size(), - TemplateParamLists.release()); + TemplateParamLists.data()); // C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);". if (isFriend) { @@ -5236,7 +5436,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // For source fidelity, store all the template param lists. NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists.size(), - TemplateParamLists.release()); + TemplateParamLists.data()); } if (Invalid) { @@ -5376,6 +5576,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, diag::err_static_out_of_line) << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); } + + // C++11 [except.spec]p15: + // A deallocation function with no exception-specification is treated + // as if it were specified with noexcept(true). + const FunctionProtoType *FPT = R->getAs<FunctionProtoType>(); + if ((Name.getCXXOverloadedOperator() == OO_Delete || + Name.getCXXOverloadedOperator() == OO_Array_Delete) && + getLangOpts().CPlusPlus0x && 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)); + } } // Filter out previous declarations that don't match the scope. @@ -5413,21 +5627,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, FTI.ArgInfo[0].Param && cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { // Empty arg list, don't push any params. - ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[0].Param); - - // In C++, the empty parameter-type-list must be spelled "void"; a - // typedef of void is not permitted. - if (getLangOpts().CPlusPlus && - Param->getType().getUnqualifiedType() != Context.VoidTy) { - bool IsTypeAlias = false; - if (const TypedefType *TT = Param->getType()->getAs<TypedefType>()) - IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl()); - else if (const TemplateSpecializationType *TST = - Param->getType()->getAs<TemplateSpecializationType>()) - IsTypeAlias = TST->isTypeAlias(); - Diag(Param->getLocation(), diag::err_param_typedef_of_void) - << IsTypeAlias; - } + checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param)); } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param); @@ -5500,6 +5700,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization)); } + // Make graceful recovery from an invalid redeclaration. + else if (!Previous.empty()) + D.setRedeclaration(true); assert((NewFD->isInvalidDecl() || !D.isRedeclaration() || Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); @@ -5510,12 +5713,10 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, TemplateIdAnnotation *TemplateId = D.getName().TemplateId; TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); - ASTTemplateArgsPtr TemplateArgsPtr(*this, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, TemplateArgs); - TemplateArgsPtr.release(); HasExplicitTemplateArgs = true; @@ -5969,20 +6170,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // Find any virtual functions that this function overrides. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD)) { if (!Method->isFunctionTemplateSpecialization() && - !Method->getDescribedFunctionTemplate()) { + !Method->getDescribedFunctionTemplate() && + Method->isCanonicalDecl()) { if (AddOverriddenMethods(Method->getParent(), Method)) { // If the function was marked as "static", we have a problem. if (NewFD->getStorageClass() == SC_Static) { - Diag(NewFD->getLocation(), diag::err_static_overrides_virtual) - << NewFD->getDeclName(); - for (CXXMethodDecl::method_iterator - Overridden = Method->begin_overridden_methods(), - OverriddenEnd = Method->end_overridden_methods(); - Overridden != OverriddenEnd; - ++Overridden) { - Diag((*Overridden)->getLocation(), - diag::note_overridden_virtual_function); - } + ReportOverrides(*this, diag::err_static_overrides_virtual, Method); } } } @@ -6191,28 +6384,12 @@ namespace { } } - // Sometimes, the expression passed in lacks the casts that are used - // to determine which DeclRefExpr's to check. Assume that the casts - // are present and continue visiting the expression. - void HandleExpr(Expr *E) { - // Skip checking T a = a where T is not a record or reference type. - // Doing so is a way to silence uninitialized warnings. - if (isRecordType || isReferenceType) - if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - HandleDeclRefExpr(DRE); - - if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { - HandleValue(CO->getTrueExpr()); - HandleValue(CO->getFalseExpr()); - } - - Visit(E); - } - // For most expressions, the cast is directly above the DeclRefExpr. // For conditional operators, the cast can be outside the conditional // operator if both expressions are DeclRefExpr's. void HandleValue(Expr *E) { + if (isReferenceType) + return; E = E->IgnoreParenImpCasts(); if (DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(E)) { HandleDeclRefExpr(DRE); @@ -6222,11 +6399,32 @@ namespace { if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { HandleValue(CO->getTrueExpr()); HandleValue(CO->getFalseExpr()); + return; + } + + if (isa<MemberExpr>(E)) { + Expr *Base = E->IgnoreParenImpCasts(); + while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) { + // Check for static member variables and don't warn on them. + if (!isa<FieldDecl>(ME->getMemberDecl())) + return; + Base = ME->getBase()->IgnoreParenImpCasts(); + } + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) + HandleDeclRefExpr(DRE); + return; } } + // Reference types are handled here since all uses of references are + // bad, not just r-value uses. + void VisitDeclRefExpr(DeclRefExpr *E) { + if (isReferenceType) + HandleDeclRefExpr(E); + } + void VisitImplicitCastExpr(ImplicitCastExpr *E) { - if ((!isRecordType && E->getCastKind() == CK_LValueToRValue) || + if (E->getCastKind() == CK_LValueToRValue || (isRecordType && E->getCastKind() == CK_NoOp)) HandleValue(E->getSubExpr()); @@ -6237,22 +6435,36 @@ namespace { // Don't warn on arrays since they can be treated as pointers. if (E->getType()->canDecayToPointerType()) return; - ValueDecl *VD = E->getMemberDecl(); - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(VD); - if (isa<FieldDecl>(VD) || (MD && !MD->isStatic())) - if (DeclRefExpr *DRE - = dyn_cast<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts())) { + // Warn when a non-static method call is followed by non-static member + // field accesses, which is followed by a DeclRefExpr. + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl()); + bool Warn = (MD && !MD->isStatic()); + Expr *Base = E->getBase()->IgnoreParenImpCasts(); + while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) { + if (!isa<FieldDecl>(ME->getMemberDecl())) + Warn = false; + Base = ME->getBase()->IgnoreParenImpCasts(); + } + + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) { + if (Warn) HandleDeclRefExpr(DRE); - return; - } + return; + } - Inherited::VisitMemberExpr(E); + // The base of a MemberExpr is not a MemberExpr or a DeclRefExpr. + // Visit that expression. + Visit(Base); } void VisitUnaryOperator(UnaryOperator *E) { // For POD record types, addresses of its own members are well-defined. - if (E->getOpcode() == UO_AddrOf && isRecordType && isPODType && - isa<MemberExpr>(E->getSubExpr()->IgnoreParens())) return; + if (E->getOpcode() == UO_AddrOf && isRecordType && + isa<MemberExpr>(E->getSubExpr()->IgnoreParens())) { + if (!isPODType) + HandleValue(E->getSubExpr()); + return; + } Inherited::VisitUnaryOperator(E); } @@ -6261,20 +6473,38 @@ namespace { void HandleDeclRefExpr(DeclRefExpr *DRE) { Decl* ReferenceDecl = DRE->getDecl(); if (OrigDecl != ReferenceDecl) return; - LookupResult Result(S, DRE->getNameInfo(), Sema::LookupOrdinaryName, - Sema::NotForRedeclaration); + unsigned diag = isReferenceType + ? diag::warn_uninit_self_reference_in_reference_init + : diag::warn_uninit_self_reference_in_init; S.DiagRuntimeBehavior(DRE->getLocStart(), DRE, - S.PDiag(diag::warn_uninit_self_reference_in_init) - << Result.getLookupName() + S.PDiag(diag) + << DRE->getNameInfo().getName() << OrigDecl->getLocation() << DRE->getSourceRange()); } }; -} -/// CheckSelfReference - Warns if OrigDecl is used in expression E. -void Sema::CheckSelfReference(Decl* OrigDecl, Expr *E) { - SelfReferenceChecker(*this, OrigDecl).HandleExpr(E); + /// CheckSelfReference - Warns if OrigDecl is used in expression E. + static void CheckSelfReference(Sema &S, Decl* OrigDecl, Expr *E, + bool DirectInit) { + // Parameters arguments are occassionially constructed with itself, + // for instance, in recursive functions. Skip them. + if (isa<ParmVarDecl>(OrigDecl)) + return; + + E = E->IgnoreParens(); + + // Skip checking T a = a where T is not a record or reference type. + // Doing so is a way to silence uninitialized warnings. + if (!DirectInit && !cast<VarDecl>(OrigDecl)->getType()->isRecordType()) + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) + if (ICE->getCastKind() == CK_LValueToRValue) + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) + if (DRE->getDecl() == OrigDecl) + return; + + SelfReferenceChecker(S, OrigDecl).Visit(E); + } } /// AddInitializerToDecl - Adds the initializer Init to the @@ -6311,15 +6541,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } - // Check for self-references within variable initializers. - // Variables declared within a function/method body (except for references) - // are handled by a dataflow analysis. - // Record types initialized by initializer list are handled here. - // Initialization by constructors are handled in TryConstructorInitialization. - if ((!VDecl->hasLocalStorage() || VDecl->getType()->isReferenceType()) && - (isa<InitListExpr>(Init) || !VDecl->getType()->isRecordType())) - CheckSelfReference(RealDecl, Init); - ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. @@ -6495,8 +6716,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, } InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, Args,NumArgs), - &DclT); + MultiExprArg(Args, NumArgs), &DclT); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; @@ -6505,6 +6725,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, Init = Result.takeAs<Expr>(); } + // Check for self-references within variable initializers. + // Variables declared within a function/method body (except for references) + // are handled by a dataflow analysis. + if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() || + VDecl->getType()->isReferenceType()) { + CheckSelfReference(*this, RealDecl, Init, DirectInit); + } + // If the type changed, it means we had an incomplete type that was // completed by the initializer. For example: // int ary[] = { 1, 3, 5 }; @@ -6515,9 +6743,28 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, // Check any implicit conversions within the expression. CheckImplicitConversions(Init, VDecl->getLocation()); - if (!VDecl->isInvalidDecl()) + if (!VDecl->isInvalidDecl()) { checkUnsafeAssigns(VDecl->getLocation(), VDecl->getType(), Init); + if (VDecl->hasAttr<BlocksAttr>()) + checkRetainCycles(VDecl, Init); + + // It is safe to assign a weak reference into a strong variable. + // Although this code can still have problems: + // id x = self.weakProp; + // id y = self.weakProp; + // we do not warn to warn spuriously when 'x' and 'y' are on separate + // paths through the function. This should be revisited if + // -Wrepeated-use-of-weak is made flow-sensitive. + if (VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + Init->getLocStart()); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->markSafeWeakUse(Init); + } + } + Init = MaybeCreateExprWithCleanups(Init); // Attach the initializer to the decl. VDecl->setInit(Init); @@ -6758,8 +7005,10 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, AbstractVariableType)) Var->setInvalidDecl(); if (!Type->isDependentType() && !Var->isInvalidDecl() && - Var->getStorageClass() == SC_PrivateExtern) + Var->getStorageClass() == SC_PrivateExtern) { Diag(Var->getLocation(), diag::warn_private_extern); + Diag(Var->getLocation(), diag::note_private_extern); + } return; @@ -6881,8 +7130,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, = InitializationKind::CreateDefault(Var->getLocation()); InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); - ExprResult Init = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, 0, 0)); + ExprResult Init = InitSeq.Perform(*this, Entity, Kind, MultiExprArg()); if (Init.isInvalid()) Var->setInvalidDecl(); else if (Init.get()) { @@ -6957,11 +7205,22 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { } } + if (var->isThisDeclarationADefinition() && + var->getLinkage() == ExternalLinkage) { + // Find a previous declaration that's not a definition. + VarDecl *prev = var->getPreviousDecl(); + while (prev && prev->isThisDeclarationADefinition()) + prev = prev->getPreviousDecl(); + + if (!prev) + Diag(var->getLocation(), diag::warn_missing_variable_declarations) << var; + } + // All the following checks are C++ only. if (!getLangOpts().CPlusPlus) return; - QualType baseType = Context.getBaseElementType(var->getType()); - if (baseType->isDependentType()) return; + QualType type = var->getType(); + if (type->isDependentType()) return; // __block variables might require us to capture a copy-initializer. if (var->hasAttr<BlocksAttr>()) { @@ -6970,8 +7229,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // Regardless, we don't want to ignore array nesting when // constructing this copy. - QualType type = var->getType(); - if (type->isStructureOrClassType()) { SourceLocation poi = var->getLocation(); Expr *varRef =new (Context) DeclRefExpr(var, false, type, VK_LValue, poi); @@ -6989,8 +7246,10 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { Expr *Init = var->getInit(); bool IsGlobal = var->hasGlobalStorage() && !var->isStaticLocal(); + QualType baseType = Context.getBaseElementType(type); - if (!var->getDeclContext()->isDependentContext() && Init) { + if (!var->getDeclContext()->isDependentContext() && + Init && !Init->isValueDependent()) { if (IsGlobal && !var->isConstexpr() && getDiagnostics().getDiagnosticLevel(diag::warn_global_constructor, var->getLocation()) @@ -7178,7 +7437,7 @@ void Sema::ActOnDocumentableDecls(Decl **Group, unsigned NumDecls) { // the lookahead in the lexer: we've consumed the semicolon and looked // ahead through comments. for (unsigned i = 0; i != NumDecls; ++i) - Context.getCommentForDecl(Group[i]); + Context.getCommentForDecl(Group[i], &PP); } } @@ -7450,6 +7709,9 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, unsigned DiagID; // unused DS.SetTypeSpecType(DeclSpec::TST_int, FTI.ArgInfo[i].IdentLoc, PrevSpec, DiagID); + // Use the identifier location for the type source range. + DS.SetRangeStart(FTI.ArgInfo[i].IdentLoc); + DS.SetRangeEnd(FTI.ArgInfo[i].IdentLoc); Declarator ParamD(DS, Declarator::KNRTypeListContext); ParamD.SetIdentifier(FTI.ArgInfo[i].Ident, FTI.ArgInfo[i].IdentLoc); FTI.ArgInfo[i].Param = ActOnParamDeclarator(S, ParamD); @@ -7464,8 +7726,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { Scope *ParentScope = FnBodyScope->getParent(); D.setFunctionDefinitionKind(FDK_Definition); - Decl *DP = HandleDeclarator(ParentScope, D, - MultiTemplateParamsArg(*this)); + Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg()); return ActOnStartOfFunctionDef(FnBodyScope, DP); } @@ -7707,7 +7968,7 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { } Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { - return ActOnFinishFunctionBody(D, move(BodyArg), false); + return ActOnFinishFunctionBody(D, BodyArg, false); } Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, @@ -7765,22 +8026,16 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (Body) computeNRVO(Body, getCurFunction()); } - if (getCurFunction()->ObjCShouldCallSuperDealloc) { - Diag(MD->getLocEnd(), diag::warn_objc_missing_super_dealloc); - getCurFunction()->ObjCShouldCallSuperDealloc = false; - } - if (getCurFunction()->ObjCShouldCallSuperFinalize) { - Diag(MD->getLocEnd(), diag::warn_objc_missing_super_finalize); - getCurFunction()->ObjCShouldCallSuperFinalize = false; + if (getCurFunction()->ObjCShouldCallSuper) { + Diag(MD->getLocEnd(), diag::warn_objc_missing_super_call) + << MD->getSelector().getAsString(); + getCurFunction()->ObjCShouldCallSuper = false; } } else { return 0; } - assert(!getCurFunction()->ObjCShouldCallSuperDealloc && - "This should only be set for ObjC methods, which should have been " - "handled in the block above."); - assert(!getCurFunction()->ObjCShouldCallSuperFinalize && + assert(!getCurFunction()->ObjCShouldCallSuper && "This should only be set for ObjC methods, which should have been " "handled in the block above."); @@ -7916,13 +8171,28 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, bool Error = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, Dummy, DiagID); (void)Error; // Silence warning. assert(!Error && "Error setting up implicit decl!"); + SourceLocation NoLoc; Declarator D(DS, Declarator::BlockContext); - D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, false, - SourceLocation(), 0, 0, 0, true, - SourceLocation(), SourceLocation(), - SourceLocation(), SourceLocation(), - EST_None, SourceLocation(), - 0, 0, 0, 0, Loc, Loc, D), + D.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/false, + /*IsAmbiguous=*/false, + /*RParenLoc=*/NoLoc, + /*ArgInfo=*/0, + /*NumArgs=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*MutableLoc=*/NoLoc, + EST_None, + /*ESpecLoc=*/NoLoc, + /*Exceptions=*/0, + /*ExceptionRanges=*/0, + /*NumExceptions=*/0, + /*NoexceptExpr=*/0, + Loc, Loc, D), DS.getAttributes(), SourceLocation()); D.SetIdentifier(&II, Loc); @@ -8071,6 +8341,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, switch (D.getDeclSpec().getTypeSpecType()) { case TST_enum: case TST_struct: + case TST_interface: case TST_union: case TST_class: { TagDecl *tagFromDeclSpec = cast<TagDecl>(D.getDeclSpec().getRepAsDecl()); @@ -8146,6 +8417,29 @@ bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, return false; } +/// \brief Get diagnostic %select index for tag kind for +/// redeclaration diagnostic message. +/// WARNING: Indexes apply to particular diagnostics only! +/// +/// \returns diagnostic %select index. +static unsigned getRedeclDiagFromTagKind(TagTypeKind Tag) { + switch (Tag) { + case TTK_Struct: return 0; + case TTK_Interface: return 1; + case TTK_Class: return 2; + default: llvm_unreachable("Invalid tag kind for redecl diagnostic!"); + } +} + +/// \brief Determine if tag kind is a class-key compatible with +/// class for redeclaration (class, struct, or __interface). +/// +/// \returns true iff the tag kind is compatible. +static bool isClassCompatTagKind(TagTypeKind Tag) +{ + return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface; +} + /// \brief Determine whether a tag with a given kind is acceptable /// as a redeclaration of the given tag declaration. /// @@ -8168,12 +8462,11 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, // struct class-key shall be used to refer to a class (clause 9) // declared using the class or struct class-key. TagTypeKind OldTag = Previous->getTagKind(); - if (!isDefinition || (NewTag != TTK_Class && NewTag != TTK_Struct)) + if (!isDefinition || !isClassCompatTagKind(NewTag)) if (OldTag == NewTag) return true; - if ((OldTag == TTK_Struct || OldTag == TTK_Class) && - (NewTag == TTK_Struct || NewTag == TTK_Class)) { + if (isClassCompatTagKind(OldTag) && isClassCompatTagKind(NewTag)) { // Warn about the struct/class tag mismatch. bool isTemplate = false; if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Previous)) @@ -8183,7 +8476,8 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, // In a template instantiation, do not offer fix-its for tag mismatches // since they usually mess up the template instead of fixing the problem. Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) - << (NewTag == TTK_Class) << isTemplate << &Name; + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name + << getRedeclDiagFromTagKind(OldTag); return true; } @@ -8202,13 +8496,13 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, if (!previousMismatch) { previousMismatch = true; Diag(NewTagLoc, diag::warn_struct_class_previous_tag_mismatch) - << (NewTag == TTK_Class) << isTemplate << &Name; + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name + << getRedeclDiagFromTagKind(I->getTagKind()); } Diag(I->getInnerLocStart(), diag::note_struct_class_suggestion) - << (NewTag == TTK_Class) + << getRedeclDiagFromTagKind(NewTag) << FixItHint::CreateReplacement(I->getInnerLocStart(), - NewTag == TTK_Class? - "class" : "struct"); + TypeWithKeyword::getTagTypeKindName(NewTag)); } } return true; @@ -8224,16 +8518,16 @@ bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, } Diag(NewTagLoc, diag::warn_struct_class_tag_mismatch) - << (NewTag == TTK_Class) - << isTemplate << &Name; + << getRedeclDiagFromTagKind(NewTag) << isTemplate << &Name + << getRedeclDiagFromTagKind(OldTag); Diag(Redecl->getLocation(), diag::note_previous_use); // If there is a previous defintion, suggest a fix-it. if (Previous->getDefinition()) { Diag(NewTagLoc, diag::note_struct_class_suggestion) - << (Redecl->getTagKind() == TTK_Class) + << getRedeclDiagFromTagKind(Redecl->getTagKind()) << FixItHint::CreateReplacement(SourceRange(NewTagLoc), - Redecl->getTagKind() == TTK_Class? "class" : "struct"); + TypeWithKeyword::getTagTypeKindName(Redecl->getTagKind())); } return true; @@ -8276,7 +8570,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, (SS.isNotEmpty() && TUK != TUK_Reference)) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(KWLoc, NameLoc, SS, - TemplateParameterLists.get(), + TemplateParameterLists.data(), TemplateParameterLists.size(), TUK == TUK_Friend, isExplicitSpecialization, @@ -8293,8 +8587,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SS, Name, NameLoc, Attr, TemplateParams, AS, ModulePrivateLoc, - TemplateParameterLists.size() - 1, - (TemplateParameterList**) TemplateParameterLists.release()); + TemplateParameterLists.size()-1, + TemplateParameterLists.data()); return Result.get(); } else { // The "template<>" header is extraneous. @@ -8843,7 +9137,7 @@ CreateNewDecl: if (TemplateParameterLists.size() > 0) { New->setTemplateParameterListsInfo(Context, TemplateParameterLists.size(), - (TemplateParameterList**) TemplateParameterLists.release()); + TemplateParameterLists.data()); } } else @@ -9298,12 +9592,15 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (!InvalidDecl && T->isVariablyModifiedType()) { bool SizeIsNegative; llvm::APSInt Oversized; - QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context, - SizeIsNegative, - Oversized); - if (!FixedTy.isNull()) { + + TypeSourceInfo *FixedTInfo = + TryToFixInvalidVariablyModifiedTypeSourceInfo(TInfo, Context, + SizeIsNegative, + Oversized); + if (FixedTInfo) { Diag(Loc, diag::warn_illegal_constant_array_size); - T = FixedTy; + TInfo = FixedTInfo; + T = FixedTInfo->getType(); } else { if (SizeIsNegative) Diag(Loc, diag::err_typecheck_negative_array_size); @@ -9460,12 +9757,12 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { return false; } -/// If the given constructor is user-provided, produce a diagnostic explaining +/// If the given constructor is user-declared, produce a diagnostic explaining /// that it makes the class non-trivial. -static bool DiagnoseNontrivialUserProvidedCtor(Sema &S, QualType QT, +static bool diagnoseNonTrivialUserDeclaredCtor(Sema &S, QualType QT, CXXConstructorDecl *CD, Sema::CXXSpecialMember CSM) { - if (!CD->isUserProvided()) + if (CD->isImplicit()) return false; SourceLocation CtorLoc = CD->getLocation(); @@ -9488,17 +9785,17 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { if (RD->hasUserDeclaredConstructor()) { typedef CXXRecordDecl::ctor_iterator ctor_iter; for (ctor_iter CI = RD->ctor_begin(), CE = RD->ctor_end(); CI != CE; ++CI) - if (DiagnoseNontrivialUserProvidedCtor(*this, QT, *CI, member)) + if (diagnoseNonTrivialUserDeclaredCtor(*this, QT, *CI, member)) return; - // No user-provided constructors; look for constructor templates. + // 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 && DiagnoseNontrivialUserProvidedCtor(*this, QT, CD, member)) + if (CD && diagnoseNonTrivialUserDeclaredCtor(*this, QT, CD, member)) return; } } @@ -10025,42 +10322,6 @@ void Sema::ActOnFields(Scope* S, Convs->setAccess(I, (*I)->getAccess()); if (!CXXRecord->isDependentType()) { - // Objective-C Automatic Reference Counting: - // If a class has a non-static data member of Objective-C pointer - // type (or array thereof), it is a non-POD type and its - // default constructor (if any), copy constructor, copy assignment - // operator, and destructor are non-trivial. - // - // This rule is also handled by CXXRecordDecl::completeDefinition(). - // However, here we check whether this particular class is only - // non-POD because of the presence of an Objective-C pointer member. - // If so, objects of this type cannot be shared between code compiled - // with ARC and code compiled with manual retain/release. - if (getLangOpts().ObjCAutoRefCount && - CXXRecord->hasObjectMember() && - CXXRecord->getLinkage() == ExternalLinkage) { - if (CXXRecord->isPOD()) { - Diag(CXXRecord->getLocation(), - diag::warn_arc_non_pod_class_with_object_member) - << CXXRecord; - } else { - // FIXME: Fix-Its would be nice here, but finding a good location - // for them is going to be tricky. - if (CXXRecord->hasTrivialCopyConstructor()) - Diag(CXXRecord->getLocation(), - diag::warn_arc_trivial_member_function_with_object_member) - << CXXRecord << 0; - if (CXXRecord->hasTrivialCopyAssignment()) - Diag(CXXRecord->getLocation(), - diag::warn_arc_trivial_member_function_with_object_member) - << CXXRecord << 1; - if (CXXRecord->hasTrivialDestructor()) - Diag(CXXRecord->getLocation(), - diag::warn_arc_trivial_member_function_with_object_member) - << CXXRecord << 2; - } - } - // Adjust user-defined destructor exception spec. if (getLangOpts().CPlusPlus0x && CXXRecord->hasUserDeclaredDestructor()) @@ -10092,7 +10353,7 @@ void Sema::ActOnFields(Scope* S, // class subobject has more than one final overrider the // program is ill-formed. Diag(Record->getLocation(), diag::err_multiple_final_overriders) - << (NamedDecl *)M->first << Record; + << (const NamedDecl *)M->first << Record; Diag(M->first->getLocation(), diag::note_overridden_virtual_function); for (OverridingMethods::overriding_iterator @@ -10100,7 +10361,7 @@ void Sema::ActOnFields(Scope* S, OMEnd = SO->second.end(); OM != OMEnd; ++OM) Diag(OM->Method->getLocation(), diag::note_final_overrider) - << (NamedDecl *)M->first << OM->Method->getParent(); + << (const NamedDecl *)M->first << OM->Method->getParent(); Record->setInvalidDecl(); } @@ -10461,57 +10722,6 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, return New; } -// Emits a warning if every element in the enum is the same value and if -// every element is initialized with a integer or boolean literal. -static void CheckForUniqueEnumValues(Sema &S, Decl **Elements, - unsigned NumElements, EnumDecl *Enum, - QualType EnumType) { - if (S.Diags.getDiagnosticLevel(diag::warn_identical_enum_values, - Enum->getLocation()) == - DiagnosticsEngine::Ignored) - return; - - if (NumElements < 2) - return; - - if (!Enum->getIdentifier()) - return; - - llvm::APSInt FirstVal; - - for (unsigned i = 0; i != NumElements; ++i) { - EnumConstantDecl *ECD = cast_or_null<EnumConstantDecl>(Elements[i]); - if (!ECD) - return; - - Expr *InitExpr = ECD->getInitExpr(); - if (!InitExpr) - return; - InitExpr = InitExpr->IgnoreImpCasts(); - if (!isa<IntegerLiteral>(InitExpr) && !isa<CXXBoolLiteralExpr>(InitExpr)) - return; - - if (i == 0) { - FirstVal = ECD->getInitVal(); - continue; - } - - if (!llvm::APSInt::isSameValue(FirstVal, ECD->getInitVal())) - return; - } - - S.Diag(Enum->getLocation(), diag::warn_identical_enum_values) - << EnumType << FirstVal.toString(10) - << Enum->getSourceRange(); - - EnumConstantDecl *Last = cast<EnumConstantDecl>(Elements[NumElements - 1]), - *Next = cast<EnumConstantDecl>(Elements[NumElements - 2]); - - S.Diag(Last->getLocation(), diag::note_identical_enum_values) - << FixItHint::CreateReplacement(Last->getInitExpr()->getSourceRange(), - Next->getName()); -} - void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, SourceLocation RBraceLoc, Decl *EnumDeclX, Decl **Elements, unsigned NumElements, @@ -10734,8 +10944,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // it needs to go into the function scope. if (InFunctionDeclarator) DeclsInPrototypeScope.push_back(Enum); - - CheckForUniqueEnumValues(*this, Elements, NumElements, Enum, EnumType); } Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, @@ -10834,10 +11042,6 @@ Decl *Sema::getObjCDeclContext() const { } AvailabilityResult Sema::getCurContextAvailability() const { - const Decl *D = cast<Decl>(getCurLexicalContext()); - // A category implicitly has the availability of the interface. - if (const ObjCCategoryDecl *CatD = dyn_cast<ObjCCategoryDecl>(D)) - D = CatD->getClassInterface(); - + const Decl *D = cast<Decl>(getCurObjCLexicalContext()); return D->getAvailability(); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index caa7b2f..e326a20 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -415,14 +415,19 @@ static void checkAttrArgsAreLockableObjs(Sema &S, Decl *D, } if (StringLiteral *StrLit = dyn_cast<StringLiteral>(ArgExp)) { - // Ignore empty strings without warnings - if (StrLit->getLength() == 0) + if (StrLit->getLength() == 0 || + StrLit->getString() == StringRef("*")) { + // Pass empty strings to the analyzer without warnings. + // Treat "*" as the universal lock. + Args.push_back(ArgExp); continue; + } // We allow constant strings to be used as a placeholder for expressions // that are not valid C++ syntax, but warn that they are ignored. S.Diag(Attr.getLoc(), diag::warn_thread_attribute_ignored) << Attr.getName(); + Args.push_back(ArgExp); continue; } @@ -859,7 +864,6 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, if (!checkAttributeNumArgs(S, Attr, 1)) return; - Expr *Arg = Attr.getArg(0); if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) { S.Diag(Attr.getLoc(), diag::warn_thread_attribute_wrong_decl_type) @@ -867,9 +871,6 @@ static void handleLockReturnedAttr(Sema &S, Decl *D, return; } - if (Arg->isTypeDependent()) - return; - // check that the argument is lockable object SmallVector<Expr*, 1> Args; checkAttrArgsAreLockableObjs(S, D, Attr, Args); @@ -962,7 +963,8 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { // If the alignment is less than or equal to 8 bits, the packed attribute // has no effect. - if (!FD->getType()->isIncompleteType() && + if (!FD->getType()->isDependentType() && + !FD->getType()->isIncompleteType() && S.Context.getTypeAlign(FD->getType()) <= 8) S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << Attr.getName() << FD->getType(); @@ -973,8 +975,8 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (TagDecl *TD = dyn_cast<TagDecl>(D)) - TD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context)); + if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) + RD->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context)); else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -1522,6 +1524,20 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) { Str->getString())); } +static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // Check the attribute arguments. + if (!checkAttributeNumArgs(S, Attr, 0)) + return; + + if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) + << Attr.getName() << ExpectedFunctionOrMethod; + return; + } + + D->addAttr(::new (S.Context) MinSizeAttr(Attr.getRange(), S.Context)); +} + static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. if (!checkAttributeNumArgs(S, Attr, 0)) @@ -2268,16 +2284,14 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) { } if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { QualType T = TD->getUnderlyingType(); - if (!T->isPointerType() || - !T->getAs<PointerType>()->getPointeeType()->isRecordType()) { + if (!T->isCARCBridgableType()) { S.Diag(TD->getLocation(), diag::err_nsobject_attribute); return; } } else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) { QualType T = PD->getType(); - if (!T->isPointerType() || - !T->getAs<PointerType>()->getPointeeType()->isRecordType()) { + if (!T->isCARCBridgableType()) { S.Diag(PD->getLocation(), diag::err_nsobject_attribute); return; } @@ -3583,7 +3597,12 @@ static void handleCallConvAttr(Sema &S, Decl *D, const AttributeList &Attr) { } D->addAttr(::new (S.Context) PcsAttr(Attr.getRange(), S.Context, PCS)); + return; } + case AttributeList::AT_PnaclCall: + D->addAttr(::new (S.Context) PnaclCallAttr(Attr.getRange(), S.Context)); + return; + default: llvm_unreachable("unexpected attribute kind"); } @@ -3636,9 +3655,17 @@ bool Sema::CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC) { Diag(attr.getLoc(), diag::err_invalid_pcs); return true; } + case AttributeList::AT_PnaclCall: CC = CC_PnaclCall; break; default: llvm_unreachable("unexpected attribute kind"); } + const TargetInfo &TI = Context.getTargetInfo(); + TargetInfo::CallingConvCheckResult A = TI.checkCallingConvention(CC); + if (A == TargetInfo::CCCR_Warning) { + Diag(attr.getLoc(), diag::warn_cconv_ignored) << attr.getName(); + CC = TI.getDefaultCallingConv(); + } + return false; } @@ -3878,11 +3905,11 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) returnType = MD->getResultType(); - else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) - returnType = PD->getType(); else if (S.getLangOpts().ObjCAutoRefCount && hasDeclarator(D) && (Attr.getKind() == AttributeList::AT_NSReturnsRetained)) return; // ignore: was handled as a type attribute + else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) + returnType = PD->getType(); else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) returnType = FD->getResultType(); else { @@ -3971,6 +3998,33 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, ::new (S.Context) ObjCReturnsInnerPointerAttr(attr.getRange(), S.Context)); } +static void handleObjCRequiresSuperAttr(Sema &S, Decl *D, + const AttributeList &attr) { + SourceLocation loc = attr.getLoc(); + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); + + if (!method) { + S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type) + << SourceRange(loc, loc) << attr.getName() << ExpectedMethod; + return; + } + DeclContext *DC = method->getDeclContext(); + if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) { + S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) + << attr.getName() << 0; + S.Diag(PDecl->getLocation(), diag::note_protocol_decl); + return; + } + if (method->getMethodFamily() == OMF_dealloc) { + S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol) + << attr.getName() << 1; + return; + } + + method->addAttr( + ::new (S.Context) ObjCRequiresSuperAttr(attr.getRange(), S.Context)); +} + /// Handle cf_audited_transfer and cf_unknown_transfer. static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) { if (!isa<FunctionDecl>(D)) { @@ -4149,19 +4203,21 @@ static void handleUuidAttr(Sema &S, Decl *D, const AttributeList &Attr) { } static void handleInheritanceAttr(Sema &S, Decl *D, const AttributeList &Attr) { - if (S.LangOpts.MicrosoftExt) { - AttributeList::Kind Kind = Attr.getKind(); - if (Kind == AttributeList::AT_SingleInheritance) - D->addAttr( - ::new (S.Context) SingleInheritanceAttr(Attr.getRange(), S.Context)); - else if (Kind == AttributeList::AT_MultipleInheritance) - D->addAttr( - ::new (S.Context) MultipleInheritanceAttr(Attr.getRange(), S.Context)); - else if (Kind == AttributeList::AT_VirtualInheritance) - D->addAttr( - ::new (S.Context) VirtualInheritanceAttr(Attr.getRange(), S.Context)); - } else + if (!S.LangOpts.MicrosoftExt) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + + AttributeList::Kind Kind = Attr.getKind(); + if (Kind == AttributeList::AT_SingleInheritance) + D->addAttr( + ::new (S.Context) SingleInheritanceAttr(Attr.getRange(), S.Context)); + else if (Kind == AttributeList::AT_MultipleInheritance) + D->addAttr( + ::new (S.Context) MultipleInheritanceAttr(Attr.getRange(), S.Context)); + else if (Kind == AttributeList::AT_VirtualInheritance) + D->addAttr( + ::new (S.Context) VirtualInheritanceAttr(Attr.getRange(), S.Context)); } static void handlePortabilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -4246,6 +4302,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ExtVectorType: handleExtVectorTypeAttr(S, scope, D, Attr); break; + case AttributeList::AT_MinSize: + handleMinSizeAttr(S, D, Attr); + break; case AttributeList::AT_Format: handleFormatAttr (S, D, Attr); break; case AttributeList::AT_FormatArg: handleFormatArgAttr (S, D, Attr); break; case AttributeList::AT_CUDAGlobal: handleGlobalAttr (S, D, Attr); break; @@ -4278,6 +4337,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ObjCReturnsInnerPointer: handleObjCReturnsInnerPointerAttr(S, D, Attr); break; + case AttributeList::AT_ObjCRequiresSuper: + handleObjCRequiresSuperAttr(S, D, Attr); break; + case AttributeList::AT_NSBridged: handleNSBridgedAttr(S, scope, D, Attr); break; @@ -4360,6 +4422,7 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ThisCall: case AttributeList::AT_Pascal: case AttributeList::AT_Pcs: + case AttributeList::AT_PnaclCall: handleCallConvAttr(S, D, Attr); break; case AttributeList::AT_OpenCLKernel: @@ -4774,18 +4837,25 @@ static bool isDeclDeprecated(Decl *D) { static void DoEmitDeprecationWarning(Sema &S, const NamedDecl *D, StringRef Message, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCPropery) { DeclarationName Name = D->getDeclName(); if (!Message.empty()) { S.Diag(Loc, diag::warn_deprecated_message) << Name << Message; S.Diag(D->getLocation(), isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at : diag::note_previous_decl) << Name; + if (ObjCPropery) + S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) + << ObjCPropery->getDeclName() << 0; } else if (!UnknownObjCClass) { S.Diag(Loc, diag::warn_deprecated) << D->getDeclName(); S.Diag(D->getLocation(), isa<ObjCMethodDecl>(D) ? diag::note_method_declared_at : diag::note_previous_decl) << Name; + if (ObjCPropery) + S.Diag(ObjCPropery->getLocation(), diag::note_property_attribute) + << ObjCPropery->getDeclName() << 0; } else { S.Diag(Loc, diag::warn_deprecated_fwdclass_message) << Name; S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class); @@ -4800,16 +4870,19 @@ void Sema::HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, DD.Triggered = true; DoEmitDeprecationWarning(*this, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc, - DD.getUnknownObjCClass()); + DD.getUnknownObjCClass(), + DD.getObjCProperty()); } void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, SourceLocation Loc, - const ObjCInterfaceDecl *UnknownObjCClass) { + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty) { // Delay if we're currently parsing a declaration. if (DelayedDiagnostics.shouldDelayDiagnostics()) { DelayedDiagnostics.add(DelayedDiagnostic::makeDeprecation(Loc, D, UnknownObjCClass, + ObjCProperty, Message)); return; } @@ -4817,5 +4890,5 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message, // Otherwise, don't warn if our current context is deprecated. if (isDeclDeprecated(cast<Decl>(getCurLexicalContext()))) return; - DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass); + DoEmitDeprecationWarning(*this, D, Message, Loc, UnknownObjCClass, ObjCProperty); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index eeac9b8..16eddf8 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -246,8 +246,7 @@ Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), EqualLoc); InitializationSequence InitSeq(*this, Entity, Kind, &Arg, 1); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, &Arg, 1)); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Arg); if (Result.isInvalid()) return true; Arg = Result.takeAs<Expr>(); @@ -374,10 +373,10 @@ void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { } } -// MergeCXXFunctionDecl - Merge two declarations of the same C++ -// function, once we already know that they have the same -// type. Subroutine of MergeFunctionDecl. Returns true if there was an -// error, false otherwise. +/// MergeCXXFunctionDecl - Merge two declarations of the same C++ +/// function, once we already know that they have the same +/// type. Subroutine of MergeFunctionDecl. Returns true if there was an +/// error, false otherwise. bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S) { bool Invalid = false; @@ -676,6 +675,20 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, return true; } +/// \brief Get diagnostic %select index for tag kind for +/// record diagnostic message. +/// WARNING: Indexes apply to particular diagnostics only! +/// +/// \returns diagnostic %select index. +static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) { + switch (Tag) { + case TTK_Struct: return 0; + case TTK_Interface: return 1; + case TTK_Class: return 2; + default: llvm_unreachable("Invalid tag kind for record diagnostic!"); + } +} + // CheckConstexprFunctionDecl - Check whether a function declaration satisfies // the requirements of a constexpr function definition or a constexpr // constructor definition. If so, return true. If not, produce appropriate @@ -692,8 +705,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { const CXXRecordDecl *RD = MD->getParent(); if (RD->getNumVBases()) { Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) - << isa<CXXConstructorDecl>(NewFD) << RD->isStruct() - << RD->getNumVBases(); + << isa<CXXConstructorDecl>(NewFD) + << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) Diag(I->getLocStart(), @@ -1005,6 +1018,41 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, return false; } +/// \brief Determine whether the given class is a base class of the given +/// class, including looking at dependent bases. +static bool findCircularInheritance(const CXXRecordDecl *Class, + const CXXRecordDecl *Current) { + SmallVector<const CXXRecordDecl*, 8> Queue; + + Class = Class->getCanonicalDecl(); + while (true) { + for (CXXRecordDecl::base_class_const_iterator I = Current->bases_begin(), + E = Current->bases_end(); + I != E; ++I) { + CXXRecordDecl *Base = I->getType()->getAsCXXRecordDecl(); + if (!Base) + continue; + + Base = Base->getDefinition(); + if (!Base) + continue; + + if (Base->getCanonicalDecl() == Class) + return true; + + Queue.push_back(Base); + } + + if (Queue.empty()) + return false; + + Current = Queue.back(); + Queue.pop_back(); + } + + return false; +} + /// \brief Check the validity of a C++ base class specifier. /// /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics @@ -1031,13 +1079,32 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, << TInfo->getTypeLoc().getSourceRange(); EllipsisLoc = SourceLocation(); } - - if (BaseType->isDependentType()) + + SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + + if (BaseType->isDependentType()) { + // Make sure that we don't have circular inheritance among our dependent + // bases. For non-dependent bases, the check for completeness below handles + // this. + if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) { + if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() || + ((BaseDecl = BaseDecl->getDefinition()) && + findCircularInheritance(Class, BaseDecl))) { + Diag(BaseLoc, diag::err_circular_inheritance) + << BaseType << Context.getTypeDeclType(Class); + + if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl()) + Diag(BaseDecl->getLocation(), diag::note_previous_decl) + << BaseType; + + return 0; + } + } + return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, Class->getTagKind() == TTK_Class, Access, TInfo, EllipsisLoc); - - SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); + } // Base specifiers must be record types. if (!BaseType->isRecordType()) { @@ -1165,10 +1232,21 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // Okay, add this new base class. KnownBase = Bases[idx]; Bases[NumGoodBases++] = Bases[idx]; - if (const RecordType *Record = NewBaseType->getAs<RecordType>()) - if (const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl())) - if (RD->hasAttr<WeakAttr>()) - Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context)); + if (const RecordType *Record = NewBaseType->getAs<RecordType>()) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); + if (Class->isInterface() && + (!RD->isInterface() || + KnownBase->getAccessSpecifier() != AS_public)) { + // The Microsoft extension __interface does not permit bases that + // are not themselves public interfaces. + Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface) + << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName() + << RD->getSourceRange(); + Invalid = true; + } + if (RD->hasAttr<WeakAttr>()) + Class->addAttr(::new (Context) WeakAttr(SourceRange(), Context)); + } } } @@ -1407,6 +1485,9 @@ bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, /// CheckOverrideControl - Check C++11 override control semantics. void Sema::CheckOverrideControl(Decl *D) { + if (D->isInvalidDecl()) + return; + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D); // Do we know which functions this declaration might be overriding? @@ -1496,6 +1577,50 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, bool isFunc = D.isDeclarationOfFunction(); + if (cast<CXXRecordDecl>(CurContext)->isInterface()) { + // The Microsoft extension __interface only permits public member functions + // and prohibits constructors, destructors, operators, non-public member + // functions, static methods and data members. + unsigned InvalidDecl; + bool ShowDeclName = true; + if (!isFunc) + InvalidDecl = (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) ? 0 : 1; + else if (AS != AS_public) + InvalidDecl = 2; + else if (DS.getStorageClassSpec() == DeclSpec::SCS_static) + InvalidDecl = 3; + else switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + InvalidDecl = 4; + ShowDeclName = false; + break; + + case DeclarationName::CXXDestructorName: + InvalidDecl = 5; + ShowDeclName = false; + break; + + case DeclarationName::CXXOperatorName: + case DeclarationName::CXXConversionFunctionName: + InvalidDecl = 6; + break; + + default: + InvalidDecl = 0; + break; + } + + if (InvalidDecl) { + if (ShowDeclName) + Diag(Loc, diag::err_invalid_member_in_interface) + << (InvalidDecl-1) << Name; + else + Diag(Loc, diag::err_invalid_member_in_interface) + << (InvalidDecl-1) << ""; + return 0; + } + } + // C++ 9.2p6: A member shall not be declared to have automatic storage // duration (auto, register) or with the extern storage-class-specifier. // C++ 7.1.1p8: The mutable specifier can be applied only to names of class @@ -1548,7 +1673,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // Member field could not be with "template" keyword. // So TemplateParameterLists should be empty in this case. if (TemplateParameterLists.size()) { - TemplateParameterList* TemplateParams = TemplateParameterLists.get()[0]; + TemplateParameterList* TemplateParams = TemplateParameterLists[0]; if (TemplateParams->size()) { // There is no such thing as a member field template. Diag(D.getIdentifierLoc(), diag::err_template_member) @@ -1588,7 +1713,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, } else { assert(InitStyle == ICIS_NoInit); - Member = HandleDeclarator(S, D, move(TemplateParameterLists)); + Member = HandleDeclarator(S, D, TemplateParameterLists); if (!Member) { return 0; } @@ -1662,6 +1787,99 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, return Member; } +namespace { + class UninitializedFieldVisitor + : public EvaluatedExprVisitor<UninitializedFieldVisitor> { + Sema &S; + ValueDecl *VD; + public: + typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited; + UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context), + S(S), VD(VD) { + } + + void HandleExpr(Expr *E) { + if (!E) return; + + // Expressions like x(x) sometimes lack the surrounding expressions + // but need to be checked anyways. + HandleValue(E); + Visit(E); + } + + void HandleValue(Expr *E) { + E = E->IgnoreParens(); + + if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + if (isa<EnumConstantDecl>(ME->getMemberDecl())) + return; + Expr *Base = E; + while (isa<MemberExpr>(Base)) { + ME = dyn_cast<MemberExpr>(Base); + if (VarDecl *VarD = dyn_cast<VarDecl>(ME->getMemberDecl())) + if (VarD->hasGlobalStorage()) + return; + Base = ME->getBase(); + } + + if (VD == ME->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; + } + } + + if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { + HandleValue(CO->getTrueExpr()); + HandleValue(CO->getFalseExpr()); + return; + } + + if (BinaryConditionalOperator *BCO = + dyn_cast<BinaryConditionalOperator>(E)) { + HandleValue(BCO->getCommon()); + HandleValue(BCO->getFalseExpr()); + return; + } + + if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { + switch (BO->getOpcode()) { + default: + return; + case(BO_PtrMemD): + case(BO_PtrMemI): + HandleValue(BO->getLHS()); + return; + case(BO_Comma): + HandleValue(BO->getRHS()); + return; + } + } + } + + void VisitImplicitCastExpr(ImplicitCastExpr *E) { + if (E->getCastKind() == CK_LValueToRValue) + HandleValue(E->getSubExpr()); + + Inherited::VisitImplicitCastExpr(E); + } + + void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { + Expr *Callee = E->getCallee(); + if (isa<MemberExpr>(Callee)) + HandleValue(Callee); + + Inherited::VisitCXXMemberCallExpr(E); + } + }; + static void CheckInitExprContainsUninitializedFields(Sema &S, Expr *E, + ValueDecl *VD) { + UninitializedFieldVisitor(S, VD).HandleExpr(E); + } +} // namespace + /// ActOnCXXInClassMemberInitializer - This is invoked after parsing an /// in-class initializer for a non-static C++ class member, and after /// instantiating an in-class initializer in a class template. Such actions @@ -1685,8 +1903,17 @@ Sema::ActOnCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, return; } + if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, InitLoc) + != DiagnosticsEngine::Ignored) { + CheckInitExprContainsUninitializedFields(*this, InitExpr, FD); + } + ExprResult Init = InitExpr; - if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { + 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 (isa<InitListExpr>(InitExpr) && isStdInitializerList(FD->getType(), 0)) { Diag(FD->getLocation(), diag::warn_dangling_std_initializer_list) << /*at end of ctor*/1 << InitExpr->getSourceRange(); @@ -1795,7 +2022,8 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { - Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + Expr *List = new (Context) ParenListExpr(Context, LParenLoc, + llvm::makeArrayRef(Args, NumArgs), RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, DS, IdLoc, List, EllipsisLoc); @@ -2044,96 +2272,6 @@ static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, << (unsigned)IsPointer; } -namespace { - class UninitializedFieldVisitor - : public EvaluatedExprVisitor<UninitializedFieldVisitor> { - Sema &S; - ValueDecl *VD; - public: - typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited; - UninitializedFieldVisitor(Sema &S, ValueDecl *VD) : Inherited(S.Context), - S(S), VD(VD) { - } - - void HandleExpr(Expr *E) { - if (!E) return; - - // Expressions like x(x) sometimes lack the surrounding expressions - // but need to be checked anyways. - HandleValue(E); - Visit(E); - } - - void HandleValue(Expr *E) { - E = E->IgnoreParens(); - - if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { - if (isa<EnumConstantDecl>(ME->getMemberDecl())) - return; - Expr *Base = E; - while (isa<MemberExpr>(Base)) { - ME = dyn_cast<MemberExpr>(Base); - if (VarDecl *VarD = dyn_cast<VarDecl>(ME->getMemberDecl())) - if (VarD->hasGlobalStorage()) - return; - Base = ME->getBase(); - } - - if (VD == ME->getMemberDecl() && isa<CXXThisExpr>(Base)) { - S.Diag(ME->getExprLoc(), diag::warn_field_is_uninit); - return; - } - } - - if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { - HandleValue(CO->getTrueExpr()); - HandleValue(CO->getFalseExpr()); - return; - } - - if (BinaryConditionalOperator *BCO = - dyn_cast<BinaryConditionalOperator>(E)) { - HandleValue(BCO->getCommon()); - HandleValue(BCO->getFalseExpr()); - return; - } - - if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { - switch (BO->getOpcode()) { - default: - return; - case(BO_PtrMemD): - case(BO_PtrMemI): - HandleValue(BO->getLHS()); - return; - case(BO_Comma): - HandleValue(BO->getRHS()); - return; - } - } - } - - void VisitImplicitCastExpr(ImplicitCastExpr *E) { - if (E->getCastKind() == CK_LValueToRValue) - HandleValue(E->getSubExpr()); - - Inherited::VisitImplicitCastExpr(E); - } - - void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - Expr *Callee = E->getCallee(); - if (isa<MemberExpr>(Callee)) - HandleValue(Callee); - - Inherited::VisitCXXMemberCallExpr(E); - } - }; - static void CheckInitExprContainsUninitializedFields(Sema &S, Expr *E, - ValueDecl *VD) { - UninitializedFieldVisitor(S, VD).HandleExpr(E); - } -} // namespace - MemInitResult Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { @@ -2167,11 +2305,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, != DiagnosticsEngine::Ignored) for (unsigned i = 0; i < NumArgs; ++i) // FIXME: Warn about the case when other fields are used before being - // uninitialized. For example, let this field be the i'th field. When + // initialized. For example, let this field be the i'th field. When // initializing the i'th field, throw a warning if any of the >= i'th // fields are used, as they are not yet initialized. // Right now we are only handling the case where the i'th field uses // itself in its initializer. + // Also need to take into account that some fields may be initialized by + // in-class initializers, see C++11 [class.base.init]p9. CheckInitExprContainsUninitializedFields(*this, Args[i], Member); SourceRange InitRange = Init->getSourceRange(); @@ -2204,7 +2344,7 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, - MultiExprArg(*this, Args, NumArgs), + MultiExprArg(Args, NumArgs), 0); if (MemberInit.isInvalid()) return true; @@ -2273,7 +2413,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, InitRange.getEnd()); InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, - MultiExprArg(*this, Args,NumArgs), + MultiExprArg(Args, NumArgs), 0); if (DelegationInit.isInvalid()) return true; @@ -2411,8 +2551,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, InitRange.getEnd()); InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, - MultiExprArg(*this, Args, NumArgs), - 0); + MultiExprArg(Args, NumArgs), 0); if (BaseInit.isInvalid()) return true; @@ -2480,8 +2619,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, InitializationKind InitKind = InitializationKind::CreateDefault(Constructor->getLocation()); InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); - BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, - MultiExprArg(SemaRef, 0, 0)); + BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, MultiExprArg()); break; } @@ -2936,7 +3074,11 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, NumInitializers * sizeof(CXXCtorInitializer*)); Constructor->setCtorInitializers(baseOrMemberInitializers); } - + + // Let template instantiation know whether we had errors. + if (AnyErrors) + Constructor->setInvalidDecl(); + return false; } @@ -3324,11 +3466,10 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl, } else { assert(Init->isDelegatingInitializer()); // This must be the only initializer - if (i != 0 || NumMemInits > 1) { - Diag(MemInits[0]->getSourceLocation(), + if (NumMemInits != 1) { + Diag(Init->getSourceLocation(), diag::err_delegating_initializer_alone) - << MemInits[0]->getSourceRange(); - HadError = true; + << Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange(); // We will treat this as being the only initializer. } SetDelegatingInitializer(Constructor, MemInits[i]); @@ -3812,6 +3953,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { diag::warn_non_virtual_dtor) << Context.getRecordType(Record); } + if (Record->isAbstract() && Record->hasAttr<FinalAttr>()) { + Diag(Record->getLocation(), diag::warn_abstract_final_class); + DiagnoseAbstractType(Record); + } + // See if a method overloads virtual methods in a base /// class without overriding any. if (!Record->isDependentType()) { @@ -4065,7 +4211,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // Compute argument constness, constexpr, and triviality. bool CanHaveConstParam = false; - bool Trivial; + bool Trivial = false; switch (CSM) { case CXXDefaultConstructor: Trivial = RD->hasTrivialDefaultConstructor(); @@ -4304,7 +4450,7 @@ bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj, /// If we're operating on a base class, the object type is the /// type of this special member. QualType objectTy; - AccessSpecifier access = target->getAccess();; + AccessSpecifier access = target->getAccess(); if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) { objectTy = S.Context.getTypeDeclType(MD->getParent()); access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access); @@ -4647,6 +4793,19 @@ namespace { }; } +/// \brief Check whether any most overriden method from MD in Methods +static bool CheckMostOverridenMethods(const CXXMethodDecl *MD, + const llvm::SmallPtrSet<const CXXMethodDecl *, 8>& Methods) { + if (MD->size_overridden_methods() == 0) + return Methods.count(MD->getCanonicalDecl()); + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) + if (CheckMostOverridenMethods(*I, Methods)) + return true; + return false; +} + /// \brief Member lookup function that determines whether a given C++ /// method overloads virtual methods in a base class without overriding any, /// to be used with CXXRecordDecl::lookupInBases(). @@ -4678,7 +4837,7 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, if (!Data.S->IsOverload(Data.Method, MD, false)) return true; // Collect the overload only if its hidden. - if (!Data.OverridenAndUsingBaseMethods.count(MD)) + if (!CheckMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods)) overloadedMethods.push_back(MD); } } @@ -4689,6 +4848,17 @@ static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, return foundSameNameMethod; } +/// \brief Add the most overriden methods from MD to Methods +static void AddMostOverridenMethods(const CXXMethodDecl *MD, + llvm::SmallPtrSet<const CXXMethodDecl *, 8>& Methods) { + if (MD->size_overridden_methods() == 0) + Methods.insert(MD->getCanonicalDecl()); + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) + AddMostOverridenMethods(*I, Methods); +} + /// \brief See if a method overloads virtual methods in a base class without /// overriding any. void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { @@ -4709,14 +4879,11 @@ void Sema::DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { // by 'using' in a set. A base method not in this set is hidden. for (DeclContext::lookup_result res = DC->lookup(MD->getDeclName()); res.first != res.second; ++res.first) { - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*res.first)) - for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), - E = MD->end_overridden_methods(); - I != E; ++I) - Data.OverridenAndUsingBaseMethods.insert((*I)->getCanonicalDecl()); + NamedDecl *ND = *res.first; if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*res.first)) - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(shad->getTargetDecl())) - Data.OverridenAndUsingBaseMethods.insert(MD->getCanonicalDecl()); + ND = shad->getTargetDecl(); + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) + AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods); } if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths) && @@ -5307,7 +5474,47 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { // Namespace Handling //===----------------------------------------------------------------------===// +/// \brief Diagnose a mismatch in 'inline' qualifiers when a namespace is +/// reopened. +static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, + SourceLocation Loc, + IdentifierInfo *II, bool *IsInline, + NamespaceDecl *PrevNS) { + assert(*IsInline != PrevNS->isInline()); + + // HACK: Work around a bug in libstdc++4.6's <atomic>, where + // std::__atomic[0,1,2] are defined as non-inline namespaces, then reopened as + // inline namespaces, with the intention of bringing names into namespace std. + // + // We support this just well enough to get that case working; this is not + // sufficient to support reopening namespaces as inline in general. + if (*IsInline && II && II->getName().startswith("__atomic") && + S.getSourceManager().isInSystemHeader(Loc)) { + // Mark all prior declarations of the namespace as inline. + for (NamespaceDecl *NS = PrevNS->getMostRecentDecl(); NS; + NS = NS->getPreviousDecl()) + NS->setInline(*IsInline); + // Patch up the lookup table for the containing namespace. This isn't really + // correct, but it's good enough for this particular case. + for (DeclContext::decl_iterator I = PrevNS->decls_begin(), + E = PrevNS->decls_end(); I != E; ++I) + if (NamedDecl *ND = dyn_cast<NamedDecl>(*I)) + PrevNS->getParent()->makeDeclVisibleInContext(ND); + return; + } + + if (PrevNS->isInline()) + // The user probably just forgot the 'inline', so suggest that it + // be added back. + S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline) + << FixItHint::CreateInsertion(KeywordLoc, "inline "); + else + S.Diag(Loc, diag::err_inline_namespace_mismatch) + << IsInline; + S.Diag(PrevNS->getLocation(), diag::note_previous_definition); + *IsInline = PrevNS->isInline(); +} /// ActOnStartNamespaceDef - This is called at the start of a namespace /// definition. @@ -5357,21 +5564,9 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, if (PrevNS) { // This is an extended namespace definition. - if (IsInline != PrevNS->isInline()) { - // inline-ness must match - if (PrevNS->isInline()) { - // The user probably just forgot the 'inline', so suggest that it - // be added back. - Diag(Loc, diag::warn_inline_namespace_reopened_noninline) - << FixItHint::CreateInsertion(NamespaceLoc, "inline "); - } else { - Diag(Loc, diag::err_inline_namespace_mismatch) - << IsInline; - } - Diag(PrevNS->getLocation(), diag::note_previous_definition); - - IsInline = PrevNS->isInline(); - } + if (IsInline != PrevNS->isInline()) + DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II, + &IsInline, PrevNS); } else if (PrevDecl) { // This is an invalid name redefinition. Diag(Loc, diag::err_redefinition_different_kind) @@ -5402,15 +5597,9 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, PrevNS = ND->getAnonymousNamespace(); } - if (PrevNS && IsInline != PrevNS->isInline()) { - // inline-ness must match - Diag(Loc, diag::err_inline_namespace_mismatch) - << IsInline; - Diag(PrevNS->getLocation(), diag::note_previous_definition); - - // Recover by ignoring the new namespace's inline status. - IsInline = PrevNS->isInline(); - } + if (PrevNS && IsInline != PrevNS->isInline()) + DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, NamespaceLoc, II, + &IsInline, PrevNS); } NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline, @@ -5460,15 +5649,15 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, if (!PrevNS) { UsingDirectiveDecl* UD - = UsingDirectiveDecl::Create(Context, CurContext, + = UsingDirectiveDecl::Create(Context, Parent, /* 'using' */ LBrace, /* 'namespace' */ SourceLocation(), /* qualifier */ NestedNameSpecifierLoc(), /* identifier */ SourceLocation(), Namespc, - /* Ancestor */ CurContext); + /* Ancestor */ Parent); UD->setImplicit(); - CurContext->addDecl(UD); + Parent->addDecl(UD); } } @@ -5697,7 +5886,8 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, if (DeclContext *DC = S.computeDeclContext(SS, false)) S.Diag(IdentLoc, diag::err_using_directive_member_suggest) << Ident << DC << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); else S.Diag(IdentLoc, diag::err_using_directive_suggest) << Ident << CorrectedQuotedStr @@ -6562,10 +6752,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, if (TemplateParamLists.size() != 1) { Diag(UsingLoc, diag::err_alias_template_extra_headers) - << SourceRange(TemplateParamLists.get()[1]->getTemplateLoc(), - TemplateParamLists.get()[TemplateParamLists.size()-1]->getRAngleLoc()); + << SourceRange(TemplateParamLists[1]->getTemplateLoc(), + TemplateParamLists[TemplateParamLists.size()-1]->getRAngleLoc()); } - TemplateParameterList *TemplateParams = TemplateParamLists.get()[0]; + TemplateParameterList *TemplateParams = TemplateParamLists[0]; // Only consider previous declarations in the same scope. FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false, @@ -6696,28 +6886,6 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, return AliasDecl; } -namespace { - /// \brief Scoped object used to handle the state changes required in Sema - /// to implicitly define the body of a C++ member function; - class ImplicitlyDefinedFunctionScope { - Sema &S; - Sema::ContextRAII SavedContext; - - public: - ImplicitlyDefinedFunctionScope(Sema &S, CXXMethodDecl *Method) - : S(S), SavedContext(S, Method) - { - S.PushFunctionScope(); - S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated); - } - - ~ImplicitlyDefinedFunctionScope() { - S.PopExpressionEvaluationContext(); - S.PopFunctionScopeInfo(); - } - }; -} - Sema::ImplicitExceptionSpecification Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) { @@ -6861,7 +7029,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = Constructor->getParent(); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); - ImplicitlyDefinedFunctionScope Scope(*this, Constructor); + SynthesizedFunctionScope Scope(*this, Constructor); DiagnosticErrorTrap Trap(Diags); if (SetCtorInitializers(Constructor, 0, 0, /*AnyErrors=*/false) || Trap.hasErrorOccurred()) { @@ -7173,7 +7341,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, if (Destructor->isInvalidDecl()) return; - ImplicitlyDefinedFunctionScope Scope(*this, Destructor); + SynthesizedFunctionScope Scope(*this, Destructor); DiagnosticErrorTrap Trap(Diags); MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), @@ -7412,7 +7580,7 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, = new (S.Context) BinaryOperator(IterationVarRefRVal, IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), BO_NE, S.Context.BoolTy, - VK_RValue, OK_Ordinary, Loc); + VK_RValue, OK_Ordinary, Loc, false); // Create the pre-increment of the iteration variable. Expr *Increment @@ -7654,7 +7822,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator); + SynthesizedFunctionScope Scope(*this, CopyAssignOperator); DiagnosticErrorTrap Trap(Diags); // C++0x [class.copy]p30: @@ -7666,7 +7834,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // which they were declared in the class definition. // The statements that form the synthesized function body. - ASTOwningVector<Stmt*> Statements(*this); + SmallVector<Stmt*, 8> Statements; // The parameter for the "other" object, which we are copying from. ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0); @@ -7846,8 +8014,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, - CollectableMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(CollectableMemCpyRef && "Builtin reference cannot fail"); } } @@ -7866,12 +8034,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, - BuiltinMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); } - ASTOwningVector<Expr*> CallArgs(*this); + 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)); @@ -7879,12 +8047,12 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, if (NeedsCollectableMemCpy) Call = ActOnCallExpr(/*Scope=*/0, CollectableMemCpyRef, - Loc, move_arg(CallArgs), + Loc, CallArgs, Loc); else Call = ActOnCallExpr(/*Scope=*/0, BuiltinMemCpyRef, - Loc, move_arg(CallArgs), + Loc, CallArgs, Loc); assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); @@ -7934,7 +8102,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, StmtResult Body; { CompoundScopeRAII CompoundScope(*this); - Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + Body = ActOnCompoundStmt(Loc, Loc, Statements, /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); } @@ -8040,7 +8208,7 @@ hasMoveOrIsTriviallyCopyable(Sema &S, QualType Type, bool IsConstructor) { // reference types, are supposed to return false here, but that appears // to be a standard defect. CXXRecordDecl *ClassDecl = Type->getAsCXXRecordDecl(); - if (!ClassDecl || !ClassDecl->getDefinition()) + if (!ClassDecl || !ClassDecl->getDefinition() || ClassDecl->isInvalidDecl()) return true; if (Type.isTriviallyCopyableType(S.Context)) @@ -8195,7 +8363,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, MoveAssignOperator->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, MoveAssignOperator); + SynthesizedFunctionScope Scope(*this, MoveAssignOperator); DiagnosticErrorTrap Trap(Diags); // C++0x [class.copy]p28: @@ -8207,7 +8375,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, // definition. // The statements that form the synthesized function body. - ASTOwningVector<Stmt*> Statements(*this); + SmallVector<Stmt*, 8> Statements; // The parameter for the "other" object, which we are move from. ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0); @@ -8395,8 +8563,8 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, - CollectableMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(CollectableMemCpyRef && "Builtin reference cannot fail"); } } @@ -8415,12 +8583,12 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, } BuiltinMemCpyRef = BuildDeclRefExpr(BuiltinMemCpy, - BuiltinMemCpy->getType(), - VK_LValue, Loc, 0).take(); + Context.BuiltinFnTy, + VK_RValue, Loc, 0).take(); assert(BuiltinMemCpyRef && "Builtin reference cannot fail"); } - ASTOwningVector<Expr*> CallArgs(*this); + 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)); @@ -8428,12 +8596,12 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, if (NeedsCollectableMemCpy) Call = ActOnCallExpr(/*Scope=*/0, CollectableMemCpyRef, - Loc, move_arg(CallArgs), + Loc, CallArgs, Loc); else Call = ActOnCallExpr(/*Scope=*/0, BuiltinMemCpyRef, - Loc, move_arg(CallArgs), + Loc, CallArgs, Loc); assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); @@ -8483,7 +8651,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, StmtResult Body; { CompoundScopeRAII CompoundScope(*this); - Body = ActOnCompoundStmt(Loc, Loc, move_arg(Statements), + Body = ActOnCompoundStmt(Loc, Loc, Statements, /*isStmtExpr=*/false); assert(!Body.isInvalid() && "Compound statement creation cannot fail"); } @@ -8691,7 +8859,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); - ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor); + SynthesizedFunctionScope Scope(*this, CopyConstructor); DiagnosticErrorTrap Trap(Diags); if (SetCtorInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) || @@ -8703,7 +8871,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, Sema::CompoundScopeRAII CompoundScope(*this); CopyConstructor->setBody(ActOnCompoundStmt(CopyConstructor->getLocation(), CopyConstructor->getLocation(), - MultiStmtArg(*this, 0, 0), + MultiStmtArg(), /*isStmtExpr=*/false) .takeAs<Stmt>()); CopyConstructor->setImplicitlyDefined(true); @@ -8874,7 +9042,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = MoveConstructor->getParent(); assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor"); - ImplicitlyDefinedFunctionScope Scope(*this, MoveConstructor); + SynthesizedFunctionScope Scope(*this, MoveConstructor); DiagnosticErrorTrap Trap(Diags); if (SetCtorInitializers(MoveConstructor, 0, 0, /*AnyErrors=*/false) || @@ -8886,7 +9054,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, Sema::CompoundScopeRAII CompoundScope(*this); MoveConstructor->setBody(ActOnCompoundStmt(MoveConstructor->getLocation(), MoveConstructor->getLocation(), - MultiStmtArg(*this, 0, 0), + MultiStmtArg(), /*isStmtExpr=*/false) .takeAs<Stmt>()); MoveConstructor->setImplicitlyDefined(true); @@ -8926,7 +9094,7 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( Conv->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, Conv); + SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); // Return the address of the __invoke function. @@ -8959,7 +9127,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( { Conv->setUsed(); - ImplicitlyDefinedFunctionScope Scope(*this, Conv); + SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); // Copy-initialize the lambda object as needed to capture it. @@ -9014,12 +9182,12 @@ static bool hasOneRealArgument(MultiExprArg Args) { return false; default: - if (!Args.get()[1]->isDefaultArgument()) + if (!Args[1]->isDefaultArgument()) return false; // fall through case 1: - return !Args.get()[0]->isDefaultArgument(); + return !Args[0]->isDefaultArgument(); } return false; @@ -9047,12 +9215,12 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, // directly into the target of the omitted copy/move if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { - Expr *SubExpr = ((Expr **)ExprArgs.get())[0]; + Expr *SubExpr = ExprArgs[0]; Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent()); } return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, - Elidable, move(ExprArgs), HadMultipleCandidates, + Elidable, ExprArgs, HadMultipleCandidates, RequiresZeroInit, ConstructKind, ParenRange); } @@ -9066,12 +9234,9 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { - unsigned NumExprs = ExprArgs.size(); - Expr **Exprs = (Expr **)ExprArgs.release(); - MarkFunctionReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, - Constructor, Elidable, Exprs, NumExprs, + Constructor, Elidable, ExprArgs, HadMultipleCandidates, /*FIXME*/false, RequiresZeroInit, static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), @@ -9085,7 +9250,7 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, // FIXME: Provide the correct paren SourceRange when available. ExprResult TempResult = BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, - move(Exprs), HadMultipleCandidates, false, + Exprs, HadMultipleCandidates, false, CXXConstructExpr::CK_Complete, SourceRange()); if (TempResult.isInvalid()) return true; @@ -9135,11 +9300,11 @@ bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, SourceLocation Loc, - ASTOwningVector<Expr*> &ConvertedArgs, + SmallVectorImpl<Expr*> &ConvertedArgs, bool AllowExplicit) { // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. unsigned NumArgs = ArgsPtr.size(); - Expr **Args = (Expr **)ArgsPtr.get(); + Expr **Args = ArgsPtr.data(); const FunctionProtoType *Proto = Constructor->getType()->getAs<FunctionProtoType>(); @@ -9268,7 +9433,7 @@ CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { } static bool -CheckOperatorDeleteDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { +CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { // C++ [basic.stc.dynamic.deallocation]p1: // A program is ill-formed if deallocation functions are declared in a // namespace scope other than global scope or declared static in global @@ -9825,7 +9990,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, /// \brief Perform semantic analysis of the given friend type declaration. /// /// \returns A friend declaration that. -FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc, +FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, SourceLocation FriendLoc, TypeSourceInfo *TSInfo) { assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); @@ -9864,7 +10029,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc, diag::warn_cxx98_compat_nonclass_type_friend : diag::ext_nonclass_type_friend) << T - << SourceRange(FriendLoc, TypeRange.getEnd()); + << TypeRange; } } else if (T->getAs<EnumType>()) { Diag(FriendLoc, @@ -9872,18 +10037,22 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc, diag::warn_cxx98_compat_enum_friend : diag::ext_enum_friend) << T - << SourceRange(FriendLoc, TypeRange.getEnd()); + << TypeRange; } - // C++0x [class.friend]p3: + // 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; + // If the type specifier in a friend declaration designates a (possibly - // cv-qualified) class type, that class is declared as a friend; otherwise, + // cv-qualified) class type, that class is declared as a friend; otherwise, // the friend declaration is ignored. - - // FIXME: C++0x has some syntactic restrictions on friend type declarations - // in [class.friend]p3 that we do not implement. - - return FriendDecl::Create(Context, CurContext, Loc, TSInfo, FriendLoc); + return FriendDecl::Create(Context, CurContext, LocStart, TSInfo, FriendLoc); } /// Handle a friend tag declaration where the scope specifier was @@ -9901,7 +10070,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(TagLoc, NameLoc, SS, - TempParamLists.get(), + TempParamLists.data(), TempParamLists.size(), /*friend*/ true, isExplicitSpecialization, @@ -9916,7 +10085,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, TemplateParams, AS_public, /*ModulePrivateLoc=*/SourceLocation(), TempParamLists.size() - 1, - (TemplateParameterList**) TempParamLists.release()).take(); + TempParamLists.data()).take(); } else { // The "template<>" header is extraneous. Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) @@ -9929,7 +10098,7 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, bool isAllExplicitSpecializations = true; for (unsigned I = TempParamLists.size(); I-- > 0; ) { - if (TempParamLists.get()[I]->size()) { + if (TempParamLists[I]->size()) { isAllExplicitSpecializations = false; break; } @@ -10076,7 +10245,7 @@ Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, if (unsigned NumTempParamLists = TempParams.size()) D = FriendTemplateDecl::Create(Context, CurContext, Loc, NumTempParamLists, - TempParams.release(), + TempParams.data(), TSI, DS.getFriendSpecLoc()); else @@ -10318,7 +10487,7 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, - move(TemplateParams), AddToScope); + TemplateParams, AddToScope); if (!ND) return 0; assert(ND->getDeclContext() == DC); @@ -10435,10 +10604,10 @@ void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { // If this definition appears within the record, do the checking when // the record is complete. const FunctionDecl *Primary = MD; - if (MD->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + if (const FunctionDecl *Pattern = MD->getTemplateInstantiationPattern()) // Find the uninstantiated declaration that actually had the '= default' // on it. - MD->getTemplateInstantiationPattern()->isDefined(Primary); + Pattern->isDefined(Primary); if (Primary == Primary->getCanonicalDecl()) return; @@ -10963,14 +11132,16 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, if (Ctor->isInvalidDecl()) return; - const FunctionDecl *FNTarget = 0; - CXXConstructorDecl *Target; - - // We ignore the result here since if we don't have a body, Target will be - // null below. - (void)Ctor->getTargetConstructor()->hasBody(FNTarget); - Target -= const_cast<CXXConstructorDecl*>(cast_or_null<CXXConstructorDecl>(FNTarget)); + CXXConstructorDecl *Target = Ctor->getTargetConstructor(); + + // Target may not be determinable yet, for instance if this is a dependent + // call in an uninstantiated template. + if (Target) { + const FunctionDecl *FNTarget = 0; + (void)Target->hasBody(FNTarget); + Target = const_cast<CXXConstructorDecl*>( + cast_or_null<CXXConstructorDecl>(FNTarget)); + } CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(), // Avoid dereferencing a null pointer here. @@ -10994,17 +11165,18 @@ void DelegatingCycleHelper(CXXConstructorDecl* Ctor, diag::warn_delegating_ctor_cycle) << Ctor; - // Don't add a note for a function delegating directo to itself. + // Don't add a note for a function delegating directly to itself. if (TCanonical != Canonical) S.Diag(Target->getLocation(), diag::note_it_delegates_to); CXXConstructorDecl *C = Target; while (C->getCanonicalDecl() != Canonical) { + const FunctionDecl *FNTarget = 0; (void)C->getTargetConstructor()->hasBody(FNTarget); assert(FNTarget && "Ctor cycle through bodiless function"); - C - = const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget)); + C = const_cast<CXXConstructorDecl*>( + cast<CXXConstructorDecl>(FNTarget)); S.Diag(C->getLocation(), diag::note_which_delegates_to); } } @@ -11027,9 +11199,8 @@ void Sema::CheckDelegatingCtorCycles() { for (DelegatingCtorDeclsType::iterator I = DelegatingCtorDecls.begin(ExternalSource), E = DelegatingCtorDecls.end(); - I != E; ++I) { - DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); - } + I != E; ++I) + DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) (*CI)->setInvalidDecl(); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 9da4d69..c4e91e8 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -282,6 +282,25 @@ void Sema::AddAnyMethodToGlobalPool(Decl *D) { AddFactoryMethodToGlobalPool(MDecl, true); } +/// HasExplicitOwnershipAttr - returns true when pointer to ObjC pointer +/// has explicit ownership attribute; false otherwise. +static bool +HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) { + QualType T = Param->getType(); + + if (const PointerType *PT = T->getAs<PointerType>()) { + T = PT->getPointeeType(); + } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) { + T = RT->getPointeeType(); + } else { + return true; + } + + // If we have a lifetime qualifier, but it's local, we must have + // inferred it. So, it is implicit. + return !T.getLocalQualifiers().hasObjCLifetime(); +} + /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible /// and user declared, in the method definition's AST. void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { @@ -313,6 +332,12 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { RequireCompleteType(Param->getLocation(), Param->getType(), diag::err_typecheck_decl_incomplete_type)) Param->setInvalidDecl(); + if (!Param->isInvalidDecl() && + getLangOpts().ObjCAutoRefCount && + !HasExplicitOwnershipAttr(*this, Param)) + Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) << + Param->getType(); + if ((*PI)->getIdentifier()) PushOnScopeChains(*PI, FnBodyScope); } @@ -345,8 +370,10 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { // Warn on deprecated methods under -Wdeprecated-implementations, // and prepare for warning on missing super calls. if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) { - if (ObjCMethodDecl *IMD = - IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod())) + ObjCMethodDecl *IMD = + IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()); + + if (IMD) DiagnoseObjCImplementedDeprecations(*this, dyn_cast<NamedDecl>(IMD), MDecl->getLocation(), 0); @@ -356,13 +383,23 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set. // Only do this if the current class actually has a superclass. if (IC->getSuperClass()) { - getCurFunction()->ObjCShouldCallSuperDealloc = - !(Context.getLangOpts().ObjCAutoRefCount || - Context.getLangOpts().getGC() == LangOptions::GCOnly) && - MDecl->getMethodFamily() == OMF_dealloc; - getCurFunction()->ObjCShouldCallSuperFinalize = - Context.getLangOpts().getGC() != LangOptions::NonGC && - MDecl->getMethodFamily() == OMF_finalize; + ObjCMethodFamily Family = MDecl->getMethodFamily(); + if (Family == OMF_dealloc) { + if (!(getLangOpts().ObjCAutoRefCount || + getLangOpts().getGC() == LangOptions::GCOnly)) + getCurFunction()->ObjCShouldCallSuper = true; + + } else if (Family == OMF_finalize) { + if (Context.getLangOpts().getGC() != LangOptions::NonGC) + getCurFunction()->ObjCShouldCallSuper = true; + + } else { + const ObjCMethodDecl *SuperMethod = + IC->getSuperClass()->lookupMethod(MDecl->getSelector(), + MDecl->isInstanceMethod()); + getCurFunction()->ObjCShouldCallSuper = + (SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>()); + } } } } @@ -510,7 +547,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // Check then save referenced protocols. if (NumProtoRefs) { - IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); IDecl->setEndOfDefinitionLoc(EndProtoLoc); } @@ -652,7 +689,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, if (!err && NumProtoRefs ) { /// Check then save referenced protocols. - PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); } @@ -819,11 +856,11 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, CurContext->addDecl(CDecl); if (NumProtoRefs) { - CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, + CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); // Protocols in the class extension belong to the class. if (CDecl->IsClassExtension()) - IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, + IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, Context); } @@ -1545,9 +1582,9 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, E = PDecl->instmeth_end(); I != E; ++I) { ObjCMethodDecl *method = *I; if (method->getImplementationControl() != ObjCMethodDecl::Optional && - !method->isSynthesized() && !InsMap.count(method->getSelector()) && - (!Super || - !Super->lookupInstanceMethod(method->getSelector()))) { + !method->isPropertyAccessor() && + !InsMap.count(method->getSelector()) && + (!Super || !Super->lookupInstanceMethod(method->getSelector()))) { // If a method is not implemented in the category implementation but // has been declared in its primary class, superclass, // or in one of their protocols, no need to issue the warning. @@ -1560,7 +1597,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, if (ObjCMethodDecl *MethodInClass = IDecl->lookupInstanceMethod(method->getSelector(), true /*shallowCategoryLookup*/)) - if (C || MethodInClass->isSynthesized()) + if (C || MethodInClass->isPropertyAccessor()) continue; unsigned DIAG = diag::warn_unimplemented_protocol_method; if (Diags.getDiagnosticLevel(DIAG, ImpLoc) @@ -1621,7 +1658,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, if (InsMapSeen.count((*I)->getSelector())) continue; InsMapSeen.insert((*I)->getSelector()); - if (!(*I)->isSynthesized() && + if (!(*I)->isPropertyAccessor() && !InsMap.count((*I)->getSelector())) { if (ImmediateClass) WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl, @@ -1638,7 +1675,7 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, if (!WarnCategoryMethodImpl) WarnConflictingTypedMethods(ImpMethodDecl, MethodDecl, isa<ObjCProtocolDecl>(CDecl)); - else if (!MethodDecl->isSynthesized()) + else if (!MethodDecl->isPropertyAccessor()) WarnExactTypedMethods(ImpMethodDecl, MethodDecl, isa<ObjCProtocolDecl>(CDecl)); } @@ -1672,14 +1709,26 @@ void Sema::MatchAllMethodDeclarations(const SelectorSet &InsMap, } if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { - // Also methods in class extensions need be looked at next. - for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) - MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, - IMPDecl, - const_cast<ObjCCategoryDecl *>(ClsExtDecl), - IncompleteImpl, false, - WarnCategoryMethodImpl); + // 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()) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, + const_cast<ObjCCategoryDecl *>(CDeclChain), + IncompleteImpl, false, + WarnCategoryMethodImpl); + else + // Also methods in class extensions need be looked at next. + for (const ObjCCategoryDecl *ClsExtDecl = I->getFirstClassExtension(); + ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) + MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, + IMPDecl, + const_cast<ObjCCategoryDecl *>(ClsExtDecl), + IncompleteImpl, false, + WarnCategoryMethodImpl); // Check for any implementation of a methods declared in protocol. for (ObjCInterfaceDecl::all_protocol_iterator @@ -2339,11 +2388,11 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, CExtDecl; CExtDecl = CExtDecl->getNextClassExtension()) { if (ObjCMethodDecl *GetterMethod = CExtDecl->getInstanceMethod(Property->getGetterName())) - GetterMethod->setSynthesized(true); + GetterMethod->setPropertyAccessor(true); if (!Property->isReadOnly()) if (ObjCMethodDecl *SetterMethod = CExtDecl->getInstanceMethod(Property->getSetterName())) - SetterMethod->setSynthesized(true); + SetterMethod->setPropertyAccessor(true); } } } @@ -2435,26 +2484,49 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { } static inline +unsigned countAlignAttr(const AttrVec &A) { + unsigned count=0; + for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) + if ((*i)->getKind() == attr::Aligned) + ++count; + return count; +} + +static inline bool containsInvalidMethodImplAttribute(ObjCMethodDecl *IMD, const AttrVec &A) { // If method is only declared in implementation (private method), // No need to issue any diagnostics on method definition with attributes. if (!IMD) return false; - + // method declared in interface has no attribute. - // But implementation has attributes. This is invalid + // But implementation has attributes. This is invalid. + // Except when implementation has 'Align' attribute which is + // immaterial to method declared in interface. if (!IMD->hasAttrs()) - return true; + return (A.size() > countAlignAttr(A)); const AttrVec &D = IMD->getAttrs(); - if (D.size() != A.size()) - return true; + unsigned countAlignOnImpl = countAlignAttr(A); + if (!countAlignOnImpl && (A.size() != D.size())) + return true; + else if (countAlignOnImpl) { + unsigned countAlignOnDecl = countAlignAttr(D); + if (countAlignOnDecl && (A.size() != D.size())) + return true; + else if (!countAlignOnDecl && + ((A.size()-countAlignOnImpl) != D.size())) + return true; + } + // attributes on method declaration and definition must match exactly. // Note that we have at most a couple of attributes on methods, so this // n*n search is good enough. for (AttrVec::const_iterator i = A.begin(), e = A.end(); i != e; ++i) { + if ((*i)->getKind() == attr::Aligned) + continue; bool match = false; for (AttrVec::const_iterator i1 = D.begin(), e1 = D.end(); i1 != e1; ++i1) { if ((*i)->getKind() == (*i1)->getKind()) { @@ -2465,6 +2537,7 @@ bool containsInvalidMethodImplAttribute(ObjCMethodDecl *IMD, if (!match) return true; } + return false; } @@ -2525,7 +2598,7 @@ public: // with this selector before. Sema::GlobalMethodPool::iterator it = S.MethodPool.find(selector); if (it == S.MethodPool.end()) { - if (!S.ExternalSource) return; + if (!S.getExternalSource()) return; S.ReadMethodPool(selector); it = S.MethodPool.find(selector); @@ -2767,7 +2840,7 @@ Decl *Sema::ActOnMethodDeclaration( ResultTInfo, CurContext, MethodType == tok::minus, isVariadic, - /*isSynthesized=*/false, + /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/false, /*isDefined=*/false, MethodDeclKind == tok::objc_optional ? ObjCMethodDecl::Optional diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index e6266fb..e1f4888 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -120,6 +120,24 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { return SourceDecl->getType()->castAs<FunctionProtoType>(); } +/// Determine whether a function has an implicitly-generated exception +/// specification. +static bool hasImplicitExceptionSpec(FunctionDecl *Decl) { + if (!isa<CXXDestructorDecl>(Decl) && + Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete && + Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) + return false; + + // If the user didn't declare the function, its exception specification must + // be implicit. + if (!Decl->getTypeSourceInfo()) + return true; + + const FunctionProtoType *Ty = + Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>(); + return !Ty->hasExceptionSpec(); +} + bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator(); bool IsOperatorNew = OO == OO_New || OO == OO_Array_New; @@ -129,25 +147,35 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { if (getLangOpts().MicrosoftExt) DiagID = diag::warn_mismatched_exception_spec; - if (!CheckEquivalentExceptionSpec(PDiag(DiagID), - PDiag(diag::note_previous_declaration), - Old->getType()->getAs<FunctionProtoType>(), - Old->getLocation(), - New->getType()->getAs<FunctionProtoType>(), - New->getLocation(), - &MissingExceptionSpecification, - &MissingEmptyExceptionSpecification, - /*AllowNoexceptAllMatchWithNoSpec=*/true, - IsOperatorNew)) + // Check the types as written: they must match before any exception + // specification adjustment is applied. + if (!CheckEquivalentExceptionSpec( + PDiag(DiagID), PDiag(diag::note_previous_declaration), + Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), + New->getType()->getAs<FunctionProtoType>(), New->getLocation(), + &MissingExceptionSpecification, &MissingEmptyExceptionSpecification, + /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) { + // C++11 [except.spec]p4 [DR1492]: + // 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 && + hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) { + Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch) + << hasImplicitExceptionSpec(Old); + if (!Old->getLocation().isInvalid()) + Diag(Old->getLocation(), diag::note_previous_declaration); + } return false; + } // The failure was something other than an empty exception // specification; return an error. if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification) return true; - const FunctionProtoType *NewProto - = New->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *NewProto = + New->getType()->getAs<FunctionProtoType>(); // The new function declaration is only missing an empty exception // specification "throw()". If the throw() specification came from a @@ -172,8 +200,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { } if (MissingExceptionSpecification && NewProto) { - const FunctionProtoType *OldProto - = Old->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *OldProto = + Old->getType()->getAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo(); EPI.ExceptionSpecType = OldProto->getExceptionSpecType(); @@ -290,14 +318,17 @@ bool Sema::CheckEquivalentExceptionSpec( unsigned DiagID = diag::err_mismatched_exception_spec; if (getLangOpts().MicrosoftExt) DiagID = diag::warn_mismatched_exception_spec; - return CheckEquivalentExceptionSpec( - PDiag(DiagID), + return CheckEquivalentExceptionSpec(PDiag(DiagID), PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc); } /// CheckEquivalentExceptionSpec - Check if the two types have compatible /// exception specifications. See C++ [except.spec]p3. +/// +/// \return \c false if the exception specifications match, \c true if there is +/// a problem. If \c true is returned, either a diagnostic has already been +/// produced or \c *MissingExceptionSpecification is set to \c true. bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Old, @@ -1029,6 +1060,7 @@ CanThrowResult Sema::canThrow(const Expr *E) { case Expr::PseudoObjectExprClass: case Expr::SubstNonTypeTemplateParmExprClass: case Expr::SubstNonTypeTemplateParmPackExprClass: + case Expr::FunctionParmPackExprClass: case Expr::UnaryExprOrTypeTraitExprClass: case Expr::UnresolvedLookupExprClass: case Expr::UnresolvedMemberExprClass: diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3875ba1..bf4abfc 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -66,6 +66,15 @@ bool Sema::CanUseDecl(NamedDecl *D) { return true; } +static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { + // Warn if this is used but marked unused. + if (D->hasAttr<UnusedAttr>()) { + const Decl *DC = cast<Decl>(S.getCurObjCLexicalContext()); + if (!DC->hasAttr<UnusedAttr>()) + S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); + } +} + static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc, const ObjCInterfaceDecl *UnknownObjCClass) { @@ -78,6 +87,17 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, if (const EnumDecl *TheEnumDecl = dyn_cast<EnumDecl>(DC)) Result = TheEnumDecl->getAvailability(&Message); } + + const ObjCPropertyDecl *ObjCPDecl = 0; + if (Result == AR_Deprecated || Result == AR_Unavailable) { + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { + if (const ObjCPropertyDecl *PD = MD->findPropertyDecl()) { + AvailabilityResult PDeclResult = PD->getAvailability(0); + if (PDeclResult == Result) + ObjCPDecl = PD; + } + } + } switch (Result) { case AR_Available: @@ -85,23 +105,30 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S, break; case AR_Deprecated: - S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass); + S.EmitDeprecationWarning(D, Message, Loc, UnknownObjCClass, ObjCPDecl); break; case AR_Unavailable: if (S.getCurContextAvailability() != AR_Unavailable) { if (Message.empty()) { - if (!UnknownObjCClass) + if (!UnknownObjCClass) { S.Diag(Loc, diag::err_unavailable) << D->getDeclName(); + if (ObjCPDecl) + S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute) + << ObjCPDecl->getDeclName() << 1; + } else S.Diag(Loc, diag::warn_unavailable_fwdclass_message) << D->getDeclName(); } - else + else S.Diag(Loc, diag::err_unavailable_message) << D->getDeclName() << Message; - S.Diag(D->getLocation(), diag::note_unavailable_here) - << isa<FunctionDecl>(D) << false; + S.Diag(D->getLocation(), diag::note_unavailable_here) + << isa<FunctionDecl>(D) << false; + if (ObjCPDecl) + S.Diag(ObjCPDecl->getLocation(), diag::note_property_attribute) + << ObjCPDecl->getDeclName() << 1; } break; } @@ -250,9 +277,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, } DiagnoseAvailabilityOfDecl(*this, D, Loc, UnknownObjCClass); - // Warn if this is used but marked unused. - if (D->hasAttr<UnusedAttr>()) - Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); + DiagnoseUnusedOfDecl(*this, D, Loc); diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc); @@ -502,7 +527,7 @@ ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E) { Res = DefaultLvalueConversion(Res.take()); if (Res.isInvalid()) return ExprError(); - return move(Res); + return Res; } @@ -1098,8 +1123,8 @@ Sema::ActOnGenericSelectionExpr(SourceLocation KeyLoc, unsigned NumAssocs = ArgTypes.size(); assert(NumAssocs == ArgExprs.size()); - ParsedType *ParsedTypes = ArgTypes.release(); - Expr **Exprs = ArgExprs.release(); + ParsedType *ParsedTypes = ArgTypes.data(); + Expr **Exprs = ArgExprs.data(); TypeSourceInfo **Types = new TypeSourceInfo*[NumAssocs]; for (unsigned i = 0; i < NumAssocs; ++i) { @@ -1185,8 +1210,9 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, if (IsResultDependent) return Owned(new (Context) GenericSelectionExpr( Context, KeyLoc, ControllingExpr, - Types, Exprs, NumAssocs, DefaultLoc, - RParenLoc, ContainsUnexpandedParameterPack)); + llvm::makeArrayRef(Types, NumAssocs), + llvm::makeArrayRef(Exprs, NumAssocs), + DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack)); SmallVector<unsigned, 1> CompatIndices; unsigned DefaultIndex = -1U; @@ -1240,8 +1266,9 @@ Sema::CreateGenericSelectionExpr(SourceLocation KeyLoc, return Owned(new (Context) GenericSelectionExpr( Context, KeyLoc, ControllingExpr, - Types, Exprs, NumAssocs, DefaultLoc, - RParenLoc, ContainsUnexpandedParameterPack, + llvm::makeArrayRef(Types, NumAssocs), + llvm::makeArrayRef(Exprs, NumAssocs), + DefaultLoc, RParenLoc, ContainsUnexpandedParameterPack, ResultIndex)); } @@ -1402,6 +1429,15 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, MarkDeclRefReferenced(E); + if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) && + Ty.getObjCLifetime() == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + E->getLocStart()); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(E); + } + // Just in case we're building an illegal pointer-to-member. FieldDecl *FD = dyn_cast<FieldDecl>(D); if (FD && FD->isBitField()) @@ -1428,11 +1464,9 @@ Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id, Buffer.setLAngleLoc(Id.TemplateId->LAngleLoc); Buffer.setRAngleLoc(Id.TemplateId->RAngleLoc); - ASTTemplateArgsPtr TemplateArgsPtr(*this, - Id.TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(Id.TemplateId->getTemplateArgs(), Id.TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, Buffer); - TemplateArgsPtr.release(); TemplateName TName = Id.TemplateId->Template.get(); SourceLocation TNameLoc = Id.TemplateId->TemplateNameLoc; @@ -1606,7 +1640,8 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, Diag(R.getNameLoc(), diag::err_no_member_suggest) << Name << computeDeclContext(SS, false) << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); if (ND) Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr; @@ -1797,7 +1832,7 @@ ExprResult Sema::ActOnIdExpression(Scope *S, // lookup fails and no expression will be built to reference it. if (!E.isInvalid() && !E.get()) return ExprError(); - return move(E); + return E; } } } @@ -1860,9 +1895,10 @@ ExprResult Sema::ActOnIdExpression(Scope *S, /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo) { - DeclContext *DC; - if (!(DC = computeDeclContext(SS, false)) || DC->isDependentContext()) + const DeclarationNameInfo &NameInfo, + bool IsAddressOfOperand) { + DeclContext *DC = computeDeclContext(SS, false); + if (!DC) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, /*TemplateArgs=*/0); @@ -1875,13 +1911,26 @@ Sema::BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, if (R.isAmbiguous()) return ExprError(); + if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), + NameInfo, /*TemplateArgs=*/0); + if (R.empty()) { Diag(NameInfo.getLoc(), diag::err_no_member) << NameInfo.getName() << DC << SS.getRange(); return ExprError(); } - return BuildDeclarationNameExpr(SS, R, /*ADL*/ false); + // Defend against this resolving to an implicit member access. We usually + // won't get here if this might be a legitimate a class member (we end up in + // BuildMemberReferenceExpr instead), but this can be valid if we're forming + // a pointer-to-member or in an unevaluated context in C++11. + if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand) + return BuildPossibleImplicitMemberExpr(SS, + /*TemplateKWLoc=*/SourceLocation(), + R, /*TemplateArgs=*/0); + + return BuildDeclarationNameExpr(SS, R, /* ADL */ false); } /// LookupInObjCMethod - The parser has read a name in, and Sema has @@ -1965,9 +2014,25 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, ObjCMethodFamily MF = CurMethod->getMethodFamily(); if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize) Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName(); - return Owned(new (Context) - ObjCIvarRefExpr(IV, IV->getType(), Loc, - SelfExpr.take(), true, true)); + + ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(), + Loc, + SelfExpr.take(), + true, true); + + if (getLangOpts().ObjCAutoRefCount) { + if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(Result); + } + if (CurContext->isClosure()) + Diag(Loc, diag::warn_implicitly_retains_self) + << FixItHint::CreateInsertion(Loc, "self->"); + } + + return Owned(Result); } } else if (CurMethod->isInstanceMethod()) { // We should warn if a local variable hides an ivar. @@ -2416,6 +2481,14 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, } case Decl::Function: { + if (unsigned BID = cast<FunctionDecl>(VD)->getBuiltinID()) { + if (!Context.BuiltinInfo.isPredefinedLibFunction(BID)) { + type = Context.BuiltinFnTy; + valueKind = VK_RValue; + break; + } + } + const FunctionType *fty = type->castAs<FunctionType>(); // If we're referring to a function with an __unknown_anytype @@ -2615,19 +2688,20 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { return ActOnIntegerConstant(Tok.getLocation(), Val-'0'); } - SmallString<512> IntegerBuffer; - // Add padding so that NumericLiteralParser can overread by one character. - IntegerBuffer.resize(Tok.getLength()+1); - const char *ThisTokBegin = &IntegerBuffer[0]; + SmallString<128> SpellingBuffer; + // NumericLiteralParser wants to overread by one character. Add padding to + // the buffer in case the token is copied to the buffer. If getSpelling() + // returns a StringRef to the memory buffer, it should have a null char at + // the EOF, so it is also safe. + SpellingBuffer.resize(Tok.getLength() + 1); // Get the spelling of the token, which eliminates trigraphs, etc. bool Invalid = false; - unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid); + StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid); if (Invalid) return ExprError(); - NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength, - Tok.getLocation(), PP); + NumericLiteralParser Literal(TokSpelling, Tok.getLocation(), PP); if (Literal.hadError) return ExprError(); @@ -2693,7 +2767,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { Context.CharTy, llvm::APInt(32, Length + 1), ArrayType::Normal, 0); Expr *Lit = StringLiteral::Create( - Context, StringRef(ThisTokBegin, Length), StringLiteral::Ascii, + Context, StringRef(TokSpelling.data(), Length), StringLiteral::Ascii, /*Pascal*/false, StrTy, &TokLoc, 1); return BuildLiteralOperatorCall(R, OpNameInfo, llvm::makeArrayRef(&Lit, 1), TokLoc); @@ -2709,7 +2783,7 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { bool CharIsUnsigned = Context.CharTy->isUnsignedIntegerType(); llvm::APSInt Value(CharBits, CharIsUnsigned); for (unsigned I = 0, N = Literal.getUDSuffixOffset(); I != N; ++I) { - Value = ThisTokBegin[I]; + Value = TokSpelling[I]; TemplateArgument Arg(Context, Value, Context.CharTy); TemplateArgumentLocInfo ArgInfo; ExplicitArgs.addArgument(TemplateArgumentLoc(Arg, ArgInfo)); @@ -2747,11 +2821,15 @@ ExprResult Sema::ActOnNumericConstant(const Token &Tok, Scope *UDLScope) { } else { QualType Ty; - // long long is a C99 feature. - if (!getLangOpts().C99 && Literal.isLongLong) - Diag(Tok.getLocation(), - getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_longlong : diag::ext_longlong); + // 'long long' is a C99 or C++11 feature. + if (!getLangOpts().C99 && Literal.isLongLong) { + if (getLangOpts().CPlusPlus) + Diag(Tok.getLocation(), + getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); + else + Diag(Tok.getLocation(), diag::ext_c99_longlong); + } // Get the value in the widest-possible width. unsigned MaxWidth = Context.getTargetInfo().getIntMaxTWidth(); @@ -3140,7 +3218,7 @@ Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, Expr *ArgEx = (Expr *)TyOrEx; ExprResult Result = CreateUnaryExprOrTypeTraitExpr(ArgEx, OpLoc, ExprKind); - return move(Result); + return Result; } static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc, @@ -3167,7 +3245,7 @@ static QualType CheckRealImagOperand(Sema &S, ExprResult &V, SourceLocation Loc, ExprResult PR = S.CheckPlaceholderExpr(V.get()); if (PR.isInvalid()) return QualType(); if (PR.get() != V.get()) { - V = move(PR); + V = PR; return CheckRealImagOperand(S, V, Loc, IsReal); } @@ -3442,8 +3520,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Expr *ResultE = Result.takeAs<Expr>(); InitializationSequence InitSeq(*this, Entity, Kind, &ResultE, 1); - Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, &ResultE, 1)); + Result = InitSeq.Perform(*this, Entity, Kind, ResultE); if (Result.isInvalid()) return ExprError(); @@ -3776,28 +3853,25 @@ ExprResult Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig, bool IsExecConfig) { - unsigned NumArgs = ArgExprs.size(); - // Since this might be a postfix expression, get rid of ParenListExprs. ExprResult Result = MaybeConvertParenListExprToParenExpr(S, Fn); if (Result.isInvalid()) return ExprError(); Fn = Result.take(); - Expr **Args = ArgExprs.release(); - if (getLangOpts().CPlusPlus) { // If this is a pseudo-destructor expression, build the call immediately. if (isa<CXXPseudoDestructorExpr>(Fn)) { - if (NumArgs > 0) { + if (!ArgExprs.empty()) { // Pseudo-destructor calls should not have any arguments. Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args) << FixItHint::CreateRemoval( - SourceRange(Args[0]->getLocStart(), - Args[NumArgs-1]->getLocEnd())); + SourceRange(ArgExprs[0]->getLocStart(), + ArgExprs.back()->getLocEnd())); } - return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy, - VK_RValue, RParenLoc)); + return Owned(new (Context) CallExpr(Context, Fn, MultiExprArg(), + Context.VoidTy, VK_RValue, + RParenLoc)); } // Determine whether this is a dependent call inside a C++ template, @@ -3807,17 +3881,16 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, bool Dependent = false; if (Fn->isTypeDependent()) Dependent = true; - else if (Expr::hasAnyTypeDependentArguments( - llvm::makeArrayRef(Args, NumArgs))) + else if (Expr::hasAnyTypeDependentArguments(ArgExprs)) Dependent = true; if (Dependent) { if (ExecConfig) { return Owned(new (Context) CUDAKernelCallExpr( - Context, Fn, cast<CallExpr>(ExecConfig), Args, NumArgs, + Context, Fn, cast<CallExpr>(ExecConfig), ArgExprs, Context.DependentTy, VK_RValue, RParenLoc)); } else { - return Owned(new (Context) CallExpr(Context, Fn, Args, NumArgs, + return Owned(new (Context) CallExpr(Context, Fn, ArgExprs, Context.DependentTy, VK_RValue, RParenLoc)); } @@ -3825,8 +3898,9 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, // Determine whether this is a call to an object (C++ [over.call.object]). if (Fn->getType()->isRecordType()) - return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, Args, NumArgs, - RParenLoc)); + return Owned(BuildCallToObjectOfClassType(S, Fn, LParenLoc, + ArgExprs.data(), + ArgExprs.size(), RParenLoc)); if (Fn->getType() == Context.UnknownAnyTy) { ExprResult result = rebuildUnknownAnyFunction(*this, Fn); @@ -3835,8 +3909,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, } if (Fn->getType() == Context.BoundMemberTy) { - return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, - RParenLoc); + return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(), + ArgExprs.size(), RParenLoc); } } @@ -3849,11 +3923,11 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, OverloadExpr *ovl = find.Expression; if (isa<UnresolvedLookupExpr>(ovl)) { UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl); - return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs, - RParenLoc, ExecConfig); + return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, ArgExprs.data(), + ArgExprs.size(), RParenLoc, ExecConfig); } else { - return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs, - RParenLoc); + return BuildCallToMemberFunction(S, Fn, LParenLoc, ArgExprs.data(), + ArgExprs.size(), RParenLoc); } } } @@ -3877,8 +3951,9 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, else if (isa<MemberExpr>(NakedFn)) NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl(); - return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc, - ExecConfig, IsExecConfig); + return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs.data(), + ArgExprs.size(), RParenLoc, ExecConfig, + IsExecConfig); } ExprResult @@ -3932,9 +4007,19 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation RParenLoc, Expr *Config, bool IsExecConfig) { FunctionDecl *FDecl = dyn_cast_or_null<FunctionDecl>(NDecl); + unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); // Promote the function operand. - ExprResult Result = UsualUnaryConversions(Fn); + // We special-case function promotion here because we only allow promoting + // builtin functions to function pointers in the callee of a call. + ExprResult Result; + if (BuiltinID && + Fn->getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn)) { + Result = ImpCastExprToType(Fn, Context.getPointerType(FDecl->getType()), + CK_BuiltinFnToFnPtr).take(); + } else { + Result = UsualUnaryConversions(Fn); + } if (Result.isInvalid()) return ExprError(); Fn = Result.take(); @@ -3945,19 +4030,17 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, if (Config) TheCall = new (Context) CUDAKernelCallExpr(Context, Fn, cast<CallExpr>(Config), - Args, NumArgs, + llvm::makeArrayRef(Args,NumArgs), Context.BoolTy, VK_RValue, RParenLoc); else TheCall = new (Context) CallExpr(Context, Fn, - Args, NumArgs, + llvm::makeArrayRef(Args, NumArgs), Context.BoolTy, VK_RValue, RParenLoc); - unsigned BuiltinID = (FDecl ? FDecl->getBuiltinID() : 0); - // Bail out early if calling a builtin with custom typechecking. if (BuiltinID && Context.BuiltinInfo.hasCustomTypechecking(BuiltinID)) return CheckBuiltinFunctionCall(BuiltinID, TheCall); @@ -4143,9 +4226,8 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, SourceRange(LParenLoc, RParenLoc), /*InitList=*/true); InitializationSequence InitSeq(*this, Entity, Kind, &LiteralExpr, 1); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, &LiteralExpr, 1), - &literalType); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, LiteralExpr, + &literalType); if (Result.isInvalid()) return ExprError(); LiteralExpr = Result.get(); @@ -4167,28 +4249,25 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, ExprResult Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, SourceLocation RBraceLoc) { - unsigned NumInit = InitArgList.size(); - Expr **InitList = InitArgList.release(); - // Immediately handle non-overload placeholders. Overloads can be // resolved contextually, but everything else here can't. - for (unsigned I = 0; I != NumInit; ++I) { - if (InitList[I]->getType()->isNonOverloadPlaceholderType()) { - ExprResult result = CheckPlaceholderExpr(InitList[I]); + for (unsigned I = 0, E = InitArgList.size(); I != E; ++I) { + if (InitArgList[I]->getType()->isNonOverloadPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(InitArgList[I]); // Ignore failures; dropping the entire initializer list because // of one failure would be terrible for indexing/etc. if (result.isInvalid()) continue; - InitList[I] = result.take(); + InitArgList[I] = result.take(); } } // Semantic analysis for initializers is done by ActOnDeclarator() and // CheckInitializer() - it requires knowledge of the object being intialized. - InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitList, - NumInit, RBraceLoc); + InitListExpr *E = new (Context) InitListExpr(Context, LBraceLoc, InitArgList, + RBraceLoc); E->setType(Context.VoidTy); // FIXME: just a place holder for now. return Owned(E); } @@ -4575,8 +4654,7 @@ 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[0], - initExprs.size(), RParenLoc); + initExprs, RParenLoc); initE->setType(Ty); return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE); } @@ -4603,10 +4681,8 @@ Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { ExprResult Sema::ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val) { - unsigned nexprs = Val.size(); - Expr **exprs = reinterpret_cast<Expr**>(Val.release()); - assert((exprs != 0) && "ActOnParenOrParenListExpr() missing expr list"); - Expr *expr = new (Context) ParenListExpr(Context, L, exprs, nexprs, R); + assert(Val.data() != 0 && "ActOnParenOrParenListExpr() missing expr list"); + Expr *expr = new (Context) ParenListExpr(Context, L, Val, R); return Owned(expr); } @@ -4884,11 +4960,11 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult LHSResult = CheckPlaceholderExpr(LHS.get()); if (!LHSResult.isUsable()) return QualType(); - LHS = move(LHSResult); + LHS = LHSResult; ExprResult RHSResult = CheckPlaceholderExpr(RHS.get()); if (!RHSResult.isUsable()) return QualType(); - RHS = move(RHSResult); + RHS = RHSResult; // C++ is sufficiently different to merit its own checker. if (getLangOpts().CPlusPlus) @@ -5247,7 +5323,7 @@ static void DiagnoseConditionalPrecedence(Sema &Self, << BinaryOperator::getOpcodeStr(CondOpcode); SuggestParentheses(Self, OpLoc, - Self.PDiag(diag::note_precedence_conditional_silence) + Self.PDiag(diag::note_precedence_silence) << BinaryOperator::getOpcodeStr(CondOpcode), SourceRange(Condition->getLocStart(), Condition->getLocEnd())); @@ -5811,8 +5887,7 @@ static void ConstructTransparentUnion(Sema &S, ASTContext &C, // of the transparent union. Expr *E = EResult.take(); InitListExpr *Initializer = new (C) InitListExpr(C, SourceLocation(), - &E, 1, - SourceLocation()); + E, SourceLocation()); Initializer->setType(UnionType); Initializer->setInitializedFieldInUnion(Field); @@ -5910,7 +5985,7 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, !CheckObjCARCUnavailableWeakConversion(LHSType, RHS.get()->getType())) result = IncompatibleObjCWeakRef; - RHS = move(Res); + RHS = Res; return result; } @@ -6708,7 +6783,7 @@ static void diagnoseFunctionPointerToVoidComparison(Sema &S, SourceLocation Loc, } static bool isObjCObjectLiteral(ExprResult &E) { - switch (E.get()->getStmtClass()) { + switch (E.get()->IgnoreParenImpCasts()->getStmtClass()) { case Stmt::ObjCArrayLiteralClass: case Stmt::ObjCDictionaryLiteralClass: case Stmt::ObjCStringLiteralClass: @@ -6800,6 +6875,7 @@ static void diagnoseObjCLiteralComparison(Sema &S, SourceLocation Loc, LK_String } LiteralKind; + Literal = Literal->IgnoreParenImpCasts(); switch (Literal->getStmtClass()) { case Stmt::ObjCStringLiteralClass: // "string literal" @@ -7202,7 +7278,10 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, (LHSType->isIntegerType() && RHSType->isAnyPointerType())) { unsigned DiagID = 0; bool isError = false; - if ((LHSIsNull && LHSType->isIntegerType()) || + if (LangOpts.DebuggerSupport) { + // Under a debugger, allow the comparison of pointers to integers, + // since users tend to want to compare addresses. + } else if ((LHSIsNull && LHSType->isIntegerType()) || (RHSIsNull && RHSType->isIntegerType())) { if (IsRelational && !getLangOpts().CPlusPlus) DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; @@ -7419,12 +7498,12 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] ExprResult LHSRes = PerformContextuallyConvertToBool(LHS.get()); if (LHSRes.isInvalid()) return InvalidOperands(Loc, LHS, RHS); - LHS = move(LHSRes); + LHS = LHSRes; ExprResult RHSRes = PerformContextuallyConvertToBool(RHS.get()); if (RHSRes.isInvalid()) return InvalidOperands(Loc, LHS, RHS); - RHS = move(RHSRes); + RHS = RHSRes; // C++ [expr.log.and]p2 // C++ [expr.log.or]p2 @@ -7683,10 +7762,31 @@ QualType Sema::CheckAssignmentOperands(Expr *LHSExpr, ExprResult &RHS, } if (ConvTy == Compatible) { - if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong) - checkRetainCycles(LHSExpr, RHS.get()); - else if (getLangOpts().ObjCAutoRefCount) + if (LHSType.getObjCLifetime() == Qualifiers::OCL_Strong) { + // Warn about retain cycles where a block captures the LHS, but + // not if the LHS is a simple variable into which the block is + // being stored...unless that variable can be captured by reference! + const Expr *InnerLHS = LHSExpr->IgnoreParenCasts(); + const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InnerLHS); + if (!DRE || DRE->getDecl()->hasAttr<BlocksAttr>()) + checkRetainCycles(LHSExpr, RHS.get()); + + // It is safe to assign a weak reference into a strong variable. + // Although this code can still have problems: + // id x = self.weakProp; + // id y = self.weakProp; + // we do not warn to warn spuriously when 'x' and 'y' are on separate + // paths through the function. This should be revisited if + // -Wrepeated-use-of-weak is made flow-sensitive. + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + RHS.get()->getLocStart()); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->markSafeWeakUse(RHS.get()); + + } else if (getLangOpts().ObjCAutoRefCount) { checkUnsafeExprAssigns(Loc, LHSExpr, RHS.get()); + } } } else { // Compound assignment "x += y" @@ -7972,8 +8072,16 @@ static QualType CheckAddressOfOperand(Sema &S, ExprResult &OrigOp, // The method was named without a qualifier. } else if (!DRE->getQualifier()) { - S.Diag(OpLoc, diag::err_unqualified_pointer_member_function) - << op->getSourceRange(); + if (MD->getParent()->getName().empty()) + S.Diag(OpLoc, diag::err_unqualified_pointer_member_function) + << op->getSourceRange(); + else { + SmallString<32> Str; + StringRef Qual = (MD->getParent()->getName() + "::").toStringRef(Str); + S.Diag(OpLoc, diag::err_unqualified_pointer_member_function) + << op->getSourceRange() + << FixItHint::CreateInsertion(op->getSourceRange().getBegin(), Qual); + } } return S.Context.getMemberPointerType(op->getType(), @@ -8216,8 +8324,7 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, InitializedEntity Entity = InitializedEntity::InitializeTemporary(LHSExpr->getType()); InitializationSequence InitSeq(*this, Entity, Kind, &RHSExpr, 1); - ExprResult Init = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(&RHSExpr, 1)); + ExprResult Init = InitSeq.Perform(*this, Entity, Kind, RHSExpr); if (Init.isInvalid()) return Init; RHSExpr = Init.take(); @@ -8340,7 +8447,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, if (CompResultTy.isNull()) return Owned(new (Context) BinaryOperator(LHS.take(), RHS.take(), Opc, - ResultTy, VK, OK, OpLoc)); + ResultTy, VK, OK, OpLoc, + FPFeatures.fp_contract)); if (getLangOpts().CPlusPlus && LHS.get()->getObjectKind() != OK_ObjCProperty) { VK = VK_LValue; @@ -8348,7 +8456,8 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, } return Owned(new (Context) CompoundAssignOperator(LHS.take(), RHS.take(), Opc, ResultTy, VK, OK, CompLHSTy, - CompResultTy, OpLoc)); + CompResultTy, OpLoc, + FPFeatures.fp_contract)); } /// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison @@ -8383,8 +8492,8 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, SourceRange DiagRange = isLeftComp ? SourceRange(LHSExpr->getLocStart(), OpLoc) : SourceRange(OpLoc, RHSExpr->getLocEnd()); - std::string OpStr = isLeftComp ? BinOp::getOpcodeStr(LHSopc) - : BinOp::getOpcodeStr(RHSopc); + StringRef OpStr = isLeftComp ? BinOp::getOpcodeStr(LHSopc) + : BinOp::getOpcodeStr(RHSopc); SourceRange ParensRange = isLeftComp ? SourceRange(cast<BinOp>(LHSExpr)->getRHS()->getLocStart(), RHSExpr->getLocEnd()) @@ -8394,7 +8503,7 @@ static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperatorKind Opc, Self.Diag(OpLoc, diag::warn_precedence_bitwise_rel) << DiagRange << BinOp::getOpcodeStr(Opc) << OpStr; SuggestParentheses(Self, OpLoc, - Self.PDiag(diag::note_precedence_bitwise_silence) << OpStr, + Self.PDiag(diag::note_precedence_silence) << OpStr, (isLeftComp ? LHSExpr : RHSExpr)->getSourceRange()); SuggestParentheses(Self, OpLoc, Self.PDiag(diag::note_precedence_bitwise_first) << BinOp::getOpcodeStr(Opc), @@ -8411,7 +8520,8 @@ EmitDiagnosticForBitwiseAndInBitwiseOr(Sema &Self, SourceLocation OpLoc, Self.Diag(Bop->getOperatorLoc(), diag::warn_bitwise_and_in_bitwise_or) << Bop->getSourceRange() << OpLoc; SuggestParentheses(Self, Bop->getOperatorLoc(), - Self.PDiag(diag::note_bitwise_and_in_bitwise_or_silence), + Self.PDiag(diag::note_precedence_silence) + << Bop->getOpcodeStr(), Bop->getSourceRange()); } @@ -8425,7 +8535,8 @@ EmitDiagnosticForLogicalAndInLogicalOr(Sema &Self, SourceLocation OpLoc, Self.Diag(Bop->getOperatorLoc(), diag::warn_logical_and_in_logical_or) << Bop->getSourceRange() << OpLoc; SuggestParentheses(Self, Bop->getOperatorLoc(), - Self.PDiag(diag::note_logical_and_in_logical_or_silence), + Self.PDiag(diag::note_precedence_silence) + << Bop->getOpcodeStr(), Bop->getSourceRange()); } @@ -8489,6 +8600,20 @@ static void DiagnoseBitwiseAndInBitwiseOr(Sema &S, SourceLocation OpLoc, } } +static void DiagnoseAdditionInShift(Sema &S, SourceLocation OpLoc, + Expr *SubExpr, StringRef Shift) { + if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) { + if (Bop->getOpcode() == BO_Add || Bop->getOpcode() == BO_Sub) { + StringRef Op = Bop->getOpcodeStr(); + S.Diag(Bop->getOperatorLoc(), diag::warn_addition_in_bitshift) + << Bop->getSourceRange() << OpLoc << Shift << Op; + SuggestParentheses(S, Bop->getOperatorLoc(), + S.PDiag(diag::note_precedence_silence) << Op, + Bop->getSourceRange()); + } + } +} + /// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky /// precedence. static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, @@ -8510,6 +8635,13 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, LHSExpr, RHSExpr); DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, LHSExpr, RHSExpr); } + + if ((Opc == BO_Shl && LHSExpr->getType()->isIntegralType(Self.getASTContext())) + || Opc == BO_Shr) { + StringRef Shift = BinaryOperator::getOpcodeStr(Opc); + DiagnoseAdditionInShift(Self, OpLoc, LHSExpr, Shift); + DiagnoseAdditionInShift(Self, OpLoc, RHSExpr, Shift); + } } // Binary Operators. 'Tok' is the token for the operator. @@ -8647,6 +8779,7 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, break; case UO_Deref: { Input = DefaultFunctionArrayLvalueConversion(Input.take()); + if (Input.isInvalid()) return ExprError(); resultType = CheckIndirectionOperand(*this, Input.get(), VK, OpLoc); break; } @@ -9147,8 +9280,7 @@ ExprResult Sema::BuildBuiltinOffsetOf(SourceLocation BuiltinLoc, } return Owned(OffsetOfExpr::Create(Context, Context.getSizeType(), BuiltinLoc, - TInfo, Comps.data(), Comps.size(), - Exprs.data(), Exprs.size(), RParenLoc)); + TInfo, Comps, Exprs, RParenLoc)); } ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, @@ -9526,6 +9658,16 @@ ExprResult Sema::BuildVAArgExpr(SourceLocation BuiltinLoc, if (Result.isInvalid()) return ExprError(); E = Result.take(); + } else if (VaListType->isRecordType() && getLangOpts().CPlusPlus) { + // If va_list is a record type and we are compiling in C++ mode, + // check the argument using reference binding. + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, + Context.getLValueReferenceType(VaListType), false); + ExprResult Init = PerformCopyInitialization(Entity, SourceLocation(), E); + if (Init.isInvalid()) + return ExprError(); + E = Init.takeAs<Expr>(); } else { // Otherwise, the va_list argument must be an l-value because // it is modified by va_arg. @@ -10094,6 +10236,14 @@ Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); } +void +Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, + ReuseLambdaContextDecl_t, + bool IsDecltype) { + Decl *LambdaContextDecl = ExprEvalContexts.back().LambdaContextDecl; + PushExpressionEvaluationContext(NewContext, LambdaContextDecl, IsDecltype); +} + void Sema::PopExpressionEvaluationContext() { ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back(); @@ -10191,15 +10341,44 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { Func->setReferenced(); - // Don't mark this function as used multiple times, unless it's a constexpr - // function which we need to instantiate. - if (Func->isUsed(false) && - !(Func->isConstexpr() && !Func->getBody() && - Func->isImplicitlyInstantiable())) - return; - - if (!IsPotentiallyEvaluatedContext(*this)) - return; + // C++11 [basic.def.odr]p3: + // A function whose name appears as a potentially-evaluated expression is + // odr-used if it is the unique lookup result or the selected member of a + // set of overloaded functions [...]. + // + // We (incorrectly) mark overload resolution as an unevaluated context, so we + // can just check that here. Skip the rest of this function if we've already + // marked the function as used. + if (Func->isUsed(false) || !IsPotentiallyEvaluatedContext(*this)) { + // C++11 [temp.inst]p3: + // Unless a function template specialization has been explicitly + // instantiated or explicitly specialized, the function template + // specialization is implicitly instantiated when the specialization is + // referenced in a context that requires a function definition to exist. + // + // We consider constexpr function templates to be referenced in a context + // that requires a definition to exist whenever they are referenced. + // + // FIXME: This instantiates constexpr functions too frequently. If this is + // really an unevaluated context (and we're not just in the definition of a + // function template or overload resolution or other cases which we + // incorrectly consider to be unevaluated contexts), and we're not in a + // subexpression which we actually need to evaluate (for instance, a + // template argument, array bound or an expression in a braced-init-list), + // we are not permitted to instantiate this constexpr function definition. + // + // FIXME: This also implicitly defines special members too frequently. They + // are only supposed to be implicitly defined if they are odr-used, but they + // are not odr-used from constant expressions in unevaluated contexts. + // However, they cannot be referenced if they are deleted, and they are + // deleted whenever the implicit definition of the special member would + // fail. + if (!Func->isConstexpr() || Func->getBody()) + return; + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Func); + if (!Func->isImplicitlyInstantiable() && (!MD || MD->isUserProvided())) + return; + } // Note that this declaration has been used. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) { @@ -10469,8 +10648,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, InitializationSequence Init(S, Entities.back(), InitKind, &Ref, 1); ExprResult Result(true); if (!Init.Diagnose(S, Entities.back(), InitKind, &Ref, 1)) - Result = Init.Perform(S, Entities.back(), InitKind, - MultiExprArg(S, &Ref, 1)); + Result = Init.Perform(S, Entities.back(), InitKind, Ref); // If this initialization requires any cleanups (e.g., due to a // default argument to a copy constructor), note that for the @@ -10886,20 +11064,21 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, } } - // Per C++11 [basic.def.odr], a variable is odr-used "unless it is - // an object that satisfies the requirements for appearing in a - // constant expression (5.19) and the lvalue-to-rvalue conversion (4.1) + // Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies + // the requirements for appearing in a constant expression (5.19) and, if + // it is an object, the lvalue-to-rvalue conversion (4.1) // is immediately applied." We check the first part here, and // Sema::UpdateMarkingForLValueToRValue deals with the second part. // Note that we use the C++11 definition everywhere because nothing in - // C++03 depends on whether we get the C++03 version correct. This does not - // apply to references, since they are not objects. + // C++03 depends on whether we get the C++03 version correct. The second + // part does not apply to references, since they are not objects. const VarDecl *DefVD; - if (E && !isa<ParmVarDecl>(Var) && !Var->getType()->isReferenceType() && + if (E && !isa<ParmVarDecl>(Var) && Var->isUsableInConstantExpressions(SemaRef.Context) && - Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) - SemaRef.MaybeODRUseExprs.insert(E); - else + Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) { + if (!Var->getType()->isReferenceType()) + SemaRef.MaybeODRUseExprs.insert(E); + } else MarkVarDeclODRUsed(SemaRef, Var, Loc); } @@ -11205,7 +11384,9 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { IsOrAssign = Op->getOperator() == OO_PipeEqual; Loc = Op->getOperatorLoc(); - } else { + } else if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) + return DiagnoseAssignmentAsCondition(POE->getSyntacticForm()); + else { // Not an assignment. return; } @@ -11759,6 +11940,10 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { case BuiltinType::PseudoObject: return checkPseudoObjectRValue(E); + case BuiltinType::BuiltinFn: + Diag(E->getLocStart(), diag::err_builtin_fn_use); + return ExprError(); + // Everything else should be impossible. #define BUILTIN_TYPE(Id, SingletonId) \ case BuiltinType::Id: @@ -11783,6 +11968,18 @@ ExprResult Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) && "Unknown Objective-C Boolean value!"); + QualType BoolT = Context.ObjCBuiltinBoolTy; + if (!Context.getBOOLDecl()) { + LookupResult Result(*this, &Context.Idents.get("BOOL"), OpLoc, + Sema::LookupOrdinaryName); + if (LookupName(Result, getCurScope()) && Result.isSingleResult()) { + NamedDecl *ND = Result.getFoundDecl(); + if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND)) + Context.setBOOLDecl(TD); + } + } + if (Context.getBOOLDecl()) + BoolT = Context.getBOOLType(); return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes, - Context.ObjCBuiltinBoolTy, OpLoc)); + BoolT, OpLoc)); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 2740259..0919bc5 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -410,33 +410,13 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } -/// Retrieve the UuidAttr associated with QT. -static UuidAttr *GetUuidAttrOfType(QualType QT) { - // Optionally remove one level of pointer, reference or array indirection. - const Type *Ty = QT.getTypePtr();; - if (QT->isPointerType() || QT->isReferenceType()) - Ty = QT->getPointeeType().getTypePtr(); - else if (QT->isArrayType()) - Ty = cast<ArrayType>(QT)->getElementType().getTypePtr(); - - // Loop all record redeclaration looking for an uuid attribute. - CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), - E = RD->redecls_end(); I != E; ++I) { - if (UuidAttr *Uuid = I->getAttr<UuidAttr>()) - return Uuid; - } - - return 0; -} - /// \brief Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc) { if (!Operand->getType()->isDependentType()) { - if (!GetUuidAttrOfType(Operand->getType())) + if (!CXXUuidofExpr::GetUuidAttrOfType(Operand->getType())) return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); } @@ -452,7 +432,7 @@ ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, Expr *E, SourceLocation RParenLoc) { if (!E->getType()->isDependentType()) { - if (!GetUuidAttrOfType(E->getType()) && + if (!CXXUuidofExpr::GetUuidAttrOfType(E->getType()) && !E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); } @@ -808,21 +788,18 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, MultiExprArg exprs, SourceLocation RParenLoc) { QualType Ty = TInfo->getType(); - unsigned NumExprs = exprs.size(); - Expr **Exprs = (Expr**)exprs.get(); SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); - if (Ty->isDependentType() || - CallExpr::hasAnyTypeDependentArguments( - llvm::makeArrayRef(Exprs, NumExprs))) { - exprs.release(); - + if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(exprs)) { return Owned(CXXUnresolvedConstructExpr::Create(Context, TInfo, LParenLoc, - Exprs, NumExprs, + exprs, RParenLoc)); } + unsigned NumExprs = exprs.size(); + Expr **Exprs = exprs.data(); + bool ListInitialization = LParenLoc.isInvalid(); assert((!ListInitialization || (NumExprs == 1 && isa<InitListExpr>(Exprs[0]))) && "List initialization must have initializer list as expression."); @@ -835,7 +812,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // corresponding cast expression. if (NumExprs == 1 && !ListInitialization) { Expr *Arg = Exprs[0]; - exprs.release(); return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc); } @@ -865,7 +841,7 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc); InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs); - ExprResult Result = InitSeq.Perform(*this, Entity, Kind, move(exprs)); + ExprResult Result = InitSeq.Perform(*this, Entity, Kind, exprs); if (!Result.isInvalid() && ListInitialization && isa<InitListExpr>(Result.get())) { @@ -881,7 +857,7 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, } // FIXME: Improve AST representation? - return move(Result); + return Result; } /// doesUsualArrayDeleteWantSize - Answers whether the usual @@ -1011,9 +987,9 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) DirectInitRange = List->getSourceRange(); - return BuildCXXNew(StartLoc, UseGlobal, + return BuildCXXNew(SourceRange(StartLoc, D.getLocEnd()), UseGlobal, PlacementLParen, - move(PlacementArgs), + PlacementArgs, PlacementRParen, TypeIdParens, AllocType, @@ -1044,7 +1020,7 @@ static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, } ExprResult -Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, +Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, @@ -1056,6 +1032,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, Expr *Initializer, bool TypeMayContainAuto) { SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); + SourceLocation StartLoc = Range.getBegin(); CXXNewExpr::InitializationStyle initStyle; if (DirectInitRange.isValid()) { @@ -1279,21 +1256,13 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } } - // ARC: warn about ABI issues. - if (getLangOpts().ObjCAutoRefCount) { - QualType BaseAllocType = Context.getBaseElementType(AllocType); - if (BaseAllocType.hasStrongOrWeakObjCLifetime()) - Diag(StartLoc, diag::warn_err_new_delete_object_array) - << 0 << BaseAllocType; - } - // Note that we do *not* convert the argument in any way. It can // be signed, larger than size_t, whatever. } FunctionDecl *OperatorNew = 0; FunctionDecl *OperatorDelete = 0; - Expr **PlaceArgs = (Expr**)PlacementArgs.get(); + Expr **PlaceArgs = PlacementArgs.data(); unsigned NumPlaceArgs = PlacementArgs.size(); if (!AllocType->isDependentType() && @@ -1432,15 +1401,14 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, } } - PlacementArgs.release(); - return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, OperatorDelete, UsualArrayDeleteWantsSize, - PlaceArgs, NumPlaceArgs, TypeIdParens, + llvm::makeArrayRef(PlaceArgs, NumPlaceArgs), + TypeIdParens, ArraySize, initStyle, Initializer, ResultType, AllocTypeInfo, - StartLoc, DirectInitRange)); + Range, DirectInitRange)); } /// \brief Checks that a type is suitable as the allocated type @@ -1638,7 +1606,7 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, = dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) { // Perform template argument deduction to try to match the // expected function type. - TemplateDeductionInfo Info(Context, StartLoc); + TemplateDeductionInfo Info(StartLoc); if (DeduceTemplateArguments(FnTmpl, 0, ExpectedFunctionType, Fn, Info)) continue; } else @@ -2100,7 +2068,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, ObjectPtrConversions.front()->getConversionType(), AA_Converting); if (Res.isUsable()) { - Ex = move(Res); + Ex = Res; Type = Ex.get()->getType(); } } @@ -2211,13 +2179,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, } } - } else if (getLangOpts().ObjCAutoRefCount && - PointeeElem->isObjCLifetimeType() && - (PointeeElem.getObjCLifetime() == Qualifiers::OCL_Strong || - PointeeElem.getObjCLifetime() == Qualifiers::OCL_Weak) && - ArrayForm) { - Diag(StartLoc, diag::warn_err_new_delete_object_array) - << 1 << PointeeElem; } if (!OperatorDelete) { @@ -2287,7 +2248,7 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, return ExprError(); } - return move(Condition); + return Condition; } /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. @@ -2354,11 +2315,9 @@ static ExprResult BuildCXXCastArgument(Sema &S, default: llvm_unreachable("Unhandled cast kind!"); case CK_ConstructorConversion: { CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Method); - ASTOwningVector<Expr*> ConstructorArgs(S); + SmallVector<Expr*, 8> ConstructorArgs; - if (S.CompleteConstructorCall(Constructor, - MultiExprArg(&From, 1), - CastLoc, ConstructorArgs)) + if (S.CompleteConstructorCall(Constructor, From, CastLoc, ConstructorArgs)) return ExprError(); S.CheckConstructorAccess(CastLoc, Constructor, @@ -2367,7 +2326,7 @@ static ExprResult BuildCXXCastArgument(Sema &S, ExprResult Result = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method), - move_arg(ConstructorArgs), + ConstructorArgs, HadMultipleCandidates, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); if (Result.isInvalid()) @@ -2511,15 +2470,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, // FIXME: When can ToType be a reference type? assert(!ToType->isReferenceType()); if (SCS.Second == ICK_Derived_To_Base) { - ASTOwningVector<Expr*> ConstructorArgs(*this); + SmallVector<Expr*, 8> ConstructorArgs; if (CompleteConstructorCall(cast<CXXConstructorDecl>(SCS.CopyConstructor), - MultiExprArg(*this, &From, 1), - /*FIXME:ConstructLoc*/SourceLocation(), + From, /*FIXME:ConstructLoc*/SourceLocation(), ConstructorArgs)) return ExprError(); return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, - move_arg(ConstructorArgs), + ConstructorArgs, /*HadMultipleCandidates*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, @@ -2527,8 +2485,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, } return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), ToType, SCS.CopyConstructor, - MultiExprArg(*this, &From, 1), - /*HadMultipleCandidates*/ false, + From, /*HadMultipleCandidates*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -2602,8 +2559,16 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, case ICK_Integral_Promotion: case ICK_Integral_Conversion: - From = ImpCastExprToType(From, ToType, CK_IntegralCast, - VK_RValue, /*BasePath=*/0, CCK).take(); + if (ToType->isBooleanType()) { + assert(FromType->castAs<EnumType>()->getDecl()->isFixed() && + SCS.Second == ICK_Integral_Promotion && + "only enums with fixed underlying type can promote to bool"); + From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean, + VK_RValue, /*BasePath=*/0, CCK).take(); + } else { + From = ImpCastExprToType(From, ToType, CK_IntegralCast, + VK_RValue, /*BasePath=*/0, CCK).take(); + } break; case ICK_Floating_Promotion: @@ -2943,6 +2908,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, case UTT_IsEmpty: case UTT_IsPolymorphic: case UTT_IsAbstract: + case UTT_IsInterfaceClass: // Fall-through // These traits require a complete type. @@ -3007,7 +2973,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, case UTT_IsUnion: return T->isUnionType(); case UTT_IsClass: - return T->isClassType() || T->isStructureType(); + return T->isClassType() || T->isStructureType() || T->isInterfaceType(); case UTT_IsFunction: return T->isFunctionType(); @@ -3073,6 +3039,10 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT, if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return RD->isAbstract(); return false; + case UTT_IsInterfaceClass: + if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + return RD->isInterface(); + return false; case UTT_IsFinal: if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) return RD->hasAttr<FinalAttr>(); @@ -3417,9 +3387,7 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc, if (Init.Failed()) return false; - ExprResult Result = Init.Perform(S, To, InitKind, - MultiExprArg(ArgExprs.data(), - ArgExprs.size())); + ExprResult Result = Init.Perform(S, To, InitKind, ArgExprs); if (Result.isInvalid() || SFINAE.hasErrorOccurred()) return false; @@ -3577,7 +3545,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, if (Init.Failed()) return false; - ExprResult Result = Init.Perform(Self, To, Kind, MultiExprArg(&FromPtr, 1)); + ExprResult Result = Init.Perform(Self, To, Kind, FromPtr); return !Result.isInvalid() && !SFINAE.hasErrorOccurred(); } @@ -3774,7 +3742,7 @@ ExprResult Sema::ActOnExpressionTrait(ExpressionTrait ET, ExprResult Result = BuildExpressionTrait(ET, KWLoc, Queried, RParen); - return move(Result); + return Result; } static bool EvaluateExpressionTrait(ExpressionTrait ET, Expr *E) { @@ -4056,14 +4024,14 @@ static bool FindConditionalOverload(Sema &Self, ExprResult &LHS, ExprResult &RHS Best->Conversions[0], Sema::AA_Converting); if (LHSRes.isInvalid()) break; - LHS = move(LHSRes); + LHS = LHSRes; ExprResult RHSRes = Self.PerformImplicitConversion(RHS.get(), Best->BuiltinTypes.ParamTypes[1], Best->Conversions[1], Sema::AA_Converting); if (RHSRes.isInvalid()) break; - RHS = move(RHSRes); + RHS = RHSRes; if (Best->Function) Self.MarkFunctionReferenced(QuestionLoc, Best->Function); return false; @@ -4104,7 +4072,7 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) { SourceLocation()); Expr *Arg = E.take(); InitializationSequence InitSeq(Self, Entity, Kind, &Arg, 1); - ExprResult Result = InitSeq.Perform(Self, Entity, Kind, MultiExprArg(&Arg, 1)); + ExprResult Result = InitSeq.Perform(Self, Entity, Kind, Arg); if (Result.isInvalid()) return true; @@ -4129,7 +4097,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult CondRes = CheckCXXBooleanCondition(Cond.take()); if (CondRes.isInvalid()) return QualType(); - Cond = move(CondRes); + Cond = CondRes; } // Assume r-value. @@ -4160,6 +4128,9 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &NonVoid = LVoid ? RHS : LHS; if (NonVoid.get()->getType()->isRecordType() && NonVoid.get()->isGLValue()) { + if (RequireNonAbstractType(QuestionLoc, NonVoid.get()->getType(), + diag::err_allocation_of_abstract_type)) + return QualType(); InitializedEntity Entity = InitializedEntity::InitializeTemporary(NonVoid.get()->getType()); NonVoid = PerformCopyInitialization(Entity, SourceLocation(), NonVoid); @@ -4302,7 +4273,11 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) { if (LTy->isRecordType()) { // The operands have class type. Make a temporary copy. + if (RequireNonAbstractType(QuestionLoc, LTy, + diag::err_allocation_of_abstract_type)) + return QualType(); InitializedEntity Entity = InitializedEntity::InitializeTemporary(LTy); + ExprResult LHSCopy = PerformCopyInitialization(Entity, SourceLocation(), LHS); @@ -4566,14 +4541,14 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, // Convert E1 to Composite1 ExprResult E1Result - = E1ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E1,1)); + = E1ToC1.Perform(*this, Entity1, Kind, E1); if (E1Result.isInvalid()) return QualType(); E1 = E1Result.takeAs<Expr>(); // Convert E2 to Composite1 ExprResult E2Result - = E2ToC1.Perform(*this, Entity1, Kind, MultiExprArg(*this,&E2,1)); + = E2ToC1.Perform(*this, Entity1, Kind, E2); if (E2Result.isInvalid()) return QualType(); E2 = E2Result.takeAs<Expr>(); @@ -4591,14 +4566,14 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc, // Convert E1 to Composite2 ExprResult E1Result - = E1ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E1, 1)); + = E1ToC2.Perform(*this, Entity2, Kind, E1); if (E1Result.isInvalid()) return QualType(); E1 = E1Result.takeAs<Expr>(); // Convert E2 to Composite2 ExprResult E2Result - = E2ToC2.Perform(*this, Entity2, Kind, MultiExprArg(*this, &E2, 1)); + = E2ToC2.Perform(*this, Entity2, Kind, E2); if (E2Result.isInvalid()) return QualType(); E2 = E2Result.takeAs<Expr>(); @@ -4839,7 +4814,8 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { BO_Comma, BO->getType(), BO->getValueKind(), BO->getObjectKind(), - BO->getOperatorLoc())); + BO->getOperatorLoc(), + BO->isFPContractable())); } } @@ -4991,7 +4967,7 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, // type C (or of pointer to a class type C), the unqualified-id is looked // up in the scope of class C. [...] ObjectType = ParsedType::make(BaseType); - return move(Base); + return Base; } ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, @@ -5056,7 +5032,8 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) return ExprError(); - if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) { + if (!ObjectType->isDependentType() && !ObjectType->isScalarType() && + !ObjectType->isVectorType()) { if (getLangOpts().MicrosoftMode && ObjectType->isVoidType()) Diag(OpLoc, diag::ext_pseudo_dtor_on_void) << Base->getSourceRange(); else @@ -5203,8 +5180,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, } else { // Resolve the template-id to a type. TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId; - ASTTemplateArgsPtr TemplateArgsPtr(*this, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); TypeResult T = ActOnTemplateIdType(TemplateId->SS, TemplateId->TemplateKWLoc, @@ -5253,8 +5229,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, } else { // Resolve the template-id to a type. TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId; - ASTTemplateArgsPtr TemplateArgsPtr(*this, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); TypeResult T = ActOnTemplateIdType(TemplateId->SS, TemplateId->TemplateKWLoc, @@ -5353,7 +5328,7 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, MarkFunctionReferenced(Exp.get()->getLocStart(), Method); CXXMemberCallExpr *CE = - new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK, + new (Context) CXXMemberCallExpr(Context, ME, MultiExprArg(), ResultType, VK, Exp.get()->getLocEnd()); return CE; } diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 8f445e2..a7fd471 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -13,6 +13,7 @@ #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" @@ -353,7 +354,7 @@ CheckExtVectorComponent(Sema &S, QualType baseType, ExprValueKind &VK, // Now look up the TypeDefDecl from the vector type. Without this, // diagostics look bad. We want extended vector types to appear built-in. for (Sema::ExtVectorDeclsType::iterator - I = S.ExtVectorDecls.begin(S.ExternalSource), + I = S.ExtVectorDecls.begin(S.getExternalSource()), E = S.ExtVectorDecls.end(); I != E; ++I) { if ((*I)->getUnderlyingType() == VT) @@ -605,7 +606,8 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, R.addDecl(ND); SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) << Name << DC << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) << ND->getDeclName(); } @@ -656,7 +658,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, } if (Result.get()) - return move(Result); + return Result; // LookupMemberExpr can modify Base, and thus change BaseType BaseType = Base->getType(); @@ -1021,7 +1023,7 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { // Do the substitution as long as the redefinition type isn't just a // possibly-qualified pointer to builtin-id or builtin-Class again. opty = redef->getAs<ObjCObjectPointerType>(); - if (opty && !opty->getObjectType()->getInterface() != 0) + if (opty && !opty->getObjectType()->getInterface()) return false; base = S.ImpCastExprToType(base.take(), redef, CK_BitCast); @@ -1272,9 +1274,23 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, if (warn) Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName(); } - return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), - MemberLoc, BaseExpr.take(), - IsArrow)); + + ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(), + MemberLoc, + BaseExpr.take(), + IsArrow); + + if (getLangOpts().ObjCAutoRefCount) { + if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + MemberLoc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(Result); + } + } + + return Owned(Result); } // Objective-C property access. @@ -1550,7 +1566,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, Id.getKind() == UnqualifiedId::IK_DestructorName) return DiagnoseDtorReference(NameInfo.getLoc(), Result.get()); - return move(Result); + return Result; } ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl, HasTrailingLParen}; @@ -1560,7 +1576,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, false, &ExtraArgs); } - return move(Result); + return Result; } static ExprResult diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 0aabf8b..e43b6bf 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -229,7 +229,7 @@ static ObjCMethodDecl *getNSNumberFactoryMethod(Sema &S, SourceLocation Loc, S.NSNumberPointer, ResultTInfo, S.NSNumberDecl, /*isInstance=*/false, /*isVariadic=*/false, - /*isSynthesized=*/false, + /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, @@ -345,7 +345,7 @@ static ExprResult CheckObjCCollectionLiteralElement(Sema &S, Expr *Element, SourceLocation()); InitializationSequence Seq(S, Entity, Kind, &Element, 1); if (!Seq.Failed()) - return Seq.Perform(S, Entity, Kind, MultiExprArg(S, &Element, 1)); + return Seq.Perform(S, Entity, Kind, Element); } Expr *OrigElement = Element; @@ -477,7 +477,7 @@ ExprResult Sema::BuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) { stringWithUTF8String, NSStringPointer, ResultTInfo, NSStringDecl, /*isInstance=*/false, /*isVariadic=*/false, - /*isSynthesized=*/false, + /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, @@ -646,7 +646,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { ResultTInfo, Context.getTranslationUnitDecl(), false /*Instance*/, false/*isVariadic*/, - /*isSynthesized=*/false, + /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, false); @@ -708,7 +708,7 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { // Check that each of the elements provided is valid in a collection literal, // performing conversions as necessary. - Expr **ElementsBuffer = Elements.get(); + Expr **ElementsBuffer = Elements.data(); for (unsigned I = 0, N = Elements.size(); I != N; ++I) { ExprResult Converted = CheckObjCCollectionLiteralElement(*this, ElementsBuffer[I], @@ -724,10 +724,8 @@ ExprResult Sema::BuildObjCArrayLiteral(SourceRange SR, MultiExprArg Elements) { Context.getObjCInterfaceType(NSArrayDecl)); return MaybeBindToTemporary( - ObjCArrayLiteral::Create(Context, - llvm::makeArrayRef(Elements.get(), - Elements.size()), - Ty, ArrayWithObjectsMethod, SR)); + ObjCArrayLiteral::Create(Context, Elements, Ty, + ArrayWithObjectsMethod, SR)); } ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, @@ -766,7 +764,7 @@ ExprResult Sema::BuildObjCDictionaryLiteral(SourceRange SR, 0 /*TypeSourceInfo */, Context.getTranslationUnitDecl(), false /*Instance*/, false/*isVariadic*/, - /*isSynthesized=*/false, + /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, false); @@ -1125,7 +1123,9 @@ void Sema::EmitRelatedResultTypeNote(const Expr *E) { bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, Expr **Args, unsigned NumArgs, - Selector Sel, ObjCMethodDecl *Method, + Selector Sel, + ArrayRef<SourceLocation> SelectorLocs, + ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage, SourceLocation lbrac, SourceLocation rbrac, QualType &ReturnType, ExprValueKind &VK) { @@ -1149,7 +1149,8 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, : diag::warn_inst_method_not_found; if (!getLangOpts().DebuggerSupport) Diag(lbrac, DiagID) - << Sel << isClassMessage << SourceRange(lbrac, rbrac); + << Sel << isClassMessage << SourceRange(SelectorLocs.front(), + SelectorLocs.back()); // In debuggers, we want to use __unknown_anytype for these // results so that clients can cast them. @@ -1304,8 +1305,8 @@ static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) { Expr *RExpr = Receiver->IgnoreParenImpCasts(); SourceLocation Loc = RExpr->getLocStart(); QualType T = RExpr->getType(); - ObjCPropertyDecl *PDecl = 0; - ObjCMethodDecl *GDecl = 0; + const ObjCPropertyDecl *PDecl = 0; + const ObjCMethodDecl *GDecl = 0; if (PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(RExpr)) { RExpr = POE->getSyntacticForm(); if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(RExpr)) { @@ -1327,34 +1328,29 @@ static void DiagnoseARCUseOfWeakReceiver(Sema &S, Expr *Receiver) { // See if receiver is a method which envokes a synthesized getter // backing a 'weak' property. ObjCMethodDecl *Method = ME->getMethodDecl(); - if (Method && Method->isSynthesized()) { - Selector Sel = Method->getSelector(); - if (Sel.getNumArgs() == 0) { - const DeclContext *Container = Method->getDeclContext(); - PDecl = - S.LookupPropertyDecl(cast<ObjCContainerDecl>(Container), - Sel.getIdentifierInfoForSlot(0)); - } + if (Method && Method->getSelector().getNumArgs() == 0) { + PDecl = Method->findPropertyDecl(); if (PDecl) T = PDecl->getType(); } } - if (T.getObjCLifetime() == Qualifiers::OCL_Weak) { - S.Diag(Loc, diag::warn_receiver_is_weak) - << ((!PDecl && !GDecl) ? 0 : (PDecl ? 1 : 2)); - if (PDecl) - S.Diag(PDecl->getLocation(), diag::note_property_declare); - else if (GDecl) - S.Diag(GDecl->getLocation(), diag::note_method_declared_at) << GDecl; - return; + if (T.getObjCLifetime() != Qualifiers::OCL_Weak) { + if (!PDecl) + return; + if (!(PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)) + return; } - - if (PDecl && - (PDecl->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)) { - S.Diag(Loc, diag::warn_receiver_is_weak) << 1; + + S.Diag(Loc, diag::warn_receiver_is_weak) + << ((!PDecl && !GDecl) ? 0 : (PDecl ? 1 : 2)); + + if (PDecl) S.Diag(PDecl->getLocation(), diag::note_property_declare); - } + else if (GDecl) + S.Diag(GDecl->getLocation(), diag::note_method_declared_at) << GDecl; + + S.Diag(Loc, diag::note_arc_assign_to_strong); } /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an @@ -1776,19 +1772,17 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, // We are in a method whose class has a superclass, so 'super' // is acting as a keyword. - if (Method->isInstanceMethod()) { - if (Sel.getMethodFamily() == OMF_dealloc) - getCurFunction()->ObjCShouldCallSuperDealloc = false; - if (Sel.getMethodFamily() == OMF_finalize) - getCurFunction()->ObjCShouldCallSuperFinalize = false; + if (Method->getSelector() == Sel) + getCurFunction()->ObjCShouldCallSuper = false; + if (Method->isInstanceMethod()) { // Since we are in an instance method, this is an instance // message to the superclass instance. QualType SuperTy = Context.getObjCInterfaceType(Super); SuperTy = Context.getObjCObjectPointerType(SuperTy); return BuildInstanceMessage(0, SuperTy, SuperLoc, Sel, /*Method=*/0, - LBracLoc, SelectorLocs, RBracLoc, move(Args)); + LBracLoc, SelectorLocs, RBracLoc, Args); } // Since we are in a class method, this is a class message to @@ -1796,7 +1790,7 @@ ExprResult Sema::ActOnSuperMessage(Scope *S, return BuildClassMessage(/*ReceiverTypeInfo=*/0, Context.getObjCInterfaceType(Super), SuperLoc, Sel, /*Method=*/0, - LBracLoc, SelectorLocs, RBracLoc, move(Args)); + LBracLoc, SelectorLocs, RBracLoc, Args); } @@ -1911,7 +1905,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, // If the receiver type is dependent, we can't type-check anything // at this point. Build a dependent expression. unsigned NumArgs = ArgsIn.size(); - Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + Expr **Args = ArgsIn.data(); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); return Owned(ObjCMessageExpr::Create(Context, ReceiverType, VK_RValue, LBracLoc, ReceiverTypeInfo, @@ -1965,8 +1959,9 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, ExprValueKind VK = VK_RValue; unsigned NumArgs = ArgsIn.size(); - Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); - if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, true, + Expr **Args = ArgsIn.data(); + if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, SelectorLocs, + Method, true, SuperLoc.isValid(), LBracLoc, RBracLoc, ReturnType, VK)) return ExprError(); @@ -2016,7 +2011,7 @@ ExprResult Sema::ActOnClassMessage(Scope *S, return BuildClassMessage(ReceiverTypeInfo, ReceiverType, /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, - LBracLoc, SelectorLocs, RBracLoc, move(Args)); + LBracLoc, SelectorLocs, RBracLoc, Args); } ExprResult Sema::BuildInstanceMessageImplicit(Expr *Receiver, @@ -2095,7 +2090,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // If the receiver is type-dependent, we can't type-check anything // at this point. Build a dependent expression. unsigned NumArgs = ArgsIn.size(); - Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + Expr **Args = ArgsIn.data(); assert(SuperLoc.isInvalid() && "Message to super with dependent type"); return Owned(ObjCMessageExpr::Create(Context, Context.DependentTy, VK_RValue, LBracLoc, Receiver, Sel, @@ -2282,7 +2277,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, LBracLoc, SelectorLocs, RBracLoc, - move(ArgsIn)); + ArgsIn); } else { // Reject other random receiver types (e.g. structs). Diag(Loc, diag::err_bad_receiver_type) @@ -2295,12 +2290,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // Check the message arguments. unsigned NumArgs = ArgsIn.size(); - Expr **Args = reinterpret_cast<Expr **>(ArgsIn.release()); + Expr **Args = ArgsIn.data(); QualType ReturnType; ExprValueKind VK = VK_RValue; bool ClassMessage = (ReceiverType->isObjCClassType() || ReceiverType->isObjCQualifiedClassType()); - if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, Method, + if (CheckMessageArgumentTypes(ReceiverType, Args, NumArgs, Sel, + SelectorLocs, Method, ClassMessage, SuperLoc.isValid(), LBracLoc, RBracLoc, ReturnType, VK)) return ExprError(); @@ -2428,6 +2424,24 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, // In ARC, check for message sends which are likely to introduce // retain cycles. checkRetainCycles(Result); + + if (!isImplicit && Method) { + if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) { + bool IsWeak = + Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak; + if (!IsWeak && Sel.isUnarySelector()) + IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak; + + if (IsWeak) { + DiagnosticsEngine::Level Level = + Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + LBracLoc); + if (Level != DiagnosticsEngine::Ignored) + getCurFunction()->recordUseOfWeak(Result, Prop); + + } + } + } } return MaybeBindToTemporary(Result); @@ -2448,7 +2462,7 @@ ExprResult Sema::ActOnInstanceMessage(Scope *S, return BuildInstanceMessage(Receiver, Receiver->getType(), /*SuperLoc=*/SourceLocation(), Sel, /*Method=*/0, - LBracLoc, SelectorLocs, RBracLoc, move(Args)); + LBracLoc, SelectorLocs, RBracLoc, Args); } enum ARCConversionTypeClass { @@ -3079,8 +3093,8 @@ Expr *Sema::stripARCUnbridgedCast(Expr *e) { return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(), gse->getControllingExpr(), - subTypes.data(), subExprs.data(), - n, gse->getDefaultLoc(), + subTypes, subExprs, + gse->getDefaultLoc(), gse->getRParenLoc(), gse->containsUnexpandedParameterPack(), gse->getResultIndex()); @@ -3101,8 +3115,8 @@ bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType, canExprType->isObjCObjectPointerType()) { if (const ObjCObjectPointerType *ObjT = canExprType->getAs<ObjCObjectPointerType>()) - if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) - return false; + if (const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl()) + return !ObjI->isArcWeakrefUnavailable(); } return true; } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 62ab1e6..3596bbf 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1316,6 +1316,8 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, // If the record is invalid, some of it's members are invalid. To avoid // confusion, we forgo checking the intializer for the entire record. if (structDecl->isInvalidDecl()) { + // Assume it was supposed to consume a single initializer. + ++Index; hadError = true; return; } @@ -1503,11 +1505,14 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef, /// corresponds to FieldName. static IndirectFieldDecl *FindIndirectFieldDesignator(FieldDecl *AnonField, IdentifierInfo *FieldName) { + if (!FieldName) + return 0; + assert(AnonField->isAnonymousStructOrUnion()); Decl *NextDecl = AnonField->getNextDeclInContext(); while (IndirectFieldDecl *IF = dyn_cast_or_null<IndirectFieldDecl>(NextDecl)) { - if (FieldName && FieldName == IF->getAnonField()->getIdentifier()) + if (FieldName == IF->getAnonField()->getIdentifier()) return IF; NextDecl = NextDecl->getNextDeclInContext(); } @@ -1521,8 +1526,8 @@ static DesignatedInitExpr *CloneDesignatedInitExpr(Sema &SemaRef, for (unsigned I = 0; I < NumIndexExprs; ++I) IndexExprs[I] = DIE->getSubExpr(I + 1); return DesignatedInitExpr::Create(SemaRef.Context, DIE->designators_begin(), - DIE->size(), IndexExprs.data(), - NumIndexExprs, DIE->getEqualOrColonLoc(), + DIE->size(), IndexExprs, + DIE->getEqualOrColonLoc(), DIE->usesGNUSyntax(), DIE->getInit()); } @@ -1562,7 +1567,7 @@ class FieldInitializerValidatorCCC : public CorrectionCandidateCallback { /// /// @param DesigIdx The index of the current designator. /// -/// @param DeclType The type of the "current object" (C99 6.7.8p17), +/// @param CurrentObjectType The type of the "current object" (C99 6.7.8p17), /// into which the designation in @p DIE should refer. /// /// @param NextField If non-NULL and the first designator in @p DIE is @@ -2068,7 +2073,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, InitListExpr *Result = new (SemaRef.Context) InitListExpr(SemaRef.Context, - InitRange.getBegin(), 0, 0, + InitRange.getBegin(), MultiExprArg(), InitRange.getEnd()); QualType ResultType = CurrentObjectType; @@ -2261,8 +2266,8 @@ ExprResult Sema::ActOnDesignatedInitializer(Designation &Desig, DesignatedInitExpr *DIE = DesignatedInitExpr::Create(Context, Designators.data(), Designators.size(), - InitExpressions.data(), InitExpressions.size(), - Loc, GNUSyntax, Init.takeAs<Expr>()); + InitExpressions, Loc, GNUSyntax, + Init.takeAs<Expr>()); if (!getLangOpts().C99) Diag(DIE->getLocStart(), diag::ext_designated_init) @@ -2814,14 +2819,6 @@ static void TryConstructorInitialization(Sema &S, assert((!InitListSyntax || (NumArgs == 1 && isa<InitListExpr>(Args[0]))) && "InitListSyntax must come with a single initializer list argument."); - // Check constructor arguments for self reference. - if (DeclaratorDecl *DD = Entity.getDecl()) - // Parameters arguments are occassionially constructed with itself, - // for instance, in recursive functions. Skip them. - if (!isa<ParmVarDecl>(DD)) - for (unsigned i = 0; i < NumArgs; ++i) - S.CheckSelfReference(DD, Args[i]); - // The type we're constructing needs to be complete. if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { Sequence.setIncompleteTypeFailure(DestType); @@ -3614,8 +3611,8 @@ static void TryValueInitialization(Sema &S, // user-provided or deleted default constructor, then the object is // zero-initialized and, if T has a non-trivial default constructor, // default-initialized; - // FIXME: The 'non-union' here is a defect (not yet assigned an issue - // number). Update the quotation when the defect is resolved. + // The 'non-union' here was removed by DR1502. The 'non-trivial default + // constructor' part was removed by DR1507. if (NeedZeroInitialization) Sequence.AddZeroInitializationStep(Entity.getType()); @@ -3703,8 +3700,14 @@ static void TryUserDefinedConversion(Sema &S, // Try to complete the type we're converting to. if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { - DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl); + DeclContext::lookup_iterator ConOrig, ConEndOrig; + llvm::tie(ConOrig, ConEndOrig) = 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); + for (SmallVector<NamedDecl*, 8>::iterator + Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end(); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -4413,7 +4416,7 @@ static ExprResult CopyObject(Sema &S, if (const RecordType *Record = T->getAs<RecordType>()) Class = cast<CXXRecordDecl>(Record->getDecl()); if (!Class) - return move(CurInit); + return CurInit; // C++0x [class.copy]p32: // When certain criteria are met, an implementation is allowed to @@ -4435,7 +4438,7 @@ static ExprResult CopyObject(Sema &S, // Make sure that the type we are copying is complete. if (S.RequireCompleteType(Loc, T, diag::err_temp_copy_incomplete)) - return move(CurInit); + return CurInit; // Perform overload resolution using the class's copy/move constructors. // Only consider constructors and constructor templates. Per @@ -4460,7 +4463,7 @@ static ExprResult CopyObject(Sema &S, CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); if (!IsExtraneousCopy || S.isSFINAEContext()) return ExprError(); - return move(CurInit); + return CurInit; case OR_Ambiguous: S.Diag(Loc, diag::err_temp_copy_ambiguous) @@ -4478,7 +4481,7 @@ static ExprResult CopyObject(Sema &S, } CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); - ASTOwningVector<Expr*> ConstructorArgs(S); + SmallVector<Expr*, 8> ConstructorArgs; CurInit.release(); // Ownership transferred into MultiExprArg, below. S.CheckConstructorAccess(Loc, Constructor, Entity, @@ -4521,7 +4524,7 @@ static ExprResult CopyObject(Sema &S, // Actually perform the constructor call. CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable, - move_arg(ConstructorArgs), + ConstructorArgs, HadMultipleCandidates, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, @@ -4530,7 +4533,7 @@ static ExprResult CopyObject(Sema &S, // If we're supposed to bind temporaries, do so. if (!CurInit.isInvalid() && shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); - return move(CurInit); + return CurInit; } /// \brief Check whether elidable copy construction for binding a reference to @@ -4619,7 +4622,7 @@ PerformConstructorInitialization(Sema &S, bool HadMultipleCandidates = Step.Function.HadMultipleCandidates; // Build a call to the selected constructor. - ASTOwningVector<Expr*> ConstructorArgs(S); + SmallVector<Expr*, 8> ConstructorArgs; SourceLocation Loc = (Kind.isCopyInit() && Kind.getEqualLoc().isValid()) ? Kind.getEqualLoc() : Kind.getLocation(); @@ -4648,7 +4651,7 @@ PerformConstructorInitialization(Sema &S, // Determine the arguments required to actually perform the constructor // call. - if (S.CompleteConstructorCall(Constructor, move(Args), + if (S.CompleteConstructorCall(Constructor, Args, Loc, ConstructorArgs, AllowExplicitConv)) return ExprError(); @@ -4660,8 +4663,6 @@ PerformConstructorInitialization(Sema &S, (Kind.getKind() == InitializationKind::IK_Direct || Kind.getKind() == InitializationKind::IK_Value)))) { // An explicitly-constructed temporary, e.g., X(1, 2). - unsigned NumExprs = ConstructorArgs.size(); - Expr **Exprs = (Expr **)ConstructorArgs.take(); S.MarkFunctionReferenced(Loc, Constructor); S.DiagnoseUseOfDecl(Constructor, Loc); @@ -4675,8 +4676,7 @@ PerformConstructorInitialization(Sema &S, CurInit = S.Owned(new (S.Context) CXXTemporaryObjectExpr(S.Context, Constructor, TSInfo, - Exprs, - NumExprs, + ConstructorArgs, ParenRange, HadMultipleCandidates, ConstructorInitRequiresZeroInit)); @@ -4702,7 +4702,7 @@ PerformConstructorInitialization(Sema &S, if (Entity.allowsNRVO()) CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), Constructor, /*Elidable=*/true, - move_arg(ConstructorArgs), + ConstructorArgs, HadMultipleCandidates, ConstructorInitRequiresZeroInit, ConstructKind, @@ -4710,7 +4710,7 @@ PerformConstructorInitialization(Sema &S, else CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), Constructor, - move_arg(ConstructorArgs), + ConstructorArgs, HadMultipleCandidates, ConstructorInitRequiresZeroInit, ConstructKind, @@ -4727,7 +4727,7 @@ PerformConstructorInitialization(Sema &S, if (shouldBindAsTemporary(Entity)) CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); - return move(CurInit); + return CurInit; } /// Determine whether the specified InitializedEntity definitely has a lifetime @@ -4775,7 +4775,7 @@ InitializationSequence::Perform(Sema &S, QualType *ResultType) { if (Failed()) { unsigned NumArgs = Args.size(); - Diagnose(S, Entity, Kind, (Expr **)Args.release(), NumArgs); + Diagnose(S, Entity, Kind, Args.data(), NumArgs); return ExprError(); } @@ -4795,7 +4795,7 @@ InitializationSequence::Perform(Sema &S, // introduced and such). So, we fall back to making the array // type a dependently-sized array type with no specified // bound. - if (isa<InitListExpr>((Expr *)Args.get()[0])) { + if (isa<InitListExpr>((Expr *)Args[0])) { SourceRange Brackets; // Scavange the location of the brackets from the entity, if we can. @@ -4823,12 +4823,12 @@ InitializationSequence::Perform(Sema &S, // Rebuild the ParenListExpr. SourceRange ParenRange = Kind.getParenRange(); return S.ActOnParenListExpr(ParenRange.getBegin(), ParenRange.getEnd(), - move(Args)); + Args); } assert(Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast() || Kind.getKind() == InitializationKind::IK_DirectList); - return ExprResult(Args.release()[0]); + return ExprResult(Args[0]); } // No steps means no initialization. @@ -4836,22 +4836,22 @@ InitializationSequence::Perform(Sema &S, return S.Owned((Expr *)0); if (S.getLangOpts().CPlusPlus0x && Entity.getType()->isReferenceType() && - Args.size() == 1 && isa<InitListExpr>(Args.get()[0]) && + Args.size() == 1 && isa<InitListExpr>(Args[0]) && Entity.getKind() != InitializedEntity::EK_Parameter) { // Produce a C++98 compatibility warning if we are initializing a reference // from an initializer list. For parameters, we produce a better warning // elsewhere. - Expr *Init = Args.get()[0]; + Expr *Init = Args[0]; S.Diag(Init->getLocStart(), diag::warn_cxx98_compat_reference_list_init) << Init->getSourceRange(); } // Diagnose cases where we initialize a pointer to an array temporary, and the // pointer obviously outlives the temporary. - if (Args.size() == 1 && Args.get()[0]->getType()->isArrayType() && + if (Args.size() == 1 && Args[0]->getType()->isArrayType() && Entity.getType()->isPointerType() && InitializedEntityOutlivesFullExpression(Entity)) { - Expr *Init = Args.get()[0]; + Expr *Init = Args[0]; Expr::LValueClassification Kind = Init->ClassifyLValue(S.Context); if (Kind == Expr::LV_ClassTemporary || Kind == Expr::LV_ArrayTemporary) S.Diag(Init->getLocStart(), diag::warn_temporary_array_to_pointer_decay) @@ -4897,7 +4897,7 @@ InitializationSequence::Perform(Sema &S, case SK_ProduceObjCObject: case SK_StdInitializerList: { assert(Args.size() == 1); - CurInit = Args.get()[0]; + CurInit = Args[0]; if (!CurInit.get()) return ExprError(); break; } @@ -4924,7 +4924,7 @@ InitializationSequence::Perform(Sema &S, // initializer to reflect that choice. S.CheckAddressOfMemberAccess(CurInit.get(), Step->Function.FoundDecl); S.DiagnoseUseOfDecl(Step->Function.FoundDecl, Kind.getLocation()); - CurInit = S.FixOverloadedFunctionReference(move(CurInit), + CurInit = S.FixOverloadedFunctionReference(CurInit, Step->Function.FoundDecl, Step->Function.Function); break; @@ -5016,7 +5016,7 @@ InitializationSequence::Perform(Sema &S, break; case SK_ExtraneousCopyToTemporary: - CurInit = CopyObject(S, Step->Type, Entity, move(CurInit), + CurInit = CopyObject(S, Step->Type, Entity, CurInit, /*IsExtraneousCopy=*/true); break; @@ -5031,7 +5031,7 @@ InitializationSequence::Perform(Sema &S, bool CreatedObject = false; if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) { // Build a call to the selected constructor. - ASTOwningVector<Expr*> ConstructorArgs(S); + SmallVector<Expr*, 8> ConstructorArgs; SourceLocation Loc = CurInit.get()->getLocStart(); CurInit.release(); // Ownership transferred into MultiExprArg, below. @@ -5045,7 +5045,7 @@ InitializationSequence::Perform(Sema &S, // Build an expression that constructs a temporary. CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor, - move_arg(ConstructorArgs), + ConstructorArgs, HadMultipleCandidates, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, @@ -5079,7 +5079,7 @@ InitializationSequence::Perform(Sema &S, FoundFn, Conversion); if(CurInitExprRes.isInvalid()) return ExprError(); - CurInit = move(CurInitExprRes); + CurInit = CurInitExprRes; // Build the actual call to the conversion function. CurInit = S.BuildCXXMemberCallExpr(CurInit.get(), FoundFn, Conversion, @@ -5115,7 +5115,7 @@ InitializationSequence::Perform(Sema &S, CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>()); if (RequiresCopy) CurInit = CopyObject(S, Entity.getType().getNonReferenceType(), Entity, - move(CurInit), /*IsExtraneousCopy=*/false); + CurInit, /*IsExtraneousCopy=*/false); break; } @@ -5144,7 +5144,7 @@ InitializationSequence::Perform(Sema &S, getAssignmentAction(Entity), CCK); if (CurInitExprRes.isInvalid()) return ExprError(); - CurInit = move(CurInitExprRes); + CurInit = CurInitExprRes; break; } @@ -5195,13 +5195,13 @@ InitializationSequence::Perform(Sema &S, Entity.getType().getNonReferenceType()); bool UseTemporary = Entity.getType()->isReferenceType(); assert(Args.size() == 1 && "expected a single argument for list init"); - InitListExpr *InitList = cast<InitListExpr>(Args.get()[0]); + InitListExpr *InitList = cast<InitListExpr>(Args[0]); S.Diag(InitList->getExprLoc(), diag::warn_cxx98_compat_ctor_list_init) << InitList->getSourceRange(); MultiExprArg Arg(InitList->getInits(), InitList->getNumInits()); CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, - Kind, move(Arg), *Step, + Kind, Arg, *Step, ConstructorInitRequiresZeroInit); break; } @@ -5214,7 +5214,7 @@ InitializationSequence::Perform(Sema &S, Expr *E = CurInit.take(); InitListExpr *Syntactic = Step->WrappingSyntacticList; InitListExpr *ILE = new (S.Context) InitListExpr(S.Context, - Syntactic->getLBraceLoc(), &E, 1, Syntactic->getRBraceLoc()); + Syntactic->getLBraceLoc(), E, Syntactic->getRBraceLoc()); ILE->setSyntacticForm(Syntactic); ILE->setType(E->getType()); ILE->setValueKind(E->getValueKind()); @@ -5234,7 +5234,7 @@ InitializationSequence::Perform(Sema &S, bool UseTemporary = Entity.getType()->isReferenceType(); CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity : Entity, - Kind, move(Args), *Step, + Kind, Args, *Step, ConstructorInitRequiresZeroInit); break; } @@ -5268,15 +5268,15 @@ InitializationSequence::Perform(Sema &S, case SK_CAssignment: { QualType SourceType = CurInit.get()->getType(); - ExprResult Result = move(CurInit); + ExprResult Result = CurInit; Sema::AssignConvertType ConvTy = S.CheckSingleAssignmentConstraints(Step->Type, Result); if (Result.isInvalid()) return ExprError(); - CurInit = move(Result); + CurInit = Result; // If this is a call, allow conversion to a transparent union. - ExprResult CurInitExprRes = move(CurInit); + ExprResult CurInitExprRes = CurInit; if (ConvTy != Sema::Compatible && Entity.getKind() == InitializedEntity::EK_Parameter && S.CheckTransparentUnionArgumentConstraints(Step->Type, CurInitExprRes) @@ -5284,7 +5284,7 @@ InitializationSequence::Perform(Sema &S, ConvTy = Sema::Compatible; if (CurInitExprRes.isInvalid()) return ExprError(); - CurInit = move(CurInitExprRes); + CurInit = CurInitExprRes; bool Complained; if (S.DiagnoseAssignmentResult(ConvTy, Kind.getLocation(), @@ -5398,7 +5398,7 @@ InitializationSequence::Perform(Sema &S, } InitListExpr *Semantic = new (S.Context) InitListExpr(S.Context, ILE->getLBraceLoc(), - Converted.data(), NumInits, ILE->getRBraceLoc()); + Converted, ILE->getRBraceLoc()); Semantic->setSyntacticForm(ILE); Semantic->setType(Dest); Semantic->setInitializesStdInitializerList(); @@ -5415,7 +5415,7 @@ InitializationSequence::Perform(Sema &S, cast<FieldDecl>(Entity.getDecl()), CurInit.get()); - return move(CurInit); + return CurInit; } //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 6414c6f..15cd2a7 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -22,13 +22,14 @@ using namespace clang; using namespace sema; CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, + TypeSourceInfo *Info, bool KnownDependent) { DeclContext *DC = CurContext; while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); // Start constructing the lambda class. - CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, + CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info, IntroducerRange.getBegin(), KnownDependent); DC->addDecl(Class); @@ -369,15 +370,13 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (!TmplScope->decl_empty()) KnownDependent = true; - CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, KnownDependent); - // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; bool ExplicitParams = true; bool ExplicitResultType = true; bool ContainsUnexpandedParameterPack = false; SourceLocation EndLoc; - llvm::ArrayRef<ParmVarDecl *> Params; + llvm::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 @@ -410,17 +409,25 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, ExplicitResultType = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType() != Context.DependentTy; - - TypeLoc TL = MethodTyInfo->getTypeLoc(); - FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL); - Params = llvm::ArrayRef<ParmVarDecl *>(Proto.getParmArray(), - Proto.getNumArgs()); + + if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && + cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) { + // Empty arg list, don't push any params. + checkVoidParamDecl(cast<ParmVarDecl>(FTI.ArgInfo[0].Param)); + } else { + Params.reserve(FTI.NumArgs); + for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) + Params.push_back(cast<ParmVarDecl>(FTI.ArgInfo[i].Param)); + } // Check for unexpanded parameter packs in the method type. if (MethodTyInfo->getType()->containsUnexpandedParameterPack()) ContainsUnexpandedParameterPack = true; } - + + CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, + KnownDependent); + CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params); @@ -528,6 +535,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, continue; } + // Ignore invalid decls; they'll just confuse the code later. + if (Var->isInvalidDecl()) + continue; + if (!Var->hasLocalStorage()) { Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id; Diag(Var->getLocation(), diag::note_previous_decl) << C->Id; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index dad196b..f6987e7 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -707,7 +707,7 @@ static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { // result), perform template argument deduction and place the // specialization into the result set. We do this to avoid forcing all // callers to perform special deduction for conversion functions. - TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc()); + TemplateDeductionInfo Info(R.getNameLoc()); FunctionDecl *Specialization = 0; const FunctionProtoType *ConvProto @@ -1725,15 +1725,17 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { namespace { struct AssociatedLookup { - AssociatedLookup(Sema &S, + AssociatedLookup(Sema &S, SourceLocation InstantiationLoc, Sema::AssociatedNamespaceSet &Namespaces, Sema::AssociatedClassSet &Classes) - : S(S), Namespaces(Namespaces), Classes(Classes) { + : S(S), Namespaces(Namespaces), Classes(Classes), + InstantiationLoc(InstantiationLoc) { } Sema &S; Sema::AssociatedNamespaceSet &Namespaces; Sema::AssociatedClassSet &Classes; + SourceLocation InstantiationLoc; }; } @@ -1796,6 +1798,7 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::Expression: + case TemplateArgument::NullPtr: // [Note: non-type template arguments do not contribute to the set of // associated namespaces. ] break; @@ -1864,8 +1867,10 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, // Only recurse into base classes for complete types. if (!Class->hasDefinition()) { - // FIXME: we might need to instantiate templates here - return; + QualType type = Result.S.Context.getTypeDeclType(Class); + if (Result.S.RequireCompleteType(Result.InstantiationLoc, type, + /*no diagnostic*/ 0)) + return; } // Add direct and indirect base classes along with their associated @@ -2069,13 +2074,15 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { /// namespaces searched by argument-dependent lookup /// (C++ [basic.lookup.argdep]) for a given set of arguments. void -Sema::FindAssociatedClassesAndNamespaces(llvm::ArrayRef<Expr *> Args, +Sema::FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, + llvm::ArrayRef<Expr *> Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses) { AssociatedNamespaces.clear(); AssociatedClasses.clear(); - AssociatedLookup Result(*this, AssociatedNamespaces, AssociatedClasses); + AssociatedLookup Result(*this, InstantiationLoc, + AssociatedNamespaces, AssociatedClasses); // C++ [basic.lookup.koenig]p2: // For each argument type T in the function call, there is a set @@ -2642,17 +2649,14 @@ void ADLResult::insert(NamedDecl *New) { void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, SourceLocation Loc, llvm::ArrayRef<Expr *> Args, - ADLResult &Result, - bool StdNamespaceIsAssociated) { + ADLResult &Result) { // Find all of the associated namespaces and classes based on the // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; AssociatedClassSet AssociatedClasses; - FindAssociatedClassesAndNamespaces(Args, + FindAssociatedClassesAndNamespaces(Loc, Args, AssociatedNamespaces, AssociatedClasses); - if (StdNamespaceIsAssociated && StdNamespace) - AssociatedNamespaces.insert(getStdNamespace()); QualType T1, T2; if (Operator) { @@ -2661,13 +2665,6 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, T2 = Args[1]->getType(); } - // Try to complete all associated classes, in case they contain a - // declaration of a friend function. - for (AssociatedClassSet::iterator C = AssociatedClasses.begin(), - CEnd = AssociatedClasses.end(); - C != CEnd; ++C) - RequireCompleteType(Loc, Context.getRecordType(*C), 0); - // C++ [basic.lookup.argdep]p3: // Let X be the lookup set produced by unqualified lookup (3.4.1) // and let Y be the lookup set produced by argument dependent @@ -4056,7 +4053,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (IsUnqualifiedLookup) UnqualifiedTyposCorrected[Typo] = Result; - return Result; + TypoCorrection TC = Result; + TC.setCorrectionRange(SS, TypoName); + return TC; } else if (BestResults.size() > 1 // Ugly hack equivalent to CTC == CTC_ObjCMessageReceiver; @@ -4076,7 +4075,9 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, if (IsUnqualifiedLookup) UnqualifiedTyposCorrected[Typo] = BestResults["super"].front(); - return BestResults["super"].front(); + TypoCorrection TC = BestResults["super"].front(); + TC.setCorrectionRange(SS, TypoName); + return TC; } // If this was an unqualified lookup and we believe the callback object did diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 27deab2..8d70860 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -22,6 +22,7 @@ #include "clang/Basic/SourceManager.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallString.h" +#include "clang/Lex/Preprocessor.h" using namespace clang; @@ -43,7 +44,7 @@ static Qualifiers::ObjCLifetime getImpliedARCOwnership( if (attrs & (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong | ObjCPropertyDecl::OBJC_PR_copy)) { - return type->getObjCARCImplicitLifetime(); + return Qualifiers::OCL_Strong; } else if (attrs & ObjCPropertyDecl::OBJC_PR_weak) { return Qualifiers::OCL_Weak; } else if (attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) { @@ -102,6 +103,15 @@ static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { << propertyLifetime; } +static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) { + if ((S.getLangOpts().getGC() != LangOptions::NonGC && + T.isObjCGCWeak()) || + (S.getLangOpts().ObjCAutoRefCount && + T.getObjCLifetime() == Qualifiers::OCL_Weak)) + return ObjCDeclSpec::DQ_PR_weak; + return 0; +} + Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, FieldDeclarator &FD, @@ -114,12 +124,8 @@ Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, unsigned Attributes = ODS.getPropertyAttributes(); TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); QualType T = TSI->getType(); - if ((getLangOpts().getGC() != LangOptions::NonGC && - T.isObjCGCWeak()) || - (getLangOpts().ObjCAutoRefCount && - T.getObjCLifetime() == Qualifiers::OCL_Weak)) - Attributes |= ObjCDeclSpec::DQ_PR_weak; - + Attributes |= deduceWeakPropertyFromType(*this, T); + bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || // default is readwrite! !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); @@ -236,6 +242,15 @@ static bool LocPropertyAttribute( ASTContext &Context, const char *attrName, } +static unsigned getOwnershipRule(unsigned attr) { + return attr & (ObjCPropertyDecl::OBJC_PR_assign | + ObjCPropertyDecl::OBJC_PR_retain | + ObjCPropertyDecl::OBJC_PR_copy | + ObjCPropertyDecl::OBJC_PR_weak | + ObjCPropertyDecl::OBJC_PR_strong | + ObjCPropertyDecl::OBJC_PR_unsafe_unretained); +} + Decl * Sema::HandlePropertyInClassExtension(Scope *S, SourceLocation AtLoc, @@ -335,6 +350,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, Diag(AtLoc, diag::err_type_mismatch_continuation_class) << PDecl->getType(); Diag(PIDecl->getLocation(), diag::note_property_declare); + return 0; } } @@ -342,13 +358,11 @@ Sema::HandlePropertyInClassExtension(Scope *S, // with continuation class's readwrite property attribute! unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { - unsigned retainCopyNonatomic = - (ObjCPropertyDecl::OBJC_PR_retain | - ObjCPropertyDecl::OBJC_PR_strong | - ObjCPropertyDecl::OBJC_PR_copy | - ObjCPropertyDecl::OBJC_PR_nonatomic); - if ((Attributes & retainCopyNonatomic) != - (PIkind & retainCopyNonatomic)) { + PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType()); + unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes); + unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind); + if (PrimaryClassMemoryModel && ClassExtensionMemoryModel && + (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) { Diag(AtLoc, diag::warn_property_attr_mismatch); Diag(PIDecl->getLocation(), diag::note_property_declare); } @@ -397,6 +411,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, Diag(AtLoc, diag) << CCPrimary->getDeclName(); Diag(PIDecl->getLocation(), diag::note_property_declare); + return 0; } *isOverridingProperty = true; // Make sure setter decl is synthesized, and added to primary class's list. @@ -405,7 +420,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl()); if (ASTMutationListener *L = Context.getASTMutationListener()) L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl); - return 0; + return PDecl; } ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, @@ -543,6 +558,23 @@ static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, ivarLifetime == Qualifiers::OCL_Autoreleasing) return; + // If the ivar is private, and it's implicitly __unsafe_unretained + // becaues of its type, then pretend it was actually implicitly + // __strong. This is only sound because we're processing the + // property implementation before parsing any method bodies. + if (ivarLifetime == Qualifiers::OCL_ExplicitNone && + propertyLifetime == Qualifiers::OCL_Strong && + ivar->getAccessControl() == ObjCIvarDecl::Private) { + SplitQualType split = ivarType.split(); + if (split.Quals.hasObjCLifetime()) { + assert(ivarType->isObjCARCImplicitlyUnretainedType()); + split.Quals.setObjCLifetime(Qualifiers::OCL_Strong); + ivarType = S.Context.getQualifiedType(split); + ivar->setType(ivarType); + return; + } + } + switch (propertyLifetime) { case Qualifiers::OCL_Strong: S.Diag(propertyImplLoc, diag::err_arc_strong_property_ownership) @@ -632,7 +664,13 @@ DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl, // property. if (Attributes & ObjCDeclSpec::DQ_PR_readonly) { if (!classExtPropertyAttr || - (classExtPropertyAttr & ObjCDeclSpec::DQ_PR_readwrite)) + (classExtPropertyAttr & + (ObjCDeclSpec::DQ_PR_readwrite| + ObjCDeclSpec::DQ_PR_assign | + ObjCDeclSpec::DQ_PR_unsafe_unretained | + ObjCDeclSpec::DQ_PR_copy | + ObjCDeclSpec::DQ_PR_retain | + ObjCDeclSpec::DQ_PR_strong))) continue; warn = true; break; @@ -857,13 +895,15 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (lifetime == Qualifiers::OCL_Weak) { bool err = false; if (const ObjCObjectPointerType *ObjT = - PropertyIvarType->getAs<ObjCObjectPointerType>()) - if (ObjT->getInterfaceDecl()->isArcWeakrefUnavailable()) { + PropertyIvarType->getAs<ObjCObjectPointerType>()) { + const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl(); + if (ObjI && ObjI->isArcWeakrefUnavailable()) { Diag(PropertyDiagLoc, diag::err_arc_weak_unavailable_property); Diag(property->getLocation(), diag::note_property_declare); err = true; } - if (!err && !getLangOpts().ObjCRuntimeHasWeak) { + } + if (!err && !getLangOpts().ObjCARCWeak) { Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime); Diag(property->getLocation(), diag::note_property_declare); } @@ -891,7 +931,6 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Ivar->setInvalidDecl(); ClassImpDecl->addDecl(Ivar); IDecl->makeDeclVisibleInContext(Ivar); - property->setPropertyIvarDecl(Ivar); if (getLangOpts().ObjCRuntime.isFragile()) Diag(PropertyDiagLoc, diag::error_missing_property_ivar_decl) @@ -907,14 +946,15 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, << Ivar << Ivar->getName(); // Note! I deliberately want it to fall thru so more errors are caught. } + property->setPropertyIvarDecl(Ivar); + QualType IvarType = Context.getCanonicalType(Ivar->getType()); // Check that type of property and its ivar are type compatible. if (!Context.hasSameType(PropertyIvarType, IvarType)) { - compat = false; if (isa<ObjCObjectPointerType>(PropertyIvarType) && isa<ObjCObjectPointerType>(IvarType)) - compat = + compat = Context.canAssignObjCInterfaces( PropertyIvarType->getAs<ObjCObjectPointerType>(), IvarType->getAs<ObjCObjectPointerType>()); @@ -988,19 +1028,21 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, // For Objective-C++, need to synthesize the AST for the IVAR object to be // returned by the getter as it must conform to C++'s copy-return rules. // FIXME. Eventually we want to do this for Objective-C as well. + SynthesizedFunctionScope Scope(*this, getterMethod); ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), - VK_RValue, SourceLocation()); + VK_RValue, PropertyDiagLoc); + MarkDeclRefReferenced(SelfExpr); Expr *IvarRefExpr = - new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, SelfExpr, true, true); ExprResult Res = PerformCopyInitialization(InitializedEntity::InitializeResult( - SourceLocation(), + PropertyDiagLoc, getterMethod->getResultType(), /*NRVO=*/false), - SourceLocation(), + PropertyDiagLoc, Owned(IvarRefExpr)); if (!Res.isInvalid()) { Expr *ResExpr = Res.takeAs<Expr>(); @@ -1021,19 +1063,22 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && Ivar->getType()->isRecordType()) { // FIXME. Eventually we want to do this for Objective-C as well. + SynthesizedFunctionScope Scope(*this, setterMethod); ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); DeclRefExpr *SelfExpr = new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(), - VK_RValue, SourceLocation()); + VK_RValue, PropertyDiagLoc); + MarkDeclRefReferenced(SelfExpr); Expr *lhs = - new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, + new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc, SelfExpr, true, true); ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); ParmVarDecl *Param = (*P); QualType T = Param->getType().getNonReferenceType(); - Expr *rhs = new (Context) DeclRefExpr(Param, false, T, - VK_LValue, SourceLocation()); - ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), + DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T, + VK_LValue, PropertyDiagLoc); + MarkDeclRefReferenced(rhs); + ExprResult Res = BuildBinOp(S, PropertyDiagLoc, BO_Assign, lhs, rhs); if (property->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_atomic) { @@ -1043,7 +1088,7 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee()) if (!FuncDecl->isTrivial()) if (property->getType()->isReferenceType()) { - Diag(PropertyLoc, + Diag(PropertyDiagLoc, diag::err_atomic_property_nontrivial_assign_op) << property->getType(); Diag(FuncDecl->getLocStart(), @@ -1395,8 +1440,8 @@ 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. void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) { + ObjCContainerDecl::PropertyMap &PropMap, + ObjCContainerDecl::PropertyMap &SuperPropMap) { if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), E = IDecl->prop_end(); P != E; ++P) { @@ -1442,118 +1487,38 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, } } -/// CollectClassPropertyImplementations - This routine collects list of -/// properties to be implemented in the class. This includes, class's -/// and its conforming protocols' properties. -static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { - if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { - for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), - E = IDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; - PropMap[Prop->getIdentifier()] = Prop; - } - for (ObjCInterfaceDecl::all_protocol_iterator - PI = IDecl->all_referenced_protocol_begin(), - E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) - CollectClassPropertyImplementations((*PI), PropMap); - } - else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; - if (!PropMap.count(Prop->getIdentifier())) - PropMap[Prop->getIdentifier()] = Prop; - } - // scan through protocol's protocols. - for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), - E = PDecl->protocol_end(); PI != E; ++PI) - CollectClassPropertyImplementations((*PI), PropMap); - } -} - /// CollectSuperClassPropertyImplementations - This routine collects list of /// properties to be implemented in super class(s) and also coming from their /// conforming protocols. static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { + ObjCInterfaceDecl::PropertyMap &PropMap) { if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { while (SDecl) { - CollectClassPropertyImplementations(SDecl, PropMap); + SDecl->collectPropertiesToImplement(PropMap); SDecl = SDecl->getSuperClass(); } } } -/// LookupPropertyDecl - Looks up a property in the current class and all -/// its protocols. -ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, - IdentifierInfo *II) { - if (const ObjCInterfaceDecl *IDecl = - dyn_cast<ObjCInterfaceDecl>(CDecl)) { - for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), - E = IDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; - if (Prop->getIdentifier() == II) - return Prop; - } - // scan through class's protocols. - for (ObjCInterfaceDecl::all_protocol_iterator - PI = IDecl->all_referenced_protocol_begin(), - E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) { - ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); - if (Prop) - return Prop; - } - } - else if (const ObjCProtocolDecl *PDecl = - dyn_cast<ObjCProtocolDecl>(CDecl)) { - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; - if (Prop->getIdentifier() == II) - return Prop; - } - // scan through protocol's protocols. - for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), - E = PDecl->protocol_end(); PI != E; ++PI) { - ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); - if (Prop) - return Prop; - } - } - return 0; -} - -static IdentifierInfo * getDefaultSynthIvarName(ObjCPropertyDecl *Prop, - ASTContext &Ctx) { - SmallString<128> ivarName; - { - llvm::raw_svector_ostream os(ivarName); - os << '_' << Prop->getIdentifier()->getName(); - } - return &Ctx.Idents.get(ivarName.str()); -} - /// \brief Default synthesizes all properties which must be synthesized /// in class's \@implementation. void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCInterfaceDecl *IDecl) { - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; - CollectClassPropertyImplementations(IDecl, PropMap); + ObjCInterfaceDecl::PropertyMap PropMap; + IDecl->collectPropertiesToImplement(PropMap); if (PropMap.empty()) return; - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; + ObjCInterfaceDecl::PropertyMap SuperPropMap; CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); - for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator + for (ObjCInterfaceDecl::PropertyMap::iterator P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { ObjCPropertyDecl *Prop = P->second; // If property to be implemented in the super class, ignore. if (SuperPropMap[Prop->getIdentifier()]) continue; - // Is there a matching propery synthesize/dynamic? + // Is there a matching property synthesize/dynamic? if (Prop->isInvalidDecl() || Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) @@ -1583,7 +1548,7 @@ void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl, ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), true, /* property = */ Prop->getIdentifier(), - /* ivar = */ getDefaultSynthIvarName(Prop, Context), + /* ivar = */ Prop->getDefaultSynthIvarName(Context), Prop->getLocation())); if (PIDecl) { Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis); @@ -1606,11 +1571,11 @@ void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) { void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl *CDecl, const SelectorSet &InsMap) { - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; + ObjCContainerDecl::PropertyMap SuperPropMap; if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; + ObjCContainerDecl::PropertyMap PropMap; CollectImmediateProperties(CDecl, PropMap, SuperPropMap); if (PropMap.empty()) return; @@ -1621,7 +1586,7 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, EI = IMPDecl->propimpl_end(); I != EI; ++I) PropImplMap.insert(I->getPropertyDecl()); - for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator + for (ObjCContainerDecl::PropertyMap::iterator P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { ObjCPropertyDecl *Prop = P->second; // Is there a matching propery synthesize/dynamic? @@ -1847,7 +1812,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, property->getGetterName(), property->getType(), 0, CD, /*isInstance=*/true, - /*isVariadic=*/false, /*isSynthesized=*/true, + /*isVariadic=*/false, /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) ? @@ -1867,7 +1832,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, } else // A user declared getter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation - GetterMethod->setSynthesized(true); + GetterMethod->setPropertyAccessor(true); property->setGetterMethodDecl(GetterMethod); // Skip setter if property is read-only. @@ -1885,7 +1850,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCMethodDecl::Create(Context, Loc, Loc, property->getSetterName(), Context.VoidTy, 0, CD, /*isInstance=*/true, /*isVariadic=*/false, - /*isSynthesized=*/true, + /*isPropertyAccessor=*/true, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, (property->getPropertyImplementation() == @@ -1916,7 +1881,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, } else // A user declared setter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation - SetterMethod->setSynthesized(true); + SetterMethod->setPropertyAccessor(true); property->setSetterMethodDecl(SetterMethod); } // Add any synthesized methods to the global pool. This allows us to @@ -2121,7 +2086,9 @@ void Sema::CheckObjCPropertyAttributes(Decl *PDecl, // issue any warning. if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC) ; - else { + else if (propertyInPrimaryClass) { + // Don't issue warning on property with no life time in class + // extension as it is inherited from property in primary class. // Skip this warning in gc-only mode. if (getLangOpts().getGC() != LangOptions::GCOnly) Diag(Loc, diag::warn_objc_property_no_assignment_attribute); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 9382f7d..9111878 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -49,7 +49,7 @@ CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, bool HadMultipleCandidates, E = S.DefaultFunctionArrayConversion(E.take()); if (E.isInvalid()) return ExprError(); - return move(E); + return E; } static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, @@ -555,6 +555,7 @@ static MakeDeductionFailureInfo(ASTContext &Context, Result.Data = 0; switch (TDK) { case Sema::TDK_Success: + case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: @@ -597,6 +598,7 @@ static MakeDeductionFailureInfo(ASTContext &Context, void OverloadCandidate::DeductionFailureInfo::Destroy() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: + case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_Incomplete: case Sema::TDK_TooManyArguments: @@ -637,6 +639,7 @@ TemplateParameter OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { 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: @@ -664,6 +667,7 @@ 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: @@ -688,6 +692,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: + case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_Incomplete: case Sema::TDK_TooManyArguments: @@ -713,6 +718,7 @@ const TemplateArgument * OverloadCandidate::DeductionFailureInfo::getSecondArg() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: + case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_Incomplete: case Sema::TDK_TooManyArguments: @@ -734,13 +740,17 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { return 0; } -void OverloadCandidateSet::clear() { +void OverloadCandidateSet::destroyCandidates() { for (iterator i = begin(), e = end(); i != e; ++i) { for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii) i->Conversions[ii].~ImplicitConversionSequence(); if (!i->Viable && i->FailureKind == ovl_fail_bad_deduction) i->DeductionFailure.Destroy(); } +} + +void OverloadCandidateSet::clear() { + destroyCandidates(); NumInlineSequences = 0; Candidates.clear(); Functions.clear(); @@ -1668,7 +1678,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { return To->getKind() == BuiltinType::UInt; } - // C++0x [conv.prom]p3: + // C++11 [conv.prom]p3: // A prvalue of an unscoped enumeration type whose underlying type is not // fixed (7.2) can be converted to an rvalue a prvalue of the first of the // following types that can represent all the values of the enumeration @@ -1680,12 +1690,26 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // with lowest integer conversion rank (4.13) greater than the rank of long // long in which all the values of the enumeration can be represented. If // there are two such extended types, the signed one is chosen. + // C++11 [conv.prom]p4: + // A prvalue of an unscoped enumeration type whose underlying type is fixed + // can be converted to a prvalue of its underlying type. Moreover, if + // integral promotion can be applied to its underlying type, a prvalue of an + // unscoped enumeration type whose underlying type is fixed can also be + // converted to a prvalue of the promoted underlying type. if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) { // C++0x 7.2p9: Note that this implicit enum to int conversion is not // provided for a scoped enumeration. if (FromEnumType->getDecl()->isScoped()) return false; + // We can perform an integral promotion to the underlying type of the enum, + // even if that's not the promoted type. + if (FromEnumType->getDecl()->isFixed()) { + QualType Underlying = FromEnumType->getDecl()->getIntegerType(); + return Context.hasSameUnqualifiedType(Underlying, ToType) || + IsIntegralPromotion(From, Underlying, ToType); + } + // We have already pre-calculated the promotion type, so this is trivial. if (ToType->isIntegerType() && !RequireCompleteType(From->getLocStart(), FromType, 0)) @@ -2899,8 +2923,6 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, case OR_Success: { // Record the standard conversion we used and the conversion function. CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); - S.MarkFunctionReferenced(From->getLocStart(), Constructor); - QualType ThisType = Constructor->getThisType(S.Context); // Initializer lists don't have conversions as such. User.Before.setAsIdentityConversion(); @@ -3081,8 +3103,6 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Best->Function)) { - S.MarkFunctionReferenced(From->getLocStart(), Constructor); - // C++ [over.ics.user]p1: // If the user-defined conversion is specified by a // constructor (12.3.1), the initial standard conversion @@ -3111,8 +3131,6 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { - S.MarkFunctionReferenced(From->getLocStart(), Conversion); - // C++ [over.ics.user]p1: // // [...] If the user-defined conversion is specified by a @@ -4025,8 +4043,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (!Best->FinalConversion.DirectBinding) return false; - if (Best->Function) - S.MarkFunctionReferenced(DeclLoc, Best->Function); ICS.setUserDefined(); ICS.UserDefined.Before = Best->Conversions[0].Standard; ICS.UserDefined.After = Best->FinalConversion; @@ -5531,7 +5547,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, // functions. In such a case, the candidate functions generated from each // function template are combined with the set of non-template candidate // functions. - TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, @@ -5581,7 +5597,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // functions. In such a case, the candidate functions generated from each // function template are combined with the set of non-template candidate // functions. - TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + TemplateDeductionInfo Info(CandidateSet.getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, @@ -5703,7 +5719,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // there are 0 arguments (i.e., nothing is allocated using ASTContext's // allocator). QualType CallResultType = ConversionType.getNonLValueExprType(Context); - CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK, + CallExpr Call(Context, &ConversionFn, MultiExprArg(), CallResultType, VK, From->getLocStart()); ImplicitConversionSequence ICS = TryCopyInitialization(*this, &Call, ToType, @@ -5765,7 +5781,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; - TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); + TemplateDeductionInfo Info(CandidateSet.getLocation()); CXXConversionDecl *Specialization = 0; if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ToType, @@ -6770,17 +6786,16 @@ public: // bool operator==(T, T); // bool operator!=(T, T); void addRelationalPointerOrEnumeralOverloads() { - // C++ [over.built]p1: - // If there is a user-written candidate with the same name and parameter - // types as a built-in candidate operator function, the built-in operator - // function is hidden and is not included in the set of candidate - // functions. + // C++ [over.match.oper]p3: + // [...]the built-in candidates include all of the candidate operator + // functions defined in 13.6 that, compared to the given operator, [...] + // do not have the same parameter-type-list as any non-template non-member + // candidate. // - // The text is actually in a note, but if we don't implement it then we end - // up with ambiguities when the user provides an overloaded operator for - // an enumeration type. Note that only enumeration types have this problem, - // so we track which enumeration types we've seen operators for. Also, the - // only other overloaded operator with enumeration argumenst, operator=, + // Note that in practice, this only affects enumeration types because there + // aren't any built-in candidates of record type, and a user-defined operator + // must have an operand of record or enumeration type. Also, the only other + // overloaded operator with enumeration arguments, operator=, // cannot be overloaded for enumeration types, so this is the only place // where we must suppress candidates like this. llvm::DenseSet<std::pair<CanQualType, CanQualType> > @@ -6795,6 +6810,9 @@ public: if (!C->Viable || !C->Function || C->Function->getNumParams() != 2) continue; + if (C->Function->isFunctionTemplateSpecialization()) + continue; + QualType FirstParamType = C->Function->getParamDecl(0)->getType().getUnqualifiedType(); QualType SecondParamType = @@ -7652,8 +7670,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, llvm::ArrayRef<Expr *> Args, TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, - bool PartialOverloading, - bool StdNamespaceIsAssociated) { + bool PartialOverloading) { ADLResult Fns; // FIXME: This approach for uniquing ADL results (and removing @@ -7664,8 +7681,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, // we supposed to consider on ADL candidates, anyway? // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, Operator, Loc, Args, Fns, - StdNamespaceIsAssociated); + ArgumentDependentLookup(Name, Operator, Loc, Args, Fns); // Erase all of the candidates we already knew about. for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), @@ -7976,10 +7992,20 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion( const PartialDiagnostic &PDiag) const { S.Diag(CaretLoc, PDiag) << Ambiguous.getFromType() << Ambiguous.getToType(); - for (AmbiguousConversionSequence::const_iterator - I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) { + // FIXME: The note limiting machinery is borrowed from + // OverloadCandidateSet::NoteCandidates; there's an opportunity for + // refactoring here. + const OverloadsShown ShowOverloads = S.Diags.getShowOverloads(); + unsigned CandsShown = 0; + AmbiguousConversionSequence::const_iterator I, E; + for (I = Ambiguous.begin(), E = Ambiguous.end(); I != E; ++I) { + if (CandsShown >= 4 && ShowOverloads == Ovl_Best) + break; + ++CandsShown; S.NoteOverloadCandidate(*I); } + if (I != E) + S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I); } namespace { @@ -8515,7 +8541,7 @@ void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { } void NoteBuiltinOperatorCandidate(Sema &S, - const char *Opc, + StringRef Opc, SourceLocation OpLoc, OverloadCandidate *Cand) { assert(Cand->NumConversions <= 2 && "builtin operator is not binary"); @@ -8561,6 +8587,7 @@ RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) { case Sema::TDK_Success: llvm_unreachable("TDK_success while diagnosing bad deduction"); + case Sema::TDK_Invalid: case Sema::TDK_Incomplete: return 1; @@ -8783,7 +8810,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, void OverloadCandidateSet::NoteCandidates(Sema &S, OverloadCandidateDisplayKind OCD, llvm::ArrayRef<Expr *> Args, - const char *Opc, + StringRef Opc, SourceLocation OpLoc) { // Sort the candidates by viability and position. Sorting directly would // be prohibitive, so we make a set of pointers and sort those. @@ -8807,8 +8834,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, bool ReportedAmbiguousConversions = false; SmallVectorImpl<OverloadCandidate*>::iterator I, E; - const DiagnosticsEngine::OverloadsShown ShowOverloads = - S.Diags.getShowOverloads(); + const OverloadsShown ShowOverloads = S.Diags.getShowOverloads(); unsigned CandsShown = 0; for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { OverloadCandidate *Cand = *I; @@ -8816,7 +8842,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, // Set an arbitrary limit on the number of candidate functions we'll spam // the user with. FIXME: This limit should depend on details of the // candidate list. - if (CandsShown >= 4 && ShowOverloads == DiagnosticsEngine::Ovl_Best) { + if (CandsShown >= 4 && ShowOverloads == Ovl_Best) { break; } ++CandsShown; @@ -8979,7 +9005,7 @@ private: // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); + TemplateDeductionInfo Info(OvlExpr->getNameLoc()); if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(FunctionTemplate, &OvlExplicitTemplateArgs, @@ -9201,7 +9227,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, Fn = Resolver.getMatchingFunctionDecl(); assert(Fn); FoundResult = *Resolver.getMatchingFunctionAccessPair(); - MarkFunctionReferenced(AddressOfExpr->getLocStart(), Fn); if (Complain) CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); } @@ -9257,7 +9282,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context, ovl->getNameLoc()); + TemplateDeductionInfo Info(ovl->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info)) { @@ -9457,8 +9482,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false, ULE->getExprLoc(), Args, ExplicitTemplateArgs, - CandidateSet, PartialOverloading, - ULE->isStdAssociatedNamespace()); + CandidateSet, PartialOverloading); } /// Attempt to recover from an ill-formed use of a non-dependent name in a @@ -9509,7 +9533,7 @@ DiagnoseTwoPhaseLookup(Sema &SemaRef, SourceLocation FnLoc, // declaring the function there instead. Sema::AssociatedNamespaceSet AssociatedNamespaces; Sema::AssociatedClassSet AssociatedClasses; - SemaRef.FindAssociatedClassesAndNamespaces(Args, + SemaRef.FindAssociatedClassesAndNamespaces(FnLoc, Args, AssociatedNamespaces, AssociatedClasses); // Never suggest declaring a function within namespace 'std'. @@ -9632,6 +9656,20 @@ class NoTypoCorrectionCCC : public CorrectionCandidateCallback { return false; } }; + +class BuildRecoveryCallExprRAII { + Sema &SemaRef; +public: + BuildRecoveryCallExprRAII(Sema &S) : SemaRef(S) { + assert(SemaRef.IsBuildingRecoveryCallExpr == false); + SemaRef.IsBuildingRecoveryCallExpr = true; + } + + ~BuildRecoveryCallExprRAII() { + SemaRef.IsBuildingRecoveryCallExpr = false; + } +}; + } /// Attempts to recover from a call where no functions were found. @@ -9644,6 +9682,15 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, llvm::MutableArrayRef<Expr *> Args, SourceLocation RParenLoc, bool EmptyLookup, bool AllowTypoCorrection) { + // Do not try to recover if it is already building a recovery call. + // This stops infinite loops for template instantiations like + // + // template <typename T> auto foo(T t) -> decltype(foo(t)) {} + // template <typename T> auto foo(T t) -> decltype(foo(&t)) {} + // + if (SemaRef.IsBuildingRecoveryCallExpr) + return ExprError(); + BuildRecoveryCallExprRAII RCE(SemaRef); CXXScopeSpec SS; SS.Adopt(ULE->getQualifierLoc()); @@ -9695,20 +9742,15 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, RParenLoc); } -/// ResolveOverloadedCallFn - Given the call expression that calls Fn -/// (which eventually refers to the declaration Func) and the call -/// arguments Args/NumArgs, attempt to resolve the function call down -/// to a specific function. If overload resolution succeeds, returns -/// the function declaration produced by overload -/// resolution. Otherwise, emits diagnostics, deletes all of the -/// arguments and Fn, and returns NULL. -ExprResult -Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, - SourceLocation LParenLoc, - Expr **Args, unsigned NumArgs, - SourceLocation RParenLoc, - Expr *ExecConfig, - bool AllowTypoCorrection) { +/// \brief Constructs and populates an OverloadedCandidateSet from +/// the given function. +/// \returns true when an the ExprResult output parameter has been set. +bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, + UnresolvedLookupExpr *ULE, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + OverloadCandidateSet *CandidateSet, + ExprResult *Result) { #ifndef NDEBUG if (ULE->requiresADL()) { // To do ADL, we must have found an unqualified name. @@ -9724,62 +9766,79 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, // We don't perform ADL in C. assert(getLangOpts().CPlusPlus && "ADL enabled in C"); - } else - assert(!ULE->isStdAssociatedNamespace() && - "std is associated namespace but not doing ADL"); + } #endif UnbridgedCastsSet UnbridgedCasts; - if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) - return ExprError(); - - OverloadCandidateSet CandidateSet(Fn->getExprLoc()); + if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) { + *Result = ExprError(); + return true; + } // Add the functions denoted by the callee to the set of candidate // functions, including those from argument-dependent lookup. AddOverloadedCallCandidates(ULE, llvm::makeArrayRef(Args, NumArgs), - CandidateSet); + *CandidateSet); // If we found nothing, try to recover. // BuildRecoveryCallExpr diagnoses the error itself, so we just bail // out if it fails. - if (CandidateSet.empty()) { + if (CandidateSet->empty()) { // In Microsoft mode, if we are inside a template class member function then // create a type dependent CallExpr. The goal is to postpone name lookup // to instantiation time to be able to search into type dependent base // classes. if (getLangOpts().MicrosoftMode && CurContext->isDependentContext() && (isa<FunctionDecl>(CurContext) || isa<CXXRecordDecl>(CurContext))) { - CallExpr *CE = new (Context) CallExpr(Context, Fn, Args, NumArgs, - Context.DependentTy, VK_RValue, - RParenLoc); + CallExpr *CE = new (Context) CallExpr(Context, Fn, + llvm::makeArrayRef(Args, NumArgs), + Context.DependentTy, VK_RValue, + RParenLoc); CE->setTypeDependent(true); - return Owned(CE); + *Result = Owned(CE); + return true; } - return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, - llvm::MutableArrayRef<Expr *>(Args, NumArgs), - RParenLoc, /*EmptyLookup=*/true, - AllowTypoCorrection); + return false; } UnbridgedCasts.restore(); + return false; +} - OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { +/// FinishOverloadedCallExpr - given an OverloadCandidateSet, builds and returns +/// the completed call expression. If overload resolution fails, emits +/// diagnostics and returns ExprError() +static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + Expr *ExecConfig, + OverloadCandidateSet *CandidateSet, + OverloadCandidateSet::iterator *Best, + OverloadingResult OverloadResult, + bool AllowTypoCorrection) { + if (CandidateSet->empty()) + return BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, + llvm::MutableArrayRef<Expr *>(Args, NumArgs), + RParenLoc, /*EmptyLookup=*/true, + AllowTypoCorrection); + + switch (OverloadResult) { case OR_Success: { - FunctionDecl *FDecl = Best->Function; - MarkFunctionReferenced(Fn->getExprLoc(), FDecl); - CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); - DiagnoseUseOfDecl(FDecl, ULE->getNameLoc()); - Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); - return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc, - ExecConfig); + 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); + return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); } case OR_No_Viable_Function: { // Try to recover by looking for viable functions which the user might // have meant to call. - ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, + ExprResult Recovery = BuildRecoveryCallExpr(SemaRef, S, Fn, ULE, LParenLoc, llvm::MutableArrayRef<Expr *>(Args, NumArgs), RParenLoc, /*EmptyLookup=*/false, @@ -9787,44 +9846,73 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, if (!Recovery.isInvalid()) return Recovery; - Diag(Fn->getLocStart(), + SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_no_viable_function_in_call) << ULE->getName() << Fn->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; } case OR_Ambiguous: - Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call) + SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call) << ULE->getName() << Fn->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, - llvm::makeArrayRef(Args, NumArgs)); + CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, + llvm::makeArrayRef(Args, NumArgs)); break; - case OR_Deleted: - { - Diag(Fn->getLocStart(), diag::err_ovl_deleted_call) - << Best->Function->isDeleted() - << ULE->getName() - << getDeletedOrUnavailableSuffix(Best->Function) - << Fn->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, - llvm::makeArrayRef(Args, NumArgs)); + case OR_Deleted: { + SemaRef.Diag(Fn->getLocStart(), diag::err_ovl_deleted_call) + << (*Best)->Function->isDeleted() + << ULE->getName() + << SemaRef.getDeletedOrUnavailableSuffix((*Best)->Function) + << Fn->getSourceRange(); + CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, + llvm::makeArrayRef(Args, NumArgs)); - // We emitted an error for the unvailable/deleted function call but keep - // the call in the AST. - FunctionDecl *FDecl = Best->Function; - Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); - return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, - RParenLoc, ExecConfig); - } + // We emitted an error for the unvailable/deleted function call but keep + // the call in the AST. + FunctionDecl *FDecl = (*Best)->Function; + Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); + return SemaRef.BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig); + } } // Overload resolution failed. return ExprError(); } +/// BuildOverloadedCallExpr - Given the call expression that calls Fn +/// (which eventually refers to the declaration Func) and the call +/// arguments Args/NumArgs, attempt to resolve the function call down +/// to a specific function. If overload resolution succeeds, returns +/// the call expression produced by overload resolution. +/// Otherwise, emits diagnostics and returns ExprError. +ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, + UnresolvedLookupExpr *ULE, + SourceLocation LParenLoc, + Expr **Args, unsigned NumArgs, + SourceLocation RParenLoc, + Expr *ExecConfig, + bool AllowTypoCorrection) { + OverloadCandidateSet CandidateSet(Fn->getExprLoc()); + ExprResult result; + + if (buildOverloadedCallSet(S, Fn, ULE, Args, NumArgs, LParenLoc, + &CandidateSet, &result)) + return result; + + OverloadCandidateSet::iterator Best; + OverloadingResult OverloadResult = + CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best); + + return FinishOverloadedCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, + RParenLoc, ExecConfig, &CandidateSet, + &Best, OverloadResult, + AllowTypoCorrection); +} + static bool IsOverloaded(const UnresolvedSetImpl &Functions) { return Functions.size() > 1 || (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); @@ -9889,10 +9977,10 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, - &Args[0], NumArgs, + llvm::makeArrayRef(Args, NumArgs), Context.DependentTy, VK_RValue, - OpLoc)); + OpLoc, false)); } // Build an empty overload set. @@ -9968,7 +10056,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, Args[0] = Input; CallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), - Args, NumArgs, ResultTy, VK, OpLoc); + llvm::makeArrayRef(Args, NumArgs), + ResultTy, VK, OpLoc, false); if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, FnDecl)) @@ -10069,7 +10158,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc, Context.DependentTy, VK_RValue, OK_Ordinary, - OpLoc)); + OpLoc, + FPFeatures.fp_contract)); return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc, Context.DependentTy, @@ -10077,7 +10167,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OK_Ordinary, Context.DependentTy, Context.DependentTy, - OpLoc)); + OpLoc, + FPFeatures.fp_contract)); } // FIXME: save results of ADL from here? @@ -10089,11 +10180,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, NestedNameSpecifierLoc(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); - return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, - Args, 2, - Context.DependentTy, - VK_RValue, - OpLoc)); + return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, + Context.DependentTy, VK_RValue, + OpLoc, FPFeatures.fp_contract)); } // Always do placeholder-like conversions on the RHS. @@ -10208,7 +10297,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr.take(), - Args, 2, ResultTy, VK, OpLoc); + Args, ResultTy, VK, OpLoc, + FPFeatures.fp_contract); if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, FnDecl)) @@ -10270,7 +10360,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Result.isInvalid()) CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, BinaryOperator::getOpcodeStr(Opc), OpLoc); - return move(Result); + return Result; } case OR_Ambiguous: @@ -10337,10 +10427,10 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Can't add any actual overloads yet return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn, - Args, 2, + Args, Context.DependentTy, VK_RValue, - RLoc)); + RLoc, false)); } // Handle placeholders on both operands. @@ -10416,8 +10506,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Subscript, - FnExpr.take(), Args, 2, - ResultTy, VK, RLoc); + FnExpr.take(), Args, + ResultTy, VK, RLoc, + false); if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, FnDecl)) @@ -10534,7 +10625,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } CXXMemberCallExpr *call - = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + = new (Context) CXXMemberCallExpr(Context, MemExprE, + llvm::makeArrayRef(Args, NumArgs), resultType, valueKind, RParenLoc); if (CheckCallReturnType(proto->getResultType(), @@ -10676,7 +10768,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, assert(Method && "Member call to something that isn't a method?"); CXXMemberCallExpr *TheCall = - new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, + new (Context) CXXMemberCallExpr(Context, MemExprE, + llvm::makeArrayRef(Args, NumArgs), ResultType, VK, RParenLoc); // Check for a valid return type. @@ -10904,6 +10997,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // that calls this method, using Object for the implicit object // parameter and passing along the remaining arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); + + // An error diagnostic has already been printed when parsing the declaration. + if (Method->isInvalidDecl()) + return ExprError(); + const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>(); @@ -10942,8 +11040,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn.take(), - MethodArgs, NumArgs + 1, - ResultTy, VK, RParenLoc); + llvm::makeArrayRef(MethodArgs, NumArgs+1), + ResultTy, VK, RParenLoc, false); delete [] MethodArgs; if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, @@ -10966,7 +11064,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (ObjRes.isInvalid()) IsError = true; else - Object = move(ObjRes); + Object = ObjRes; TheCall->setArg(0, Object.take()); // Check the argument types. @@ -11116,7 +11214,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr.take(), - &Base, 1, ResultTy, VK, OpLoc); + Base, ResultTy, VK, OpLoc, false); if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, Method)) @@ -11187,7 +11285,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, ResultTy = ResultTy.getNonLValueExprType(Context); UserDefinedLiteral *UDL = - new (Context) UserDefinedLiteral(Context, Fn.take(), ConvArgs, Args.size(), + new (Context) UserDefinedLiteral(Context, Fn.take(), + llvm::makeArrayRef(ConvArgs, Args.size()), ResultTy, VK, LitEndLoc, UDSuffixLoc); if (CheckCallReturnType(FD->getResultType(), UDSuffixLoc, UDL, FD)) @@ -11199,6 +11298,80 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, return MaybeBindToTemporary(UDL); } +/// Build a call to 'begin' or 'end' for a C++11 for-range statement. If the +/// given LookupResult is non-empty, it is assumed to describe a member which +/// will be invoked. Otherwise, the function will be found via argument +/// dependent lookup. +/// CallExpr is set to a valid expression and FRS_Success returned on success, +/// otherwise CallExpr is set to ExprError() and some non-success value +/// is returned. +Sema::ForRangeStatus +Sema::BuildForRangeBeginEndCall(Scope *S, SourceLocation Loc, + SourceLocation RangeLoc, VarDecl *Decl, + BeginEndFunction BEF, + const DeclarationNameInfo &NameInfo, + LookupResult &MemberLookup, + OverloadCandidateSet *CandidateSet, + Expr *Range, ExprResult *CallExpr) { + CandidateSet->clear(); + if (!MemberLookup.empty()) { + ExprResult MemberRef = + BuildMemberReferenceExpr(Range, Range->getType(), Loc, + /*IsPtr=*/false, CXXScopeSpec(), + /*TemplateKWLoc=*/SourceLocation(), + /*FirstQualifierInScope=*/0, + MemberLookup, + /*TemplateArgs=*/0); + if (MemberRef.isInvalid()) { + *CallExpr = ExprError(); + Diag(Range->getLocStart(), diag::note_in_for_range) + << RangeLoc << BEF << Range->getType(); + return FRS_DiagnosticIssued; + } + *CallExpr = ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(), Loc, 0); + if (CallExpr->isInvalid()) { + *CallExpr = ExprError(); + Diag(Range->getLocStart(), diag::note_in_for_range) + << RangeLoc << BEF << Range->getType(); + return FRS_DiagnosticIssued; + } + } else { + UnresolvedSet<0> FoundNames; + UnresolvedLookupExpr *Fn = + UnresolvedLookupExpr::Create(Context, /*NamingClass=*/0, + NestedNameSpecifierLoc(), NameInfo, + /*NeedsADL=*/true, /*Overloaded=*/false, + FoundNames.begin(), FoundNames.end()); + + bool CandidateSetError = buildOverloadedCallSet(S, Fn, Fn, &Range, 1, Loc, + CandidateSet, CallExpr); + if (CandidateSet->empty() || CandidateSetError) { + *CallExpr = ExprError(); + return FRS_NoViableFunction; + } + OverloadCandidateSet::iterator Best; + OverloadingResult OverloadResult = + CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best); + + if (OverloadResult == OR_No_Viable_Function) { + *CallExpr = ExprError(); + return FRS_NoViableFunction; + } + *CallExpr = FinishOverloadedCallExpr(*this, S, Fn, Fn, Loc, &Range, 1, + Loc, 0, CandidateSet, &Best, + OverloadResult, + /*AllowTypoCorrection=*/false); + if (CallExpr->isInvalid() || OverloadResult != OR_Success) { + *CallExpr = ExprError(); + Diag(Range->getLocStart(), diag::note_in_for_range) + << RangeLoc << BEF << Range->getType(); + return FRS_DiagnosticIssued; + } + } + return FRS_Success; +} + + /// FixOverloadedFunctionReference - E is an expression that refers to /// a C++ overloaded function (possibly with some parentheses and /// perhaps a '&' around it). We have resolved the overloaded function @@ -11358,6 +11531,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, TemplateArgs, type, valueKind, OK_Ordinary); ME->setHadMultipleCandidates(true); + MarkMemberReferenced(ME); return ME; } diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index 722ac19..a8d75b2 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -31,6 +31,7 @@ //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" +#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/Initialization.h" #include "clang/AST/ExprObjC.h" #include "clang/Lex/Preprocessor.h" @@ -91,9 +92,8 @@ namespace { return new (S.Context) GenericSelectionExpr(S.Context, gse->getGenericLoc(), gse->getControllingExpr(), - assocTypes.data(), - assocs.data(), - numAssocs, + assocTypes, + assocs, gse->getDefaultLoc(), gse->getRParenLoc(), gse->containsUnexpandedParameterPack(), @@ -187,7 +187,7 @@ namespace { UnaryOperatorKind opcode, Expr *op); - ExprResult complete(Expr *syntacticForm); + virtual ExprResult complete(Expr *syntacticForm); OpaqueValueExpr *capture(Expr *op); OpaqueValueExpr *captureValueAsResult(Expr *op); @@ -198,7 +198,14 @@ namespace { } /// Return true if assignments have a non-void result. - virtual bool assignmentsHaveResult() { return true; } + bool CanCaptureValueOfType(QualType ty) { + assert(!ty->isIncompleteType()); + assert(!ty->isDependentType()); + + if (const CXXRecordDecl *ClassDecl = ty->getAsCXXRecordDecl()) + return ClassDecl->isTriviallyCopyable(); + return true; + } virtual Expr *rebuildAndCaptureObject(Expr *) = 0; virtual ExprResult buildGet() = 0; @@ -206,7 +213,7 @@ namespace { bool captureSetValueAsResult) = 0; }; - /// A PseudoOpBuilder for Objective-C @properties. + /// A PseudoOpBuilder for Objective-C \@properties. class ObjCPropertyOpBuilder : public PseudoOpBuilder { ObjCPropertyRefExpr *RefExpr; ObjCPropertyRefExpr *SyntacticRefExpr; @@ -239,6 +246,9 @@ namespace { Expr *rebuildAndCaptureObject(Expr *syntacticBase); ExprResult buildGet(); ExprResult buildSet(Expr *op, SourceLocation, bool); + ExprResult complete(Expr *SyntacticForm); + + bool isWeakProperty() const; }; /// A PseudoOpBuilder for Objective-C array/dictionary indexing. @@ -292,7 +302,7 @@ OpaqueValueExpr *PseudoOpBuilder::capture(Expr *e) { /// operation. This routine is safe against expressions which may /// already be captured. /// -/// \param Returns the captured expression, which will be the +/// \returns the captured expression, which will be the /// same as the input if the input was already captured OpaqueValueExpr *PseudoOpBuilder::captureValueAsResult(Expr *e) { assert(ResultIndex == PseudoObjectExpr::NoResult); @@ -353,7 +363,7 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, syntactic = new (S.Context) BinaryOperator(syntacticLHS, capturedRHS, opcode, capturedRHS->getType(), capturedRHS->getValueKind(), - OK_Ordinary, opcLoc); + OK_Ordinary, opcLoc, false); } else { ExprResult opLHS = buildGet(); if (opLHS.isInvalid()) return ExprError(); @@ -372,12 +382,12 @@ PseudoOpBuilder::buildAssignmentOperation(Scope *Sc, SourceLocation opcLoc, OK_Ordinary, opLHS.get()->getType(), result.get()->getType(), - opcLoc); + opcLoc, false); } // The result of the assignment, if not void, is the value set into // the l-value. - result = buildSet(result.take(), opcLoc, assignmentsHaveResult()); + result = buildSet(result.take(), opcLoc, /*captureSetValueAsResult*/ true); if (result.isInvalid()) return ExprError(); addSemanticExpr(result.take()); @@ -401,7 +411,7 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, QualType resultType = result.get()->getType(); // That's the postfix result. - if (UnaryOperator::isPostfix(opcode) && assignmentsHaveResult()) { + if (UnaryOperator::isPostfix(opcode) && CanCaptureValueOfType(resultType)) { result = capture(result.take()); setResultToLastSemantic(); } @@ -420,8 +430,7 @@ PseudoOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, // Store that back into the result. The value stored is the result // of a prefix operation. - result = buildSet(result.take(), opcLoc, - UnaryOperator::isPrefix(opcode) && assignmentsHaveResult()); + result = buildSet(result.take(), opcLoc, UnaryOperator::isPrefix(opcode)); if (result.isInvalid()) return ExprError(); addSemanticExpr(result.take()); @@ -472,6 +481,23 @@ static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel, return S.LookupMethodInObjectType(sel, IT, false); } +bool ObjCPropertyOpBuilder::isWeakProperty() const { + QualType T; + if (RefExpr->isExplicitProperty()) { + const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty(); + if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) + return true; + + T = Prop->getType(); + } else if (Getter) { + T = Getter->getResultType(); + } else { + return false; + } + + return T.getObjCLifetime() == Qualifiers::OCL_Weak; +} + bool ObjCPropertyOpBuilder::findGetter() { if (Getter) return true; @@ -532,7 +558,7 @@ bool ObjCPropertyOpBuilder::findSetter(bool warn) { // Do a normal method lookup first. if (ObjCMethodDecl *setter = LookupMethodInReceiverType(S, SetterSelector, RefExpr)) { - if (setter->isSynthesized() && warn) + if (setter->isPropertyAccessor() && warn) if (const ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(setter->getDeclContext())) { const StringRef thisPropertyName(prop->getName()); @@ -617,7 +643,7 @@ ExprResult ObjCPropertyOpBuilder::buildGet() { /// Store to an Objective-C property reference. /// -/// \param bindSetValueAsResult - If true, capture the actual +/// \param captureSetValueAsResult If true, capture the actual /// value being set as the value of the property operation. ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, bool captureSetValueAsResult) { @@ -676,7 +702,8 @@ ExprResult ObjCPropertyOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, ObjCMessageExpr *msgExpr = cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); Expr *arg = msgExpr->getArg(0); - msgExpr->setArg(0, captureValueAsResult(arg)); + if (CanCaptureValueOfType(arg->getType())) + msgExpr->setArg(0, captureValueAsResult(arg)); } return msg; @@ -819,6 +846,19 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc, return PseudoOpBuilder::buildIncDecOperation(Sc, opcLoc, opcode, op); } +ExprResult ObjCPropertyOpBuilder::complete(Expr *SyntacticForm) { + if (S.getLangOpts().ObjCAutoRefCount && isWeakProperty()) { + DiagnosticsEngine::Level Level = + S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, + SyntacticForm->getLocStart()); + if (Level != DiagnosticsEngine::Ignored) + S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr, + SyntacticRefExpr->isMessagingGetter()); + } + + return PseudoOpBuilder::complete(SyntacticForm); +} + // ObjCSubscript build stuff. // @@ -1035,7 +1075,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexGetter() { 0 /*TypeSourceInfo */, S.Context.getTranslationUnitDecl(), true /*Instance*/, false/*isVariadic*/, - /*isSynthesized=*/false, + /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, false); @@ -1151,7 +1191,7 @@ bool ObjCSubscriptOpBuilder::findAtIndexSetter() { ResultTInfo, S.Context.getTranslationUnitDecl(), true /*Instance*/, false/*isVariadic*/, - /*isSynthesized=*/false, + /*isPropertyAccessor=*/false, /*isImplicitlyDeclared=*/true, /*isDefined=*/false, ObjCMethodDecl::Required, false); @@ -1255,7 +1295,7 @@ ExprResult ObjCSubscriptOpBuilder::buildGet() { /// Store into the container the "op" object at "Index"'ed location /// by building this messaging expression: /// - (void)setObject:(id)object atIndexedSubscript:(NSInteger)index; -/// \param bindSetValueAsResult - If true, capture the actual +/// \param captureSetValueAsResult If true, capture the actual /// value being set as the value of the property operation. ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, bool captureSetValueAsResult) { @@ -1279,7 +1319,8 @@ ExprResult ObjCSubscriptOpBuilder::buildSet(Expr *op, SourceLocation opcLoc, ObjCMessageExpr *msgExpr = cast<ObjCMessageExpr>(msg.get()->IgnoreImplicit()); Expr *arg = msgExpr->getArg(0); - msgExpr->setArg(0, captureValueAsResult(arg)); + if (CanCaptureValueOfType(arg->getType())) + msgExpr->setArg(0, captureValueAsResult(arg)); } return msg; @@ -1333,7 +1374,7 @@ ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc, // Do nothing if either argument is dependent. if (LHS->isTypeDependent() || RHS->isTypeDependent()) return new (Context) BinaryOperator(LHS, RHS, opcode, Context.DependentTy, - VK_RValue, OK_Ordinary, opcLoc); + VK_RValue, OK_Ordinary, opcLoc, false); // Filter out non-overload placeholder types in the RHS. if (RHS->getType()->isNonOverloadPlaceholderType()) { @@ -1404,14 +1445,14 @@ Expr *Sema::recreateSyntacticForm(PseudoObjectExpr *E) { cop->getObjectKind(), cop->getComputationLHSType(), cop->getComputationResultType(), - cop->getOperatorLoc()); + cop->getOperatorLoc(), false); } else if (BinaryOperator *bop = dyn_cast<BinaryOperator>(syntax)) { Expr *lhs = stripOpaqueValuesFromPseudoObjectRef(*this, bop->getLHS()); Expr *rhs = cast<OpaqueValueExpr>(bop->getRHS())->getSourceExpr(); return new (Context) BinaryOperator(lhs, rhs, bop->getOpcode(), bop->getType(), bop->getValueKind(), bop->getObjectKind(), - bop->getOperatorLoc()); + bop->getOperatorLoc(), false); } else { assert(syntax->hasPlaceholderType(BuiltinType::PseudoObject)); return stripOpaqueValuesFromPseudoObjectRef(*this, syntax); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 86884b7..f55174e 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -28,27 +28,10 @@ #include "clang/Lex/Preprocessor.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCObjectFileInfo.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/MCAsmLexer.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" using namespace clang; using namespace sema; @@ -177,6 +160,13 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { !E->isUnusedResultAWarning(WarnExpr, Loc, R1, R2, Context)) return; + // If this is a GNU statement expression expanded from a macro, it is probably + // unused because it is a function-like macro that can be used as either an + // expression or statement. Don't warn, because it is almost certainly a + // false positive. + if (isa<StmtExpr>(E) && Loc.isMacroID()) + return; + // Okay, we have an unused result. Depending on what the base expression is, // we might want to make a more specific diagnostic. Check for one of these // cases now. @@ -271,7 +261,7 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg elts, bool isStmtExpr) { unsigned NumElts = elts.size(); - Stmt **Elts = reinterpret_cast<Stmt**>(elts.release()); + Stmt **Elts = elts.data(); // If we're in C89 mode, check that we don't have any decls after stmts. If // so, emit an extension diagnostic. if (!getLangOpts().C99 && !getLangOpts().CPlusPlus) { @@ -381,8 +371,10 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, // Otherwise, things are good. Fill in the declaration and return it. LabelStmt *LS = new (Context) LabelStmt(IdentLoc, TheDecl, SubStmt); TheDecl->setStmt(LS); - if (!TheDecl->isGnuLocal()) + if (!TheDecl->isGnuLocal()) { + TheDecl->setLocStart(IdentLoc); TheDecl->setLocation(IdentLoc); + } return Owned(LS); } @@ -1566,25 +1558,6 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, ForLoc, RParenLoc)); } -namespace { - -enum BeginEndFunction { - BEF_begin, - BEF_end -}; - -/// Build a variable declaration for a for-range statement. -static VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, - QualType Type, const char *Name) { - DeclContext *DC = SemaRef.CurContext; - IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); - TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); - VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, - TInfo, SC_Auto, SC_None); - Decl->setImplicit(); - return Decl; -} - /// Finish building a variable declaration for a for-range statement. /// \return true if an error occurs. static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, @@ -1617,12 +1590,14 @@ static bool FinishForRangeVarDecl(Sema &SemaRef, VarDecl *Decl, Expr *Init, return false; } +namespace { + /// Produce a note indicating which begin/end function was implicitly called -/// by a C++0x for-range statement. This is often not obvious from the code, +/// by a C++11 for-range statement. This is often not obvious from the code, /// nor from the diagnostics produced when analysing the implicit expressions /// required in a for-range statement. void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, - BeginEndFunction BEF) { + Sema::BeginEndFunction BEF) { CallExpr *CE = dyn_cast<CallExpr>(E); if (!CE) return; @@ -1643,56 +1618,16 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E, << BEF << IsTemplate << Description << E->getType(); } -/// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the -/// given LookupResult is non-empty, it is assumed to describe a member which -/// will be invoked. Otherwise, the function will be found via argument -/// dependent lookup. -static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S, - SourceLocation Loc, - VarDecl *Decl, - BeginEndFunction BEF, - const DeclarationNameInfo &NameInfo, - LookupResult &MemberLookup, - Expr *Range) { - ExprResult CallExpr; - if (!MemberLookup.empty()) { - ExprResult MemberRef = - SemaRef.BuildMemberReferenceExpr(Range, Range->getType(), Loc, - /*IsPtr=*/false, CXXScopeSpec(), - /*TemplateKWLoc=*/SourceLocation(), - /*FirstQualifierInScope=*/0, - MemberLookup, - /*TemplateArgs=*/0); - if (MemberRef.isInvalid()) - return ExprError(); - CallExpr = SemaRef.ActOnCallExpr(S, MemberRef.get(), Loc, MultiExprArg(), - Loc, 0); - if (CallExpr.isInvalid()) - return ExprError(); - } else { - UnresolvedSet<0> FoundNames; - // C++0x [stmt.ranged]p1: For the purposes of this name lookup, namespace - // std is an associated namespace. - UnresolvedLookupExpr *Fn = - UnresolvedLookupExpr::Create(SemaRef.Context, /*NamingClass=*/0, - NestedNameSpecifierLoc(), NameInfo, - /*NeedsADL=*/true, /*Overloaded=*/false, - FoundNames.begin(), FoundNames.end(), - /*LookInStdNamespace=*/true); - CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, - 0, /*AllowTypoCorrection=*/false); - if (CallExpr.isInvalid()) { - SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type) - << Range->getType(); - return ExprError(); - } - } - if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc, - diag::err_for_range_iter_deduction_failure)) { - NoteForRangeBeginEndFunction(SemaRef, CallExpr.get(), BEF); - return ExprError(); - } - return CallExpr; +/// Build a variable declaration for a for-range statement. +VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, + QualType Type, const char *Name) { + DeclContext *DC = SemaRef.CurContext; + IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name); + TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc); + VarDecl *Decl = VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, + TInfo, SC_Auto, SC_None); + Decl->setImplicit(); + return Decl; } } @@ -1723,7 +1658,7 @@ static bool ObjCEnumerationCollection(Expr *Collection) { StmtResult Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, Stmt *First, SourceLocation ColonLoc, Expr *Range, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, BuildForRangeKind Kind) { if (!First || !Range) return StmtError(); @@ -1761,15 +1696,137 @@ Sema::ActOnCXXForRangeStmt(SourceLocation ForLoc, return BuildCXXForRangeStmt(ForLoc, ColonLoc, RangeDecl.get(), /*BeginEndDecl=*/0, /*Cond=*/0, /*Inc=*/0, DS, - RParenLoc); + RParenLoc, Kind); } -/// BuildCXXForRangeStmt - Build or instantiate a C++0x for-range statement. +/// \brief Create the initialization, compare, and increment steps for +/// the range-based for loop expression. +/// This function does not handle array-based for loops, +/// which are created in Sema::BuildCXXForRangeStmt. +/// +/// \returns a ForRangeStatus indicating success or what kind of error occurred. +/// BeginExpr and EndExpr are set and FRS_Success is returned on success; +/// CandidateSet and BEF are set and some non-success value is returned on +/// failure. +static Sema::ForRangeStatus BuildNonArrayForRange(Sema &SemaRef, Scope *S, + Expr *BeginRange, Expr *EndRange, + QualType RangeType, + VarDecl *BeginVar, + VarDecl *EndVar, + SourceLocation ColonLoc, + OverloadCandidateSet *CandidateSet, + ExprResult *BeginExpr, + ExprResult *EndExpr, + Sema::BeginEndFunction *BEF) { + DeclarationNameInfo BeginNameInfo( + &SemaRef.PP.getIdentifierTable().get("begin"), ColonLoc); + DeclarationNameInfo EndNameInfo(&SemaRef.PP.getIdentifierTable().get("end"), + ColonLoc); + + LookupResult BeginMemberLookup(SemaRef, BeginNameInfo, + Sema::LookupMemberName); + LookupResult EndMemberLookup(SemaRef, EndNameInfo, Sema::LookupMemberName); + + if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { + // - if _RangeT is a class type, the unqualified-ids begin and end are + // looked up in the scope of class _RangeT as if by class member access + // lookup (3.4.5), and if either (or both) finds at least one + // declaration, begin-expr and end-expr are __range.begin() and + // __range.end(), respectively; + SemaRef.LookupQualifiedName(BeginMemberLookup, D); + SemaRef.LookupQualifiedName(EndMemberLookup, D); + + if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { + SourceLocation RangeLoc = BeginVar->getLocation(); + *BEF = BeginMemberLookup.empty() ? Sema::BEF_end : Sema::BEF_begin; + + SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch) + << RangeLoc << BeginRange->getType() << *BEF; + return Sema::FRS_DiagnosticIssued; + } + } else { + // - otherwise, begin-expr and end-expr are begin(__range) and + // end(__range), respectively, where begin and end are looked up with + // argument-dependent lookup (3.4.2). For the purposes of this name + // lookup, namespace std is an associated namespace. + + } + + *BEF = Sema::BEF_begin; + Sema::ForRangeStatus RangeStatus = + SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, BeginVar, + Sema::BEF_begin, BeginNameInfo, + BeginMemberLookup, CandidateSet, + BeginRange, BeginExpr); + + if (RangeStatus != Sema::FRS_Success) + return RangeStatus; + if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF); + return Sema::FRS_DiagnosticIssued; + } + + *BEF = Sema::BEF_end; + RangeStatus = + SemaRef.BuildForRangeBeginEndCall(S, ColonLoc, ColonLoc, EndVar, + Sema::BEF_end, EndNameInfo, + EndMemberLookup, CandidateSet, + EndRange, EndExpr); + if (RangeStatus != Sema::FRS_Success) + return RangeStatus; + if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc, + diag::err_for_range_iter_deduction_failure)) { + NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF); + return Sema::FRS_DiagnosticIssued; + } + return Sema::FRS_Success; +} + +/// Speculatively attempt to dereference an invalid range expression. +/// If the attempt fails, this function will return a valid, null StmtResult +/// and emit no diagnostics. +static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, + SourceLocation ForLoc, + Stmt *LoopVarDecl, + SourceLocation ColonLoc, + Expr *Range, + SourceLocation RangeLoc, + SourceLocation RParenLoc) { + // Determine whether we can rebuild the for-range statement with a + // dereferenced range expression. + ExprResult AdjustedRange; + { + Sema::SFINAETrap Trap(SemaRef); + + AdjustedRange = SemaRef.BuildUnaryOp(S, RangeLoc, UO_Deref, Range); + if (AdjustedRange.isInvalid()) + return StmtResult(); + + StmtResult SR = + SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc, + AdjustedRange.get(), RParenLoc, + Sema::BFRK_Check); + if (SR.isInvalid()) + return StmtResult(); + } + + // The attempt to dereference worked well enough that it could produce a valid + // loop. Produce a fixit, and rebuild the loop with diagnostics enabled, in + // case there are any other (non-fatal) problems with it. + SemaRef.Diag(RangeLoc, diag::err_for_range_dereference) + << Range->getType() << FixItHint::CreateInsertion(RangeLoc, "*"); + return SemaRef.ActOnCXXForRangeStmt(ForLoc, LoopVarDecl, ColonLoc, + AdjustedRange.get(), RParenLoc, + Sema::BFRK_Rebuild); +} + +/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *BeginEnd, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, BuildForRangeKind Kind) { Scope *S = getCurScope(); DeclStmt *RangeDS = cast<DeclStmt>(RangeDecl); @@ -1855,50 +1912,43 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, return StmtError(); } } else { - DeclarationNameInfo BeginNameInfo(&PP.getIdentifierTable().get("begin"), - ColonLoc); - DeclarationNameInfo EndNameInfo(&PP.getIdentifierTable().get("end"), - ColonLoc); - - LookupResult BeginMemberLookup(*this, BeginNameInfo, LookupMemberName); - LookupResult EndMemberLookup(*this, EndNameInfo, LookupMemberName); - - if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) { - // - if _RangeT is a class type, the unqualified-ids begin and end are - // looked up in the scope of class _RangeT as if by class member access - // lookup (3.4.5), and if either (or both) finds at least one - // declaration, begin-expr and end-expr are __range.begin() and - // __range.end(), respectively; - LookupQualifiedName(BeginMemberLookup, D); - LookupQualifiedName(EndMemberLookup, D); - - if (BeginMemberLookup.empty() != EndMemberLookup.empty()) { - Diag(ColonLoc, diag::err_for_range_member_begin_end_mismatch) - << RangeType << BeginMemberLookup.empty(); - return StmtError(); - } - } else { - // - otherwise, begin-expr and end-expr are begin(__range) and - // end(__range), respectively, where begin and end are looked up with - // argument-dependent lookup (3.4.2). For the purposes of this name - // lookup, namespace std is an associated namespace. + OverloadCandidateSet CandidateSet(RangeLoc); + Sema::BeginEndFunction BEFFailure; + ForRangeStatus RangeStatus = + BuildNonArrayForRange(*this, S, BeginRangeRef.get(), + EndRangeRef.get(), RangeType, + BeginVar, EndVar, ColonLoc, &CandidateSet, + &BeginExpr, &EndExpr, &BEFFailure); + + // If building the range failed, try dereferencing the range expression + // unless a diagnostic was issued or the end function is problematic. + if (Kind == BFRK_Build && RangeStatus == FRS_NoViableFunction && + BEFFailure == BEF_begin) { + StmtResult SR = RebuildForRangeWithDereference(*this, S, ForLoc, + LoopVarDecl, ColonLoc, + Range, RangeLoc, + RParenLoc); + if (SR.isInvalid() || SR.isUsable()) + return SR; } - BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar, - BEF_begin, BeginNameInfo, - BeginMemberLookup, - BeginRangeRef.get()); - if (BeginExpr.isInvalid()) - return StmtError(); - - EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar, - BEF_end, EndNameInfo, - EndMemberLookup, EndRangeRef.get()); - if (EndExpr.isInvalid()) + // Otherwise, emit diagnostics if we haven't already. + if (RangeStatus == FRS_NoViableFunction) { + 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)); + } + // Return an error if no fix was discovered. + if (RangeStatus != FRS_Success) return StmtError(); } - // C++0x [decl.spec.auto]p6: BeginType and EndType must be the same. + assert(!BeginExpr.isInvalid() && !EndExpr.isInvalid() && + "invalid range expression in for loop"); + + // C++11 [dcl.spec.auto]p7: BeginType and EndType must be the same. QualType BeginType = BeginVar->getType(), EndType = EndVar->getType(); if (!Context.hasSameType(BeginType, EndType)) { Diag(RangeLoc, diag::err_for_range_begin_end_types_differ) @@ -1930,6 +1980,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, NotEqExpr = ActOnBooleanCondition(S, ColonLoc, NotEqExpr.get()); NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); if (NotEqExpr.isInvalid()) { + Diag(RangeLoc, diag::note_for_range_invalid_iterator) + << RangeLoc << 0 << BeginRangeRef.get()->getType(); NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); if (!Context.hasSameType(BeginType, EndType)) NoteForRangeBeginEndFunction(*this, EndExpr.get(), BEF_end); @@ -1945,6 +1997,8 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, IncrExpr = ActOnUnaryOp(S, ColonLoc, tok::plusplus, BeginRef.get()); IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); if (IncrExpr.isInvalid()) { + Diag(RangeLoc, diag::note_for_range_invalid_iterator) + << RangeLoc << 2 << BeginRangeRef.get()->getType() ; NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); return StmtError(); } @@ -1957,12 +2011,15 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, ExprResult DerefExpr = ActOnUnaryOp(S, ColonLoc, tok::star, BeginRef.get()); if (DerefExpr.isInvalid()) { + Diag(RangeLoc, diag::note_for_range_invalid_iterator) + << RangeLoc << 1 << BeginRangeRef.get()->getType(); NoteForRangeBeginEndFunction(*this, BeginExpr.get(), BEF_begin); return StmtError(); } - // Attach *__begin as initializer for VD. - if (!LoopVar->isInvalidDecl()) { + // Attach *__begin as initializer for VD. Don't touch it if we're just + // trying to determine whether this would be a valid range. + if (!LoopVar->isInvalidDecl() && Kind != BFRK_Check) { AddInitializerToDecl(LoopVar, DerefExpr.get(), /*DirectInit=*/false, /*TypeMayContainAuto=*/true); if (LoopVar->isInvalidDecl()) @@ -1973,6 +2030,11 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, RangeVar->setUsed(); } + // Don't bother to actually allocate the result if we're just trying to + // determine whether it would be valid. + if (Kind == BFRK_Check) + return StmtResult(); + return Owned(new (Context) CXXForRangeStmt(RangeDS, cast_or_null<DeclStmt>(BeginEndDecl.get()), NotEqExpr.take(), IncrExpr.take(), @@ -2485,600 +2547,6 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { return Owned(Result); } -/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently -/// ignore "noop" casts in places where an lvalue is required by an inline asm. -/// We emulate this behavior when -fheinous-gnu-extensions is specified, but -/// provide a strong guidance to not use it. -/// -/// This method checks to see if the argument is an acceptable l-value and -/// returns false if it is a case we can handle. -static bool CheckAsmLValue(const Expr *E, Sema &S) { - // Type dependent expressions will be checked during instantiation. - if (E->isTypeDependent()) - return false; - - if (E->isLValue()) - return false; // Cool, this is an lvalue. - - // Okay, this is not an lvalue, but perhaps it is the result of a cast that we - // are supposed to allow. - const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); - if (E != E2 && E2->isLValue()) { - if (!S.getLangOpts().HeinousExtensions) - S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) - << E->getSourceRange(); - else - S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) - << E->getSourceRange(); - // Accept, even if we emitted an error diagnostic. - return false; - } - - // None of the above, just randomly invalid non-lvalue. - return true; -} - -/// isOperandMentioned - Return true if the specified operand # is mentioned -/// anywhere in the decomposed asm string. -static bool isOperandMentioned(unsigned OpNo, - ArrayRef<AsmStmt::AsmStringPiece> AsmStrPieces) { - for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { - const AsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; - if (!Piece.isOperand()) continue; - - // If this is a reference to the input and if the input was the smaller - // one, then we have to reject this asm. - if (Piece.getOperandNo() == OpNo) - return true; - } - return false; -} - -StmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsSimple, - bool IsVolatile, unsigned NumOutputs, - unsigned NumInputs, IdentifierInfo **Names, - MultiExprArg constraints, MultiExprArg exprs, - Expr *asmString, MultiExprArg clobbers, - SourceLocation RParenLoc, bool MSAsm) { - unsigned NumClobbers = clobbers.size(); - StringLiteral **Constraints = - reinterpret_cast<StringLiteral**>(constraints.get()); - Expr **Exprs = exprs.get(); - StringLiteral *AsmString = cast<StringLiteral>(asmString); - StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.get()); - - SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; - - // The parser verifies that there is a string literal here. - if (!AsmString->isAscii()) - return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) - << AsmString->getSourceRange()); - - for (unsigned i = 0; i != NumOutputs; i++) { - StringLiteral *Literal = Constraints[i]; - if (!Literal->isAscii()) - return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) - << Literal->getSourceRange()); - - StringRef OutputName; - if (Names[i]) - OutputName = Names[i]->getName(); - - TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); - if (!Context.getTargetInfo().validateOutputConstraint(Info)) - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_invalid_output_constraint) - << Info.getConstraintStr()); - - // Check that the output exprs are valid lvalues. - Expr *OutputExpr = Exprs[i]; - if (CheckAsmLValue(OutputExpr, *this)) { - return StmtError(Diag(OutputExpr->getLocStart(), - diag::err_asm_invalid_lvalue_in_output) - << OutputExpr->getSourceRange()); - } - - OutputConstraintInfos.push_back(Info); - } - - SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; - - for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { - StringLiteral *Literal = Constraints[i]; - if (!Literal->isAscii()) - return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) - << Literal->getSourceRange()); - - StringRef InputName; - if (Names[i]) - InputName = Names[i]->getName(); - - TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); - if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), - NumOutputs, Info)) { - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_invalid_input_constraint) - << Info.getConstraintStr()); - } - - Expr *InputExpr = Exprs[i]; - - // Only allow void types for memory constraints. - if (Info.allowsMemory() && !Info.allowsRegister()) { - if (CheckAsmLValue(InputExpr, *this)) - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_invalid_lvalue_in_input) - << Info.getConstraintStr() - << InputExpr->getSourceRange()); - } - - if (Info.allowsRegister()) { - if (InputExpr->getType()->isVoidType()) { - return StmtError(Diag(InputExpr->getLocStart(), - diag::err_asm_invalid_type_in_input) - << InputExpr->getType() << Info.getConstraintStr() - << InputExpr->getSourceRange()); - } - } - - ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); - if (Result.isInvalid()) - return StmtError(); - - Exprs[i] = Result.take(); - InputConstraintInfos.push_back(Info); - } - - // Check that the clobbers are valid. - for (unsigned i = 0; i != NumClobbers; i++) { - StringLiteral *Literal = Clobbers[i]; - if (!Literal->isAscii()) - return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) - << Literal->getSourceRange()); - - StringRef Clobber = Literal->getString(); - - if (!Context.getTargetInfo().isValidClobber(Clobber)) - return StmtError(Diag(Literal->getLocStart(), - diag::err_asm_unknown_register_name) << Clobber); - } - - AsmStmt *NS = - new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, - NumOutputs, NumInputs, Names, Constraints, Exprs, - AsmString, NumClobbers, Clobbers, RParenLoc); - // Validate the asm string, ensuring it makes sense given the operands we - // have. - SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; - unsigned DiagOffs; - if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { - Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) - << AsmString->getSourceRange(); - return StmtError(); - } - - // Validate tied input operands for type mismatches. - for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { - TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; - - // If this is a tied constraint, verify that the output and input have - // either exactly the same type, or that they are int/ptr operands with the - // same size (int/long, int*/long, are ok etc). - if (!Info.hasTiedOperand()) continue; - - unsigned TiedTo = Info.getTiedOperand(); - unsigned InputOpNo = i+NumOutputs; - Expr *OutputExpr = Exprs[TiedTo]; - Expr *InputExpr = Exprs[InputOpNo]; - - if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) - continue; - - QualType InTy = InputExpr->getType(); - QualType OutTy = OutputExpr->getType(); - if (Context.hasSameType(InTy, OutTy)) - continue; // All types can be tied to themselves. - - // Decide if the input and output are in the same domain (integer/ptr or - // floating point. - enum AsmDomain { - AD_Int, AD_FP, AD_Other - } InputDomain, OutputDomain; - - if (InTy->isIntegerType() || InTy->isPointerType()) - InputDomain = AD_Int; - else if (InTy->isRealFloatingType()) - InputDomain = AD_FP; - else - InputDomain = AD_Other; - - if (OutTy->isIntegerType() || OutTy->isPointerType()) - OutputDomain = AD_Int; - else if (OutTy->isRealFloatingType()) - OutputDomain = AD_FP; - else - OutputDomain = AD_Other; - - // They are ok if they are the same size and in the same domain. This - // allows tying things like: - // void* to int* - // void* to int if they are the same size. - // double to long double if they are the same size. - // - uint64_t OutSize = Context.getTypeSize(OutTy); - uint64_t InSize = Context.getTypeSize(InTy); - if (OutSize == InSize && InputDomain == OutputDomain && - InputDomain != AD_Other) - continue; - - // If the smaller input/output operand is not mentioned in the asm string, - // then we can promote the smaller one to a larger input and the asm string - // won't notice. - bool SmallerValueMentioned = false; - - // If this is a reference to the input and if the input was the smaller - // one, then we have to reject this asm. - if (isOperandMentioned(InputOpNo, Pieces)) { - // This is a use in the asm string of the smaller operand. Since we - // codegen this by promoting to a wider value, the asm will get printed - // "wrong". - SmallerValueMentioned |= InSize < OutSize; - } - if (isOperandMentioned(TiedTo, Pieces)) { - // If this is a reference to the output, and if the output is the larger - // value, then it's ok because we'll promote the input to the larger type. - SmallerValueMentioned |= OutSize < InSize; - } - - // If the smaller value wasn't mentioned in the asm string, and if the - // output was a register, just extend the shorter one to the size of the - // larger one. - if (!SmallerValueMentioned && InputDomain != AD_Other && - OutputConstraintInfos[TiedTo].allowsRegister()) - continue; - - // Either both of the operands were mentioned or the smaller one was - // mentioned. One more special case that we'll allow: if the tied input is - // integer, unmentioned, and is a constant, then we'll allow truncating it - // down to the size of the destination. - if (InputDomain == AD_Int && OutputDomain == AD_Int && - !isOperandMentioned(InputOpNo, Pieces) && - InputExpr->isEvaluatable(Context)) { - CastKind castKind = - (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); - InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); - Exprs[InputOpNo] = InputExpr; - NS->setInputExpr(i, InputExpr); - continue; - } - - Diag(InputExpr->getLocStart(), - diag::err_asm_tying_incompatible_types) - << InTy << OutTy << OutputExpr->getSourceRange() - << InputExpr->getSourceRange(); - return StmtError(); - } - - return Owned(NS); -} - -// isMSAsmKeyword - Return true if this is an MS-style inline asm keyword. These -// require special handling. -static bool isMSAsmKeyword(StringRef Name) { - bool Ret = llvm::StringSwitch<bool>(Name) - .Cases("EVEN", "ALIGN", true) // Alignment directives. - .Cases("LENGTH", "SIZE", "TYPE", true) // Type and variable sizes. - .Case("_emit", true) // _emit Pseudoinstruction. - .Default(false); - return Ret; -} - -static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { - StringRef Asm; - SmallString<512> TokenBuf; - TokenBuf.resize(512); - bool StringInvalid = false; - Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); - assert (!StringInvalid && "Expected valid string!"); - return Asm; -} - -static void patchMSAsmStrings(Sema &SemaRef, bool &IsSimple, - SourceLocation AsmLoc, - ArrayRef<Token> AsmToks, - const TargetInfo &TI, - std::vector<llvm::BitVector> &AsmRegs, - std::vector<llvm::BitVector> &AsmNames, - std::vector<std::string> &AsmStrings) { - assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); - - // Assume simple asm stmt until we parse a non-register identifer (or we just - // need to bail gracefully). - IsSimple = true; - - SmallString<512> Asm; - unsigned NumAsmStrings = 0; - for (unsigned i = 0, e = AsmToks.size(); i != e; ++i) { - - // Determine if this should be considered a new asm. - bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || - AsmToks[i].is(tok::kw_asm); - - // Emit the previous asm string. - if (i && isNewAsm) { - AsmStrings[NumAsmStrings++] = Asm.c_str(); - if (AsmToks[i].is(tok::kw_asm)) { - ++i; // Skip __asm - assert (i != e && "Expected another token."); - } - } - - // Start a new asm string with the opcode. - if (isNewAsm) { - AsmRegs[NumAsmStrings].resize(AsmToks.size()); - AsmNames[NumAsmStrings].resize(AsmToks.size()); - - StringRef Piece = AsmToks[i].getIdentifierInfo()->getName(); - // MS-style inline asm keywords require special handling. - if (isMSAsmKeyword(Piece)) - IsSimple = false; - - // TODO: Verify this is a valid opcode. - Asm = Piece; - continue; - } - - if (i && AsmToks[i].hasLeadingSpace()) - Asm += ' '; - - // Check the operand(s). - switch (AsmToks[i].getKind()) { - default: - IsSimple = false; - Asm += getSpelling(SemaRef, AsmToks[i]); - break; - case tok::comma: Asm += ","; break; - case tok::colon: Asm += ":"; break; - case tok::l_square: Asm += "["; break; - case tok::r_square: Asm += "]"; break; - case tok::l_brace: Asm += "{"; break; - case tok::r_brace: Asm += "}"; break; - case tok::numeric_constant: - Asm += getSpelling(SemaRef, AsmToks[i]); - break; - case tok::identifier: { - IdentifierInfo *II = AsmToks[i].getIdentifierInfo(); - StringRef Name = II->getName(); - - // Valid register? - if (TI.isValidGCCRegisterName(Name)) { - AsmRegs[NumAsmStrings].set(i); - Asm += Name; - break; - } - - IsSimple = false; - - // MS-style inline asm keywords require special handling. - if (isMSAsmKeyword(Name)) { - IsSimple = false; - Asm += Name; - break; - } - - // FIXME: Why are we missing this segment register? - if (Name == "fs") { - Asm += Name; - break; - } - - // Lookup the identifier. - // TODO: Someone with more experience with clang should verify this the - // proper way of doing a symbol lookup. - DeclarationName DeclName(II); - Scope *CurScope = SemaRef.getCurScope(); - LookupResult R(SemaRef, DeclName, AsmLoc, Sema::LookupOrdinaryName); - if (!SemaRef.LookupName(R, CurScope, false/*AllowBuiltinCreation*/)) - break; - - assert (R.isSingleResult() && "Expected a single result?!"); - NamedDecl *Decl = R.getFoundDecl(); - switch (Decl->getKind()) { - default: - assert(0 && "Unknown decl kind."); - break; - case Decl::Var: { - case Decl::ParmVar: - AsmNames[NumAsmStrings].set(i); - - VarDecl *Var = cast<VarDecl>(Decl); - QualType Ty = Var->getType(); - (void)Ty; // Avoid warning. - // TODO: Patch identifier with valid operand. One potential idea is to - // probe the backend with type information to guess the possible - // operand. - break; - } - } - break; - } - } - } - - // Emit the final (and possibly only) asm string. - AsmStrings[NumAsmStrings] = Asm.c_str(); -} - -// Build the unmodified MSAsmString. -static std::string buildMSAsmString(Sema &SemaRef, - ArrayRef<Token> AsmToks, - unsigned &NumAsmStrings) { - assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); - NumAsmStrings = 0; - - SmallString<512> Asm; - for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { - bool isNewAsm = i == 0 || AsmToks[i].isAtStartOfLine() || - AsmToks[i].is(tok::kw_asm); - - if (isNewAsm) { - ++NumAsmStrings; - if (i) - Asm += '\n'; - if (AsmToks[i].is(tok::kw_asm)) { - i++; // Skip __asm - assert (i != e && "Expected another token"); - } - } - - if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) - Asm += ' '; - - Asm += getSpelling(SemaRef, AsmToks[i]); - } - return Asm.c_str(); -} - -StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, - SourceLocation LBraceLoc, - ArrayRef<Token> AsmToks, - SourceLocation EndLoc) { - // MS-style inline assembly is not fully supported, so emit a warning. - Diag(AsmLoc, diag::warn_unsupported_msasm); - SmallVector<StringRef,4> Clobbers; - std::set<std::string> ClobberRegs; - SmallVector<IdentifierInfo*, 4> Inputs; - SmallVector<IdentifierInfo*, 4> Outputs; - - // Empty asm statements don't need to instantiate the AsmParser, etc. - if (AsmToks.empty()) { - StringRef AsmString; - MSAsmStmt *NS = - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, - /*IsVolatile*/ true, AsmToks, Inputs, Outputs, - AsmString, Clobbers, EndLoc); - return Owned(NS); - } - - unsigned NumAsmStrings; - std::string AsmString = buildMSAsmString(*this, AsmToks, NumAsmStrings); - - bool IsSimple; - std::vector<llvm::BitVector> Regs; - std::vector<llvm::BitVector> Names; - std::vector<std::string> PatchedAsmStrings; - - Regs.resize(NumAsmStrings); - Names.resize(NumAsmStrings); - PatchedAsmStrings.resize(NumAsmStrings); - - // Rewrite operands to appease the AsmParser. - patchMSAsmStrings(*this, IsSimple, AsmLoc, AsmToks, - Context.getTargetInfo(), Regs, Names, PatchedAsmStrings); - - // patchMSAsmStrings doesn't correctly patch non-simple asm statements. - if (!IsSimple) { - MSAsmStmt *NS = - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, - /*IsVolatile*/ true, AsmToks, Inputs, Outputs, - AsmString, Clobbers, EndLoc); - return Owned(NS); - } - - // Initialize targets and assembly printers/parsers. - llvm::InitializeAllTargetInfos(); - llvm::InitializeAllTargetMCs(); - llvm::InitializeAllAsmParsers(); - - // Get the target specific parser. - std::string Error; - const std::string &TT = Context.getTargetInfo().getTriple().getTriple(); - const llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); - - OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); - OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); - OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); - OwningPtr<llvm::MCSubtargetInfo> - STI(TheTarget->createMCSubtargetInfo(TT, "", "")); - - for (unsigned i = 0, e = PatchedAsmStrings.size(); i != e; ++i) { - llvm::SourceMgr SrcMgr; - llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); - llvm::MemoryBuffer *Buffer = - llvm::MemoryBuffer::getMemBuffer(PatchedAsmStrings[i], "<inline asm>"); - - // Tell SrcMgr about this buffer, which is what the parser will pick up. - SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); - - OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); - OwningPtr<llvm::MCAsmParser> - Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); - OwningPtr<llvm::MCTargetAsmParser> - TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); - // Change to the Intel dialect. - Parser->setAssemblerDialect(1); - Parser->setTargetParser(*TargetParser.get()); - - // Prime the lexer. - Parser->Lex(); - - // Parse the opcode. - StringRef IDVal; - Parser->ParseIdentifier(IDVal); - - // Canonicalize the opcode to lower case. - SmallString<128> Opcode; - for (unsigned i = 0, e = IDVal.size(); i != e; ++i) - Opcode.push_back(tolower(IDVal[i])); - - // Parse the operands. - llvm::SMLoc IDLoc; - SmallVector<llvm::MCParsedAsmOperand*, 8> Operands; - bool HadError = TargetParser->ParseInstruction(Opcode.str(), IDLoc, - Operands); - assert (!HadError && "Unexpected error parsing instruction"); - - // Match the MCInstr. - SmallVector<llvm::MCInst, 2> Instrs; - HadError = TargetParser->MatchInstruction(IDLoc, Operands, Instrs); - assert (!HadError && "Unexpected error matching instruction"); - assert ((Instrs.size() == 1) && "Expected only a single instruction."); - - // Get the instruction descriptor. - llvm::MCInst Inst = Instrs[0]; - const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); - const llvm::MCInstrDesc &Desc = MII->get(Inst.getOpcode()); - llvm::MCInstPrinter *IP = - TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); - - // Build the list of clobbers. - for (unsigned i = 0, e = Desc.getNumDefs(); i != e; ++i) { - const llvm::MCOperand &Op = Inst.getOperand(i); - if (!Op.isReg()) - continue; - - std::string Reg; - llvm::raw_string_ostream OS(Reg); - IP->printRegName(OS, Op.getReg()); - - StringRef Clobber(OS.str()); - if (!Context.getTargetInfo().isValidClobber(Clobber)) - return StmtError(Diag(AsmLoc, diag::err_asm_unknown_register_name) << - Clobber); - ClobberRegs.insert(Reg); - } - } - for (std::set<std::string>::iterator I = ClobberRegs.begin(), - E = ClobberRegs.end(); I != E; ++I) - Clobbers.push_back(*I); - - MSAsmStmt *NS = - new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, - /*IsVolatile*/ true, AsmToks, Inputs, Outputs, - AsmString, Clobbers, EndLoc); - return Owned(NS); -} - StmtResult Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc, SourceLocation RParen, Decl *Parm, @@ -3104,7 +2572,7 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc, Stmt *Try, getCurFunction()->setHasBranchProtectedScope(); unsigned NumCatchStmts = CatchStmts.size(); return Owned(ObjCAtTryStmt::Create(Context, AtLoc, Try, - CatchStmts.release(), + CatchStmts.data(), NumCatchStmts, Finally)); } @@ -3239,7 +2707,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, unsigned NumHandlers = RawHandlers.size(); assert(NumHandlers > 0 && "The parser shouldn't call this if there are no handlers."); - Stmt **Handlers = RawHandlers.get(); + Stmt **Handlers = RawHandlers.data(); SmallVector<TypeWithHandler, 8> TypesWithHandlers; diff --git a/lib/Sema/SemaStmtAsm.cpp b/lib/Sema/SemaStmtAsm.cpp new file mode 100644 index 0000000..7c2c766 --- /dev/null +++ b/lib/Sema/SemaStmtAsm.cpp @@ -0,0 +1,661 @@ +//===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements semantic analysis for inline asm statements. +// +//===----------------------------------------------------------------------===// + +#include "clang/Sema/SemaInternal.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/ScopeInfo.h" +#include "clang/Sema/Initialization.h" +#include "clang/Sema/Lookup.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/TypeLoc.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Basic/TargetInfo.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/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" +using namespace clang; +using namespace sema; + +/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently +/// ignore "noop" casts in places where an lvalue is required by an inline asm. +/// We emulate this behavior when -fheinous-gnu-extensions is specified, but +/// provide a strong guidance to not use it. +/// +/// This method checks to see if the argument is an acceptable l-value and +/// returns false if it is a case we can handle. +static bool CheckAsmLValue(const Expr *E, Sema &S) { + // Type dependent expressions will be checked during instantiation. + if (E->isTypeDependent()) + return false; + + if (E->isLValue()) + return false; // Cool, this is an lvalue. + + // Okay, this is not an lvalue, but perhaps it is the result of a cast that we + // are supposed to allow. + const Expr *E2 = E->IgnoreParenNoopCasts(S.Context); + if (E != E2 && E2->isLValue()) { + if (!S.getLangOpts().HeinousExtensions) + S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue) + << E->getSourceRange(); + else + S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue) + << E->getSourceRange(); + // Accept, even if we emitted an error diagnostic. + return false; + } + + // None of the above, just randomly invalid non-lvalue. + return true; +} + +/// isOperandMentioned - Return true if the specified operand # is mentioned +/// anywhere in the decomposed asm string. +static bool isOperandMentioned(unsigned OpNo, + ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) { + for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) { + const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p]; + if (!Piece.isOperand()) continue; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (Piece.getOperandNo() == OpNo) + return true; + } + return false; +} + +StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg constraints, MultiExprArg exprs, + Expr *asmString, MultiExprArg clobbers, + SourceLocation RParenLoc) { + unsigned NumClobbers = clobbers.size(); + StringLiteral **Constraints = + reinterpret_cast<StringLiteral**>(constraints.data()); + Expr **Exprs = exprs.data(); + StringLiteral *AsmString = cast<StringLiteral>(asmString); + StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data()); + + SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; + + // The parser verifies that there is a string literal here. + if (!AsmString->isAscii()) + return StmtError(Diag(AsmString->getLocStart(),diag::err_asm_wide_character) + << AsmString->getSourceRange()); + + for (unsigned i = 0; i != NumOutputs; i++) { + StringLiteral *Literal = Constraints[i]; + if (!Literal->isAscii()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + StringRef OutputName; + if (Names[i]) + OutputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); + if (!Context.getTargetInfo().validateOutputConstraint(Info)) + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_invalid_output_constraint) + << Info.getConstraintStr()); + + // Check that the output exprs are valid lvalues. + Expr *OutputExpr = Exprs[i]; + if (CheckAsmLValue(OutputExpr, *this)) { + return StmtError(Diag(OutputExpr->getLocStart(), + diag::err_asm_invalid_lvalue_in_output) + << OutputExpr->getSourceRange()); + } + + OutputConstraintInfos.push_back(Info); + } + + SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos; + + for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { + StringLiteral *Literal = Constraints[i]; + if (!Literal->isAscii()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + StringRef InputName; + if (Names[i]) + InputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); + if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos.data(), + NumOutputs, Info)) { + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_invalid_input_constraint) + << Info.getConstraintStr()); + } + + Expr *InputExpr = Exprs[i]; + + // Only allow void types for memory constraints. + if (Info.allowsMemory() && !Info.allowsRegister()) { + if (CheckAsmLValue(InputExpr, *this)) + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_lvalue_in_input) + << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } + + if (Info.allowsRegister()) { + if (InputExpr->getType()->isVoidType()) { + return StmtError(Diag(InputExpr->getLocStart(), + diag::err_asm_invalid_type_in_input) + << InputExpr->getType() << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } + } + + ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); + if (Result.isInvalid()) + return StmtError(); + + Exprs[i] = Result.take(); + InputConstraintInfos.push_back(Info); + } + + // Check that the clobbers are valid. + for (unsigned i = 0; i != NumClobbers; i++) { + StringLiteral *Literal = Clobbers[i]; + if (!Literal->isAscii()) + return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) + << Literal->getSourceRange()); + + StringRef Clobber = Literal->getString(); + + if (!Context.getTargetInfo().isValidClobber(Clobber)) + return StmtError(Diag(Literal->getLocStart(), + diag::err_asm_unknown_register_name) << Clobber); + } + + GCCAsmStmt *NS = + new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, + NumInputs, Names, Constraints, Exprs, AsmString, + NumClobbers, Clobbers, RParenLoc); + // Validate the asm string, ensuring it makes sense given the operands we + // have. + SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces; + unsigned DiagOffs; + if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) { + Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID) + << AsmString->getSourceRange(); + return StmtError(); + } + + // Validate constraints and modifiers. + for (unsigned i = 0, e = Pieces.size(); i != e; ++i) { + GCCAsmStmt::AsmStringPiece &Piece = Pieces[i]; + if (!Piece.isOperand()) continue; + + // Look for the correct constraint index. + unsigned Idx = 0; + unsigned ConstraintIdx = 0; + for (unsigned i = 0, e = NS->getNumOutputs(); i != e; ++i, ++ConstraintIdx) { + TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i]; + if (Idx == Piece.getOperandNo()) + break; + ++Idx; + + if (Info.isReadWrite()) { + if (Idx == Piece.getOperandNo()) + break; + ++Idx; + } + } + + for (unsigned i = 0, e = NS->getNumInputs(); i != e; ++i, ++ConstraintIdx) { + TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; + if (Idx == Piece.getOperandNo()) + break; + ++Idx; + + if (Info.isReadWrite()) { + if (Idx == Piece.getOperandNo()) + break; + ++Idx; + } + } + + // Now that we have the right indexes go ahead and check. + StringLiteral *Literal = Constraints[ConstraintIdx]; + const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr(); + if (Ty->isDependentType() || Ty->isIncompleteType()) + continue; + + unsigned Size = Context.getTypeSize(Ty); + if (!Context.getTargetInfo() + .validateConstraintModifier(Literal->getString(), Piece.getModifier(), + Size)) + Diag(Exprs[ConstraintIdx]->getLocStart(), + diag::warn_asm_mismatched_size_modifier); + } + + // Validate tied input operands for type mismatches. + for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) { + TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i]; + + // If this is a tied constraint, verify that the output and input have + // either exactly the same type, or that they are int/ptr operands with the + // same size (int/long, int*/long, are ok etc). + if (!Info.hasTiedOperand()) continue; + + unsigned TiedTo = Info.getTiedOperand(); + unsigned InputOpNo = i+NumOutputs; + Expr *OutputExpr = Exprs[TiedTo]; + Expr *InputExpr = Exprs[InputOpNo]; + + if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent()) + continue; + + QualType InTy = InputExpr->getType(); + QualType OutTy = OutputExpr->getType(); + if (Context.hasSameType(InTy, OutTy)) + continue; // All types can be tied to themselves. + + // Decide if the input and output are in the same domain (integer/ptr or + // floating point. + enum AsmDomain { + AD_Int, AD_FP, AD_Other + } InputDomain, OutputDomain; + + if (InTy->isIntegerType() || InTy->isPointerType()) + InputDomain = AD_Int; + else if (InTy->isRealFloatingType()) + InputDomain = AD_FP; + else + InputDomain = AD_Other; + + if (OutTy->isIntegerType() || OutTy->isPointerType()) + OutputDomain = AD_Int; + else if (OutTy->isRealFloatingType()) + OutputDomain = AD_FP; + else + OutputDomain = AD_Other; + + // They are ok if they are the same size and in the same domain. This + // allows tying things like: + // void* to int* + // void* to int if they are the same size. + // double to long double if they are the same size. + // + uint64_t OutSize = Context.getTypeSize(OutTy); + uint64_t InSize = Context.getTypeSize(InTy); + if (OutSize == InSize && InputDomain == OutputDomain && + InputDomain != AD_Other) + continue; + + // If the smaller input/output operand is not mentioned in the asm string, + // then we can promote the smaller one to a larger input and the asm string + // won't notice. + bool SmallerValueMentioned = false; + + // If this is a reference to the input and if the input was the smaller + // one, then we have to reject this asm. + if (isOperandMentioned(InputOpNo, Pieces)) { + // This is a use in the asm string of the smaller operand. Since we + // codegen this by promoting to a wider value, the asm will get printed + // "wrong". + SmallerValueMentioned |= InSize < OutSize; + } + if (isOperandMentioned(TiedTo, Pieces)) { + // If this is a reference to the output, and if the output is the larger + // value, then it's ok because we'll promote the input to the larger type. + SmallerValueMentioned |= OutSize < InSize; + } + + // If the smaller value wasn't mentioned in the asm string, and if the + // output was a register, just extend the shorter one to the size of the + // larger one. + if (!SmallerValueMentioned && InputDomain != AD_Other && + OutputConstraintInfos[TiedTo].allowsRegister()) + continue; + + // Either both of the operands were mentioned or the smaller one was + // mentioned. One more special case that we'll allow: if the tied input is + // integer, unmentioned, and is a constant, then we'll allow truncating it + // down to the size of the destination. + if (InputDomain == AD_Int && OutputDomain == AD_Int && + !isOperandMentioned(InputOpNo, Pieces) && + InputExpr->isEvaluatable(Context)) { + CastKind castKind = + (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast); + InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).take(); + Exprs[InputOpNo] = InputExpr; + NS->setInputExpr(i, InputExpr); + continue; + } + + Diag(InputExpr->getLocStart(), + diag::err_asm_tying_incompatible_types) + << InTy << OutTy << OutputExpr->getSourceRange() + << InputExpr->getSourceRange(); + return StmtError(); + } + + return Owned(NS); +} + +// getSpelling - Get the spelling of the AsmTok token. +static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { + StringRef Asm; + SmallString<512> TokenBuf; + TokenBuf.resize(512); + bool StringInvalid = false; + Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); + assert (!StringInvalid && "Expected valid string!"); + return Asm; +} + +// Build the inline assembly string. Returns true on error. +static bool buildMSAsmString(Sema &SemaRef, + SourceLocation AsmLoc, + ArrayRef<Token> AsmToks, + llvm::SmallVectorImpl<unsigned> &TokOffsets, + std::string &AsmString) { + assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); + + SmallString<512> Asm; + for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { + bool isNewAsm = ((i == 0) || + AsmToks[i].isAtStartOfLine() || + AsmToks[i].is(tok::kw_asm)); + if (isNewAsm) { + if (i != 0) + Asm += "\n\t"; + + if (AsmToks[i].is(tok::kw_asm)) { + i++; // Skip __asm + if (i == e) { + SemaRef.Diag(AsmLoc, diag::err_asm_empty); + return true; + } + + } + } + + if (i && AsmToks[i].hasLeadingSpace() && !isNewAsm) + Asm += ' '; + + StringRef Spelling = getSpelling(SemaRef, AsmToks[i]); + Asm += Spelling; + TokOffsets.push_back(Asm.size()); + } + AsmString = Asm.str(); + return false; +} + +namespace { + +class MCAsmParserSemaCallbackImpl : public llvm::MCAsmParserSemaCallback { + Sema &SemaRef; + SourceLocation AsmLoc; + ArrayRef<Token> AsmToks; + ArrayRef<unsigned> TokOffsets; + +public: + MCAsmParserSemaCallbackImpl(Sema &Ref, SourceLocation Loc, + ArrayRef<Token> Toks, + ArrayRef<unsigned> Offsets) + : SemaRef(Ref), AsmLoc(Loc), AsmToks(Toks), TokOffsets(Offsets) { } + ~MCAsmParserSemaCallbackImpl() {} + + void *LookupInlineAsmIdentifier(StringRef Name, void *SrcLoc, unsigned &Size){ + SourceLocation Loc = SourceLocation::getFromPtrEncoding(SrcLoc); + NamedDecl *OpDecl = SemaRef.LookupInlineAsmIdentifier(Name, Loc, Size); + return static_cast<void *>(OpDecl); + } + + bool LookupInlineAsmField(StringRef Base, StringRef Member, + unsigned &Offset) { + return SemaRef.LookupInlineAsmField(Base, Member, Offset, AsmLoc); + } + + static void MSAsmDiagHandlerCallback(const llvm::SMDiagnostic &D, + void *Context) { + ((MCAsmParserSemaCallbackImpl*)Context)->MSAsmDiagHandler(D); + } + void MSAsmDiagHandler(const llvm::SMDiagnostic &D) { + // Compute an offset into the inline asm buffer. + // FIXME: This isn't right if .macro is involved (but hopefully, no + // real-world code does that). + const llvm::SourceMgr &LSM = *D.getSourceMgr(); + const llvm::MemoryBuffer *LBuf = + LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); + unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); + + // Figure out which token that offset points into. + const unsigned *OffsetPtr = + std::lower_bound(TokOffsets.begin(), TokOffsets.end(), Offset); + unsigned TokIndex = OffsetPtr - TokOffsets.begin(); + + // If we come up with an answer which seems sane, use it; otherwise, + // just point at the __asm keyword. + // FIXME: Assert the answer is sane once we handle .macro correctly. + SourceLocation Loc = AsmLoc; + if (TokIndex < AsmToks.size()) { + const Token *Tok = &AsmToks[TokIndex]; + Loc = Tok->getLocation(); + Loc = Loc.getLocWithOffset(Offset - (*OffsetPtr - Tok->getLength())); + } + SemaRef.Diag(Loc, diag::err_inline_ms_asm_parsing) << D.getMessage(); + } +}; + +} + +NamedDecl *Sema::LookupInlineAsmIdentifier(StringRef Name, SourceLocation Loc, + unsigned &Size) { + Size = 0; + LookupResult Result(*this, &Context.Idents.get(Name), Loc, + Sema::LookupOrdinaryName); + + if (!LookupName(Result, getCurScope())) { + // If we don't find anything, return null; the AsmParser will assume + // it is a label of some sort. + return 0; + } + + if (!Result.isSingleResult()) { + // FIXME: Diagnose result. + 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; + } + + // FIXME: Handle other kinds of results? (FieldDecl, etc.) + // FIXME: Diagnose if we find something we can't handle, like a typedef. + return 0; +} + +bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member, + unsigned &Offset, SourceLocation AsmLoc) { + Offset = 0; + LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(), + LookupOrdinaryName); + + if (!LookupName(BaseResult, getCurScope())) + return true; + + if (!BaseResult.isSingleResult()) + return true; + + NamedDecl *FoundDecl = BaseResult.getFoundDecl(); + const RecordType *RT = 0; + if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl)) { + RT = VD->getType()->getAs<RecordType>(); + } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(FoundDecl)) { + RT = TD->getUnderlyingType()->getAs<RecordType>(); + } + if (!RT) + return true; + + if (RequireCompleteType(AsmLoc, QualType(RT, 0), 0)) + return true; + + LookupResult FieldResult(*this, &Context.Idents.get(Member), SourceLocation(), + LookupMemberName); + + if (!LookupQualifiedName(FieldResult, RT->getDecl())) + return true; + + // FIXME: Handle IndirectFieldDecl? + FieldDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); + if (!FD) + return true; + + const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl()); + unsigned i = FD->getFieldIndex(); + CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i)); + Offset = (unsigned)Result.getQuantity(); + + return false; +} + +StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, + ArrayRef<Token> AsmToks,SourceLocation EndLoc) { + SmallVector<IdentifierInfo*, 4> Names; + SmallVector<StringRef, 4> ConstraintRefs; + SmallVector<Expr*, 4> Exprs; + SmallVector<StringRef, 4> ClobberRefs; + + // Empty asm statements don't need to instantiate the AsmParser, etc. + if (AsmToks.empty()) { + StringRef EmptyAsmStr; + MSAsmStmt *NS = + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, /*IsSimple*/ true, + /*IsVolatile*/ true, AsmToks, /*NumOutputs*/ 0, + /*NumInputs*/ 0, Names, ConstraintRefs, Exprs, + EmptyAsmStr, ClobberRefs, EndLoc); + return Owned(NS); + } + + std::string AsmString; + llvm::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 llvm::Target *TheTarget(llvm::TargetRegistry::lookupTarget(TT, Error)); + + OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT)); + OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); + OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); + OwningPtr<llvm::MCSubtargetInfo> + STI(TheTarget->createMCSubtargetInfo(TT, "", "")); + + llvm::SourceMgr SrcMgr; + llvm::MCContext Ctx(*MAI, *MRI, MOFI.get(), &SrcMgr); + llvm::MemoryBuffer *Buffer = + llvm::MemoryBuffer::getMemBuffer(AsmString, "<inline asm>"); + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + SrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); + + OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); + OwningPtr<llvm::MCAsmParser> + Parser(createMCAsmParser(SrcMgr, Ctx, *Str.get(), *MAI)); + OwningPtr<llvm::MCTargetAsmParser> + TargetParser(TheTarget->createMCAsmParser(*STI, *Parser)); + + // Get the instruction descriptor. + const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); + llvm::MCInstPrinter *IP = + TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); + + // Change to the Intel dialect. + Parser->setAssemblerDialect(1); + Parser->setTargetParser(*TargetParser.get()); + Parser->setParsingInlineAsm(true); + TargetParser->setParsingInlineAsm(true); + + MCAsmParserSemaCallbackImpl MCAPSI(*this, AsmLoc, AsmToks, TokOffsets); + TargetParser->setSemaCallback(&MCAPSI); + SrcMgr.setDiagHandler(MCAsmParserSemaCallbackImpl::MSAsmDiagHandlerCallback, + &MCAPSI); + + unsigned NumOutputs; + unsigned NumInputs; + std::string AsmStringIR; + SmallVector<std::pair<void *, bool>, 4> OpDecls; + SmallVector<std::string, 4> Constraints; + SmallVector<std::string, 4> Clobbers; + if (Parser->ParseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, + NumOutputs, NumInputs, OpDecls, Constraints, + Clobbers, MII, IP, MCAPSI)) + return StmtError(); + + // Build the vector of clobber StringRefs. + unsigned NumClobbers = Clobbers.size(); + ClobberRefs.resize(NumClobbers); + for (unsigned i = 0; i != NumClobbers; ++i) + ClobberRefs[i] = StringRef(Clobbers[i]); + + // Recast the void pointers and build the vector of constraint StringRefs. + unsigned NumExprs = NumOutputs + NumInputs; + Names.resize(NumExprs); + ConstraintRefs.resize(NumExprs); + Exprs.resize(NumExprs); + for (unsigned i = 0, e = NumExprs; i != e; ++i) { + NamedDecl *OpDecl = static_cast<NamedDecl *>(OpDecls[i].first); + if (!OpDecl) + return StmtError(); + + DeclarationNameInfo NameInfo(OpDecl->getDeclName(), AsmLoc); + ExprResult OpExpr = BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, + OpDecl); + if (OpExpr.isInvalid()) + return StmtError(); + + // Need offset of variable. + if (OpDecls[i].second) + OpExpr = BuildUnaryOp(getCurScope(), AsmLoc, clang::UO_AddrOf, + OpExpr.take()); + + Names[i] = OpDecl->getIdentifier(); + ConstraintRefs[i] = StringRef(Constraints[i]); + Exprs[i] = OpExpr.take(); + } + + bool IsSimple = NumExprs > 0; + MSAsmStmt *NS = + new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, + /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs, + Names, ConstraintRefs, Exprs, AsmStringIR, + ClobberRefs, EndLoc); + return Owned(NS); +} diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp index 3c15b7a..b268b45 100644 --- a/lib/Sema/SemaStmtAttr.cpp +++ b/lib/Sema/SemaStmtAttr.cpp @@ -48,11 +48,16 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A, static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, SourceRange Range) { switch (A.getKind()) { + case AttributeList::UnknownAttribute: + S.Diag(A.getLoc(), A.isDeclspecAttribute() ? + diag::warn_unhandled_ms_attribute_ignored : + diag::warn_unknown_attribute_ignored) << A.getName(); + return 0; case AttributeList::AT_FallThrough: return handleFallThroughAttr(S, St, A, Range); default: - // if we're here, then we parsed an attribute, but didn't recognize it as a - // statement attribute => it is declaration attribute + // 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(); return 0; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 4dbf3e4..f56b054 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -333,7 +333,8 @@ void Sema::LookupTemplateName(LookupResult &Found, if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); else Diag(Found.getNameLoc(), diag::err_no_template_suggest) << Name << CorrectedQuotedStr @@ -1104,6 +1105,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Attr) ProcessDeclAttributeList(S, NewClass, Attr); + if (PrevClassTemplate) + mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); + AddPushedVisibilityAttribute(NewClass); if (TUK != TUK_Friend) @@ -1138,8 +1142,6 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, NewTemplate->setInvalidDecl(); NewClass->setInvalidDecl(); } - if (PrevClassTemplate) - mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); ActOnDocumentableDecl(NewTemplate); @@ -1204,11 +1206,17 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, /// of a template template parameter, recursively. static bool DiagnoseUnexpandedParameterPacks(Sema &S, TemplateTemplateParmDecl *TTP) { + // A template template parameter which is a parameter pack is also a pack + // expansion. + if (TTP->isParameterPack()) + return false; + TemplateParameterList *Params = TTP->getTemplateParameters(); for (unsigned I = 0, N = Params->size(); I != N; ++I) { NamedDecl *P = Params->getParam(I); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { - if (S.DiagnoseUnexpandedParameterPack(NTTP->getLocation(), + if (!NTTP->isParameterPack() && + S.DiagnoseUnexpandedParameterPack(NTTP->getLocation(), NTTP->getTypeSourceInfo(), Sema::UPPC_NonTypeTemplateParameterType)) return true; @@ -1321,7 +1329,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (NonTypeTemplateParmDecl *NewNonTypeParm = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) { // Check for unexpanded parameter packs. - if (DiagnoseUnexpandedParameterPack(NewNonTypeParm->getLocation(), + if (!NewNonTypeParm->isParameterPack() && + DiagnoseUnexpandedParameterPack(NewNonTypeParm->getLocation(), NewNonTypeParm->getTypeSourceInfo(), UPPC_NonTypeTemplateParameterType)) { Invalid = true; @@ -1342,7 +1351,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, if (NewNonTypeParm->isParameterPack()) { assert(!NewNonTypeParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); - SawParameterPack = true; + if (!NewNonTypeParm->isPackExpansion()) + SawParameterPack = true; } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && NewNonTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); @@ -1389,7 +1399,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, if (NewTemplateParm->isParameterPack()) { assert(!NewTemplateParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); - SawParameterPack = true; + if (!NewTemplateParm->isPackExpansion()) + SawParameterPack = true; } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && NewTemplateParm->hasDefaultArgument()) { OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); @@ -1416,10 +1427,10 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, MissingDefaultArg = true; } - // C++0x [temp.param]p11: + // C++11 [temp.param]p11: // If a template parameter of a primary class template or alias template // is a template parameter pack, it shall be the last template parameter. - if (SawParameterPack && (NewParam + 1) != NewParamEnd && + if (SawParameterPack && (NewParam + 1) != NewParamEnd && (TPC == TPC_ClassTemplate || TPC == TPC_TypeAliasTemplate)) { Diag((*NewParam)->getLocation(), diag::err_template_param_pack_must_be_last_template_parameter); @@ -1998,9 +2009,11 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, for (unsigned I = 0; I < Depth; ++I) TemplateArgLists.addOuterTemplateArguments(0, 0); + LocalInstantiationScope Scope(*this); InstantiatingTemplate Inst(*this, TemplateLoc, Template); if (Inst) return QualType(); + CanonType = SubstType(Pattern->getUnderlyingType(), TemplateArgLists, AliasTemplate->getLocation(), AliasTemplate->getDeclName()); @@ -2085,7 +2098,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Converted.data(), Converted.size(), 0); ClassTemplate->AddSpecialization(Decl, InsertPos); - Decl->setLexicalDeclContext(CurContext); + if (ClassTemplate->isOutOfLine()) + Decl->setLexicalDeclContext(ClassTemplate->getLexicalDeclContext()); } CanonType = Context.getTypeDeclType(Decl); @@ -2137,7 +2151,6 @@ Sema::ActOnTemplateIdType(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, } QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); - TemplateArgsIn.release(); if (Result.isNull()) return true; @@ -2831,6 +2844,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, case TemplateArgument::Declaration: case TemplateArgument::Integral: + case TemplateArgument::NullPtr: // We've already checked this template argument, so just copy // it to the list of converted arguments. Converted.push_back(Arg.getArgument()); @@ -2947,7 +2961,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (CheckTemplateArgument(TempParm, Arg)) + if (CheckTemplateArgument(TempParm, Arg, ArgumentPackIndex)) return true; Converted.push_back(Arg.getArgument()); @@ -2965,6 +2979,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, llvm_unreachable("Declaration argument with template template parameter"); case TemplateArgument::Integral: llvm_unreachable("Integral argument with template template parameter"); + case TemplateArgument::NullPtr: + llvm_unreachable("Null pointer argument with template template parameter"); case TemplateArgument::Pack: llvm_unreachable("Caller must expand template argument packs"); @@ -2996,6 +3012,33 @@ static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template, return true; } +/// \brief Check whether the template parameter is a pack expansion, and if so, +/// determine the number of parameters produced by that expansion. For instance: +/// +/// \code +/// template<typename ...Ts> struct A { +/// template<Ts ...NTs, template<Ts> class ...TTs, typename ...Us> struct B; +/// }; +/// \endcode +/// +/// 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) { + if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (NTTP->isExpandedParameterPack()) + return NTTP->getNumExpansionTypes(); + } + + if (TemplateTemplateParmDecl *TTP + = dyn_cast<TemplateTemplateParmDecl>(Param)) { + if (TTP->isExpandedParameterPack()) + return TTP->getNumExpansionTemplateParameters(); + } + + return llvm::Optional<unsigned>(); +} + /// \brief Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, @@ -3008,15 +3051,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, *ExpansionIntoFixedList = false; TemplateParameterList *Params = Template->getTemplateParameters(); - unsigned NumParams = Params->size(); - unsigned NumArgs = TemplateArgs.size(); - bool Invalid = false; SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc(); - bool HasParameterPack = - NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); - // C++ [temp.arg]p1: // [...] The type and form of each template-argument specified in // a template-id shall match the type and form specified for the @@ -3024,38 +3061,50 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // template-parameter-list. bool isTemplateTemplateParameter = isa<TemplateTemplateParmDecl>(Template); SmallVector<TemplateArgument, 2> ArgumentPack; - TemplateParameterList::iterator Param = Params->begin(), - ParamEnd = Params->end(); - unsigned ArgIdx = 0; + unsigned ArgIdx = 0, NumArgs = TemplateArgs.size(); LocalInstantiationScope InstScope(*this, true); - bool SawPackExpansion = false; - while (Param != ParamEnd) { - if (ArgIdx < NumArgs) { - // If we have an expanded parameter pack, make sure we don't have too - // many arguments. - // FIXME: This really should fall out from the normal arity checking. - if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - if (NTTP->isExpandedParameterPack() && - ArgumentPack.size() >= NTTP->getNumExpansionTypes()) { - Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << true - << (isa<ClassTemplateDecl>(Template)? 0 : - isa<FunctionTemplateDecl>(Template)? 1 : - isa<TemplateTemplateParmDecl>(Template)? 2 : 3) - << Template; - Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); - return true; - } + for (TemplateParameterList::iterator Param = Params->begin(), + ParamEnd = Params->end(); + 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 (*Expansions == ArgumentPack.size()) { + // We're done with this parameter pack. Pack up its arguments and add + // them to the list. + Converted.push_back( + TemplateArgument::CreatePackCopy(Context, + ArgumentPack.data(), + ArgumentPack.size())); + ArgumentPack.clear(); + + // This argument is assigned to the next parameter. + ++Param; + continue; + } else if (ArgIdx == NumArgs && !PartialTemplateArgs) { + // Not enough arguments for this parameter pack. + Diag(TemplateLoc, diag::err_template_arg_list_different_arity) + << false + << (isa<ClassTemplateDecl>(Template)? 0 : + isa<FunctionTemplateDecl>(Template)? 1 : + isa<TemplateTemplateParmDecl>(Template)? 2 : 3) + << Template; + Diag(Template->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; } + } + if (ArgIdx < NumArgs) { // Check the template argument we were given. if (CheckTemplateArgument(*Param, TemplateArgs[ArgIdx], Template, TemplateLoc, RAngleLoc, ArgumentPack.size(), Converted)) return true; + // We're now done with this argument. + ++ArgIdx; + if ((*Param)->isTemplateParameterPack()) { // The template parameter was a template parameter pack, so take the // deduced argument and place it on the argument pack. Note that we @@ -3067,16 +3116,47 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // Move to the next template parameter. ++Param; } - - // If this template argument is a pack expansion, record that fact - // and break out; we can't actually check any more. - if (TemplateArgs[ArgIdx].getArgument().isPackExpansion()) { - SawPackExpansion = true; - ++ArgIdx; - break; + + // If we just saw a pack expansion, then directly convert the remaining + // arguments, because we don't know what parameters they'll match up + // with. + if (TemplateArgs[ArgIdx-1].getArgument().isPackExpansion()) { + bool InFinalParameterPack = Param != ParamEnd && + Param + 1 == ParamEnd && + (*Param)->isTemplateParameterPack() && + !getExpandedPackSize(*Param); + + if (!InFinalParameterPack && !ArgumentPack.empty()) { + // If we were part way through filling in an expanded parameter pack, + // fall back to just producing individual arguments. + Converted.insert(Converted.end(), + ArgumentPack.begin(), ArgumentPack.end()); + ArgumentPack.clear(); + } + + while (ArgIdx < NumArgs) { + if (InFinalParameterPack) + ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument()); + else + Converted.push_back(TemplateArgs[ArgIdx].getArgument()); + ++ArgIdx; + } + + // Push the argument pack onto the list of converted arguments. + if (InFinalParameterPack) { + Converted.push_back( + TemplateArgument::CreatePackCopy(Context, + ArgumentPack.data(), + ArgumentPack.size())); + ArgumentPack.clear(); + } else if (ExpansionIntoFixedList) { + // We have expanded a pack into a fixed list. + *ExpansionIntoFixedList = true; + } + + return false; } - - ++ArgIdx; + continue; } @@ -3087,14 +3167,30 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgumentPack.data(), ArgumentPack.size())); - return Invalid; + return false; } // If we have a template parameter pack with no more corresponding // arguments, just break out now and we'll fill in the argument pack below. - if ((*Param)->isTemplateParameterPack()) - break; - + if ((*Param)->isTemplateParameterPack()) { + assert(!getExpandedPackSize(*Param) && + "Should have dealt with this already"); + + // A non-expanded parameter pack before the end of the parameter list + // only occurs for an ill-formed template parameter list, unless we've + // got a partial argument list for a function template, so just bail out. + if (Param + 1 != ParamEnd) + return true; + + Converted.push_back(TemplateArgument::CreatePackCopy(Context, + ArgumentPack.data(), + ArgumentPack.size())); + ArgumentPack.clear(); + + ++Param; + continue; + } + // Check whether we have a default argument. TemplateArgumentLoc Arg; @@ -3181,86 +3277,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ++ArgIdx; } - // If we saw a pack expansion, then directly convert the remaining arguments, - // because we don't know what parameters they'll match up with. - if (SawPackExpansion) { - bool AddToArgumentPack - = Param != ParamEnd && (*Param)->isTemplateParameterPack(); - while (ArgIdx < NumArgs) { - if (AddToArgumentPack) - ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument()); - else - Converted.push_back(TemplateArgs[ArgIdx].getArgument()); - ++ArgIdx; - } - - // Push the argument pack onto the list of converted arguments. - if (AddToArgumentPack) { - if (ArgumentPack.empty()) - Converted.push_back(TemplateArgument(0, 0)); - else { - Converted.push_back( - TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); - ArgumentPack.clear(); - } - } else if (ExpansionIntoFixedList) { - // We have expanded a pack into a fixed list. - *ExpansionIntoFixedList = true; - } - - return Invalid; - } - // If we have any leftover arguments, then there were too many arguments. // Complain and fail. if (ArgIdx < NumArgs) return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs); - - // If we have an expanded parameter pack, make sure we don't have too - // many arguments. - // FIXME: This really should fall out from the normal arity checking. - if (Param != ParamEnd) { - if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { - if (NTTP->isExpandedParameterPack() && - ArgumentPack.size() < NTTP->getNumExpansionTypes()) { - Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << false - << (isa<ClassTemplateDecl>(Template)? 0 : - isa<FunctionTemplateDecl>(Template)? 1 : - isa<TemplateTemplateParmDecl>(Template)? 2 : 3) - << Template; - Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); - return true; - } - } - } - - // Form argument packs for each of the parameter packs remaining. - while (Param != ParamEnd) { - // If we're checking a partial list of template arguments, don't fill - // in arguments for non-template parameter packs. - if ((*Param)->isTemplateParameterPack()) { - if (!HasParameterPack) - return true; - if (ArgumentPack.empty()) - Converted.push_back(TemplateArgument(0, 0)); - else { - Converted.push_back(TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); - ArgumentPack.clear(); - } - } else if (!PartialTemplateArgs) - return diagnoseArityMismatch(*this, Template, TemplateLoc, TemplateArgs); - - ++Param; - } - return Invalid; + return false; } namespace { @@ -3650,7 +3672,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, switch (isNullPointerValueTemplateArgument(S, Param, ParamType, Arg)) { case NPV_NullPointer: S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); - Converted = TemplateArgument((Decl *)0); + Converted = TemplateArgument(ParamType, /*isNullPtr*/true); return false; case NPV_Error: @@ -3738,7 +3760,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, return true; } - NamedDecl *Entity = DRE->getDecl(); + ValueDecl *Entity = DRE->getDecl(); // Cannot refer to non-static data members if (FieldDecl *Field = dyn_cast<FieldDecl>(Entity)) { @@ -3926,7 +3948,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, } // Create the template argument. - Converted = TemplateArgument(Entity->getCanonicalDecl()); + Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), + ParamType->isReferenceType()); S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity); return false; } @@ -3947,7 +3970,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, return true; case NPV_NullPointer: S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); - Converted = TemplateArgument((Decl *)0); + Converted = TemplateArgument(ParamType, /*isNullPtr*/true); return false; case NPV_NotNullPointer: break; @@ -4016,10 +4039,12 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, if (isa<NonTypeTemplateParmDecl>(VD) || (isa<VarDecl>(VD) && S.Context.getCanonicalType(VD->getType()).isConstQualified())) { - if (Arg->isTypeDependent() || Arg->isValueDependent()) + if (Arg->isTypeDependent() || Arg->isValueDependent()) { Converted = TemplateArgument(Arg); - else - Converted = TemplateArgument(VD->getCanonicalDecl()); + } else { + VD = cast<ValueDecl>(VD->getCanonicalDecl()); + Converted = TemplateArgument(VD, /*isReferenceParam*/false); + } return Invalid; } } @@ -4040,10 +4065,12 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, // Okay: this is the address of a non-static member, and therefore // a member pointer constant. - if (Arg->isTypeDependent() || Arg->isValueDependent()) + if (Arg->isTypeDependent() || Arg->isValueDependent()) { Converted = TemplateArgument(Arg); - else - Converted = TemplateArgument(DRE->getDecl()->getCanonicalDecl()); + } else { + ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl()); + Converted = TemplateArgument(D, /*isReferenceParam*/false); + } return Invalid; } @@ -4396,8 +4423,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, case NPV_NullPointer: Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); - Converted = TemplateArgument((Decl *)0); - return Owned(Arg);; + Converted = TemplateArgument(ParamType, /*isNullPtr*/true); + return Owned(Arg); } } @@ -4417,8 +4444,9 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, /// This routine implements the semantics of C++ [temp.arg.template]. /// It returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, - const TemplateArgumentLoc &Arg) { - TemplateName Name = Arg.getArgument().getAsTemplate(); + const TemplateArgumentLoc &Arg, + unsigned ArgumentPackIndex) { + TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern(); TemplateDecl *Template = Name.getAsTemplateDecl(); if (!Template) { // Any dependent template name is fine. @@ -4448,8 +4476,12 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, << Template; } + TemplateParameterList *Params = Param->getTemplateParameters(); + if (Param->isExpandedParameterPack()) + Params = Param->getExpansionTemplateParameters(ArgumentPackIndex); + return !TemplateParameterListsAreEqual(Template->getTemplateParameters(), - Param->getTemplateParameters(), + Params, true, TPL_TemplateTemplateArgumentMatch, Arg.getLocation()); @@ -4463,12 +4495,9 @@ ExprResult Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc) { - assert(Arg.getKind() == TemplateArgument::Declaration && - "Only declaration template arguments permitted here"); - // For a NULL non-type template argument, return nullptr casted to the // parameter's type. - if (!Arg.getAsDecl()) { + if (Arg.getKind() == TemplateArgument::NullPtr) { return ImpCastExprToType( new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc), ParamType, @@ -4476,7 +4505,9 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, ? CK_NullToMemberPointer : CK_NullToPointer); } - + assert(Arg.getKind() == TemplateArgument::Declaration && + "Only declaration template arguments permitted here"); + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); if (VD->getDeclContext()->isRecord() && @@ -4524,7 +4555,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, assert(!RefExpr.isInvalid() && Context.hasSameType(((Expr*) RefExpr.get())->getType(), ParamType.getUnqualifiedType())); - return move(RefExpr); + return RefExpr; } } @@ -4542,7 +4573,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, if (RefExpr.isInvalid()) return ExprError(); - return move(RefExpr); + return RefExpr; } // Take the address of everything else @@ -5071,10 +5102,10 @@ static bool CheckNonTypeClassTemplatePartialSpecializationArgs(Sema &S, continue; } - Expr *ArgExpr = Args[I].getAsExpr(); - if (!ArgExpr) { + if (Args[I].getKind() != TemplateArgument::Expression) continue; - } + + Expr *ArgExpr = Args[I].getAsExpr(); // We can have a pack expansion of any of the bullets below. if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr)) @@ -5173,7 +5204,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // NOTE: KWLoc is the location of the tag keyword. This will instead // store the location of the outermost template keyword in the declaration. SourceLocation TemplateKWLoc = TemplateParameterLists.size() > 0 - ? TemplateParameterLists.get()[0]->getTemplateLoc() : SourceLocation(); + ? TemplateParameterLists[0]->getTemplateLoc() : SourceLocation(); // Find the class template we're specializing TemplateName Name = TemplateD.getAsVal<TemplateName>(); @@ -5199,7 +5230,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, TemplateNameLoc, SS, - (TemplateParameterList**)TemplateParameterLists.get(), + TemplateParameterLists.data(), TemplateParameterLists.size(), TUK == TUK_Friend, isExplicitSpecialization, @@ -5354,7 +5385,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, TemplateParameterLists.size(), - (TemplateParameterList**) TemplateParameterLists.release()); + TemplateParameterLists.data()); } PrevDecl = 0; CanonType = Context.getTypeDeclType(Specialization); @@ -5382,7 +5413,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateParams, AS_none, /*ModulePrivateLoc=*/SourceLocation(), TemplateParameterLists.size() - 1, - (TemplateParameterList**) TemplateParameterLists.release()); + TemplateParameterLists.data()); } // Create a new class template partial specialization declaration node. @@ -5406,7 +5437,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (TemplateParameterLists.size() > 1 && SS.isSet()) { Partial->setTemplateParameterListsInfo(Context, TemplateParameterLists.size() - 1, - (TemplateParameterList**) TemplateParameterLists.release()); + TemplateParameterLists.data()); } if (!PrevPartial) @@ -5461,7 +5492,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, TemplateParameterLists.size(), - (TemplateParameterList**) TemplateParameterLists.release()); + TemplateParameterLists.data()); } if (!PrevDecl) @@ -5544,7 +5575,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Specialization->setTypeAsWritten(WrittenTy); Specialization->setTemplateKeywordLoc(TemplateKWLoc); } - TemplateArgsIn.release(); // C++ [temp.expl.spec]p9: // A template explicit specialization is in the scope of the @@ -5579,7 +5609,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Decl *Sema::ActOnTemplateDeclarator(Scope *S, MultiTemplateParamsArg TemplateParameterLists, Declarator &D) { - Decl *NewDecl = HandleDeclarator(S, D, move(TemplateParameterLists)); + Decl *NewDecl = HandleDeclarator(S, D, TemplateParameterLists); ActOnDocumentableDecl(NewDecl); return NewDecl; } @@ -5598,7 +5628,7 @@ Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = HandleDeclarator(ParentScope, D, - move(TemplateParameterLists)); + TemplateParameterLists); if (FunctionTemplateDecl *FunctionTemplate = dyn_cast_or_null<FunctionTemplateDecl>(DP)) return ActOnStartOfFunctionDef(FnBodyScope, @@ -5902,7 +5932,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Perform template argument deduction to determine whether we may be // specializing this template. // FIXME: It is somewhat wasteful to build - TemplateDeductionInfo Info(Context, FD->getLocation()); + TemplateDeductionInfo Info(FD->getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, @@ -6399,7 +6429,6 @@ Sema::ActOnExplicitInstantiation(Scope *S, TemplateArgs, Context.getTypeDeclType(Specialization)); Specialization->setTypeAsWritten(WrittenTy); - TemplateArgsIn.release(); // Set source locations for keywords. Specialization->setExternLoc(ExternLoc); @@ -6475,9 +6504,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, NameLoc, Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), - MultiTemplateParamsArg(*this, 0, 0), - Owned, IsDependent, SourceLocation(), false, - TypeResult()); + MultiTemplateParamsArg(), Owned, IsDependent, + SourceLocation(), false, TypeResult()); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); if (!TagD) @@ -6729,12 +6757,10 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateIdAnnotation *TemplateId = D.getName().TemplateId; TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); - ASTTemplateArgsPtr TemplateArgsPtr(*this, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); translateTemplateArguments(TemplateArgsPtr, TemplateArgs); HasExplicitTemplateArgs = true; - TemplateArgsPtr.release(); } // C++ [temp.explicit]p1: @@ -6762,7 +6788,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!FunTmpl) continue; - TemplateDeductionInfo Info(Context, D.getIdentifierLoc()); + TemplateDeductionInfo Info(D.getIdentifierLoc()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 9500ec3..bf4533d 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -158,9 +158,6 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) { /// \brief Determine whether two declaration pointers refer to the same /// declaration. static bool isSameDeclaration(Decl *X, Decl *Y) { - if (!X || !Y) - return !X && !Y; - if (NamedDecl *NX = dyn_cast<NamedDecl>(X)) X = NX->getUnderlyingDecl(); if (NamedDecl *NY = dyn_cast<NamedDecl>(Y)) @@ -262,7 +259,27 @@ checkDeducedTemplateArguments(ASTContext &Context, // If we deduced two declarations, make sure they they refer to the // same declaration. if (Y.getKind() == TemplateArgument::Declaration && - isSameDeclaration(X.getAsDecl(), Y.getAsDecl())) + isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) && + X.isDeclForReferenceParam() == Y.isDeclForReferenceParam()) + return X; + + // All other combinations are incompatible. + return DeducedTemplateArgument(); + + case TemplateArgument::NullPtr: + // If we deduced a null pointer and a dependent expression, keep the + // null pointer. + if (Y.getKind() == TemplateArgument::Expression) + return X; + + // If we deduced a null pointer and an integral constant, keep the + // integral constant. + if (Y.getKind() == TemplateArgument::Integral) + return Y; + + // If we deduced two null pointers, make sure they have the same type. + if (Y.getKind() == TemplateArgument::NullPtr && + Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType())) return X; // All other combinations are incompatible. @@ -356,13 +373,15 @@ DeduceNonTypeTemplateArgument(Sema &S, static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, - Decl *D, + ValueDecl *D, TemplateDeductionInfo &Info, SmallVectorImpl<DeducedTemplateArgument> &Deduced) { assert(NTTP->getDepth() == 0 && "Cannot deduce non-type template argument with depth > 0"); - DeducedTemplateArgument NewDeduced(D? D->getCanonicalDecl() : 0); + D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : 0; + TemplateArgument New(D, NTTP->getType()->isReferenceType()); + DeducedTemplateArgument NewDeduced(New); DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context, Deduced[NTTP->getIndex()], NewDeduced); @@ -570,7 +589,10 @@ static void PrepareArgumentPackDeduction(Sema &S, SavedPacks[I] = Deduced[PackIndices[I]]; Deduced[PackIndices[I]] = TemplateArgument(); - // If the template arugment pack was explicitly specified, add that to + if (!S.CurrentInstantiationScope) + continue; + + // If the template argument pack was explicitly specified, add that to // the set of deduced arguments. const TemplateArgument *ExplicitArgs; unsigned NumExplicitArgs; @@ -612,7 +634,7 @@ FinishArgumentPackDeduction(Sema &S, if (NewlyDeducedPacks[I].empty()) { // If we deduced an empty argument pack, create it now. - NewPack = DeducedTemplateArgument(TemplateArgument(0, 0)); + NewPack = DeducedTemplateArgument(TemplateArgument::getEmptyPack()); } else { TemplateArgument *ArgumentPack = new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()]; @@ -1371,9 +1393,11 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, // If this is a base class, try to perform template argument // deduction from it. if (NextT != RecordT) { + TemplateDeductionInfo BaseInfo(Info.getLocation()); Sema::TemplateDeductionResult BaseResult = DeduceTemplateArguments(S, TemplateParams, SpecParam, - QualType(NextT, 0), Info, Deduced); + QualType(NextT, 0), BaseInfo, + Deduced); // If template argument deduction for this base was successful, // note that we had some success. Otherwise, ignore any deductions @@ -1382,6 +1406,9 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S, Successful = true; DeducedOrig.clear(); DeducedOrig.append(Deduced.begin(), Deduced.end()); + Info.Param = BaseInfo.Param; + Info.FirstArg = BaseInfo.FirstArg; + Info.SecondArg = BaseInfo.SecondArg; } else Deduced = DeducedOrig; @@ -1596,7 +1623,17 @@ DeduceTemplateArguments(Sema &S, case TemplateArgument::Declaration: if (Arg.getKind() == TemplateArgument::Declaration && - isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl())) + isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()) && + Param.isDeclForReferenceParam() == Arg.isDeclForReferenceParam()) + return Sema::TDK_Success; + + Info.FirstArg = Param; + Info.SecondArg = Arg; + return Sema::TDK_NonDeducedMismatch; + + case TemplateArgument::NullPtr: + if (Arg.getKind() == TemplateArgument::NullPtr && + S.Context.hasSameType(Param.getNullPtrType(), Arg.getNullPtrType())) return Sema::TDK_Success; Info.FirstArg = Param; @@ -1867,7 +1904,11 @@ static bool isSameTemplateArg(ASTContext &Context, Context.getCanonicalType(Y.getAsType()); case TemplateArgument::Declaration: - return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()); + return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) && + X.isDeclForReferenceParam() == Y.isDeclForReferenceParam(); + + case TemplateArgument::NullPtr: + return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType()); case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: @@ -1937,6 +1978,14 @@ getTrivialTemplateArgumentLoc(Sema &S, return TemplateArgumentLoc(TemplateArgument(E), E); } + case TemplateArgument::NullPtr: { + Expr *E + = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc) + .takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(NTTPType, /*isNullPtr*/true), + E); + } + case TemplateArgument::Integral: { Expr *E = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>(); @@ -2162,6 +2211,9 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, const TemplateArgumentList &TemplateArgs, TemplateDeductionInfo &Info) { + if (Partial->isInvalidDecl()) + return TDK_Invalid; + // C++ [temp.class.spec.match]p2: // A partial specialization matches a given actual template // argument list if the template arguments of the partial @@ -2601,12 +2653,13 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, // explicitly-specified set (C++0x [temp.arg.explicit]p9). const TemplateArgument *ExplicitArgs; unsigned NumExplicitArgs; - if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs, + if (CurrentInstantiationScope && + CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs, &NumExplicitArgs) == Param) Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs)); else - Builder.push_back(TemplateArgument(0, 0)); + Builder.push_back(TemplateArgument::getEmptyPack()); continue; } @@ -2784,7 +2837,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, // Otherwise, see if we can resolve a function type FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc()); + TemplateDeductionInfo Info(Ovl->getNameLoc()); if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs, Specialization, Info)) continue; @@ -2815,7 +2868,7 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, // So we do not reject deductions which were made elsewhere. SmallVector<DeducedTemplateArgument, 8> Deduced(TemplateParams->size()); - TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc()); + TemplateDeductionInfo Info(Ovl->getNameLoc()); Sema::TemplateDeductionResult Result = DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType, ArgType, Info, Deduced, TDF); @@ -2992,8 +3045,6 @@ DeduceTemplateArgumentByListElement(Sema &S, /// /// \param Args the function call arguments /// -/// \param NumArgs the number of arguments in Args -/// /// \param Name the name of the function being called. This is only significant /// when the function template is a conversion function template, in which /// case this routine will also perform template argument deduction based on @@ -3013,6 +3064,9 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, llvm::ArrayRef<Expr *> Args, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { + if (FunctionTemplate->isInvalidDecl()) + return TDK_Invalid; + FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); // C++ [temp.deduct.call]p1: @@ -3269,6 +3323,9 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType ArgFunctionType, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { + if (FunctionTemplate->isInvalidDecl()) + return TDK_Invalid; + FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); @@ -3328,6 +3385,9 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType ToType, CXXConversionDecl *&Specialization, TemplateDeductionInfo &Info) { + if (FunctionTemplate->isInvalidDecl()) + return TDK_Invalid; + CXXConversionDecl *Conv = cast<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()); QualType FromType = Conv->getConversionType(); @@ -3572,7 +3632,7 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, QualType InitType = Init->getType(); unsigned TDF = 0; - TemplateDeductionInfo Info(Context, Loc); + TemplateDeductionInfo Info(Loc); InitListExpr *InitList = dyn_cast<InitListExpr>(Init); if (InitList) { @@ -3594,10 +3654,11 @@ Sema::DeduceAutoType(TypeSourceInfo *Type, Expr *&Init, return DAR_Failed; } - QualType DeducedType = Deduced[0].getAsType(); - if (DeducedType.isNull()) + if (Deduced[0].getKind() != TemplateArgument::Type) return DAR_Failed; + QualType DeducedType = Deduced[0].getAsType(); + if (InitList) { DeducedType = BuildStdInitializerList(DeducedType, Loc); if (DeducedType.isNull()) @@ -3637,26 +3698,23 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T, llvm::SmallBitVector &Deduced); /// \brief If this is a non-static member function, -static void MaybeAddImplicitObjectParameterType(ASTContext &Context, +static void AddImplicitObjectParameterType(ASTContext &Context, CXXMethodDecl *Method, SmallVectorImpl<QualType> &ArgTypes) { - if (Method->isStatic()) - return; - - // C++ [over.match.funcs]p4: - // - // For non-static member functions, the type of the implicit - // object parameter is - // - "lvalue reference to cv X" for functions declared without a - // ref-qualifier or with the & ref-qualifier - // - "rvalue reference to cv X" for functions declared with the - // && ref-qualifier + // C++11 [temp.func.order]p3: + // [...] The new parameter is of type "reference to cv A," where cv are + // the cv-qualifiers of the function template (if any) and A is + // the class of which the function template is a member. // - // FIXME: We don't have ref-qualifiers yet, so we don't do that part. + // The standard doesn't say explicitly, but we pick the appropriate kind of + // reference type based on [over.match.funcs]p4. QualType ArgTy = Context.getTypeDeclType(Method->getParent()); ArgTy = Context.getQualifiedType(ArgTy, Qualifiers::fromCVRMask(Method->getTypeQualifiers())); - ArgTy = Context.getLValueReferenceType(ArgTy); + if (Method->getRefQualifier() == RQ_RValue) + ArgTy = Context.getRValueReferenceType(ArgTy); + else + ArgTy = Context.getLValueReferenceType(ArgTy); ArgTypes.push_back(ArgTy); } @@ -3682,7 +3740,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // C++0x [temp.deduct.partial]p3: // The types used to determine the ordering depend on the context in which // the partial ordering is done: - TemplateDeductionInfo Info(S.Context, Loc); + TemplateDeductionInfo Info(Loc); CXXMethodDecl *Method1 = 0; CXXMethodDecl *Method2 = 0; bool IsNonStatic2 = false; @@ -3697,7 +3755,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, IsNonStatic1 = Method1 && !Method1->isStatic(); IsNonStatic2 = Method2 && !Method2->isStatic(); - // C++0x [temp.func.order]p3: + // C++11 [temp.func.order]p3: // [...] If only one of the function templates is a non-static // member, that function template is considered to have a new // first parameter inserted in its function parameter list. The @@ -3705,22 +3763,25 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // the cv-qualifiers of the function template (if any) and A is // the class of which the function template is a member. // + // Note that we interpret this to mean "if one of the function + // templates is a non-static member and the other is a non-member"; + // otherwise, the ordering rules for static functions against non-static + // functions don't make any sense. + // // C++98/03 doesn't have this provision, so instead we drop the - // first argument of the free function or static member, which - // seems to match existing practice. + // first argument of the free function, which seems to match + // existing practice. SmallVector<QualType, 4> Args1; - unsigned Skip1 = !S.getLangOpts().CPlusPlus0x && - IsNonStatic2 && !IsNonStatic1; - if (S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !IsNonStatic2) - MaybeAddImplicitObjectParameterType(S.Context, Method1, Args1); + unsigned Skip1 = !S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1; + if (S.getLangOpts().CPlusPlus0x && 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 && !IsNonStatic2; - if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !IsNonStatic1) - MaybeAddImplicitObjectParameterType(S.Context, Method2, Args2); + Skip2 = !S.getLangOpts().CPlusPlus0x && IsNonStatic1 && !Method2; + if (S.getLangOpts().CPlusPlus0x && IsNonStatic2 && !Method1) + AddImplicitObjectParameterType(S.Context, Method2, Args2); Args2.insert(Args2.end(), Proto2->arg_type_begin() + Skip2, Proto2->arg_type_end()); @@ -4118,7 +4179,7 @@ Sema::getMoreSpecializedPartialSpecialization( // template partial specialization's template arguments, for // example. SmallVector<DeducedTemplateArgument, 4> Deduced; - TemplateDeductionInfo Info(Context, Loc); + TemplateDeductionInfo Info(Loc); QualType PT1 = PS1->getInjectedSpecializationType(); QualType PT2 = PS2->getInjectedSpecializationType(); @@ -4496,6 +4557,11 @@ MarkUsedTemplateParameters(ASTContext &Ctx, case TemplateArgument::Declaration: break; + case TemplateArgument::NullPtr: + MarkUsedTemplateParameters(Ctx, TemplateArg.getNullPtrType(), OnlyDeduced, + Depth, Used); + break; + case TemplateArgument::Type: MarkUsedTemplateParameters(Ctx, TemplateArg.getAsType(), OnlyDeduced, Depth, Used); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 20e755f..665dd07 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -769,7 +769,7 @@ namespace { /// instantiating it. Decl *TransformDefinition(SourceLocation Loc, Decl *D); - /// \bried Transform the first qualifier within a scope by instantiating the + /// \brief Transform the first qualifier within a scope by instantiating the /// declaration. NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc); @@ -802,11 +802,24 @@ namespace { ExprResult TransformPredefinedExpr(PredefinedExpr *E); ExprResult TransformDeclRefExpr(DeclRefExpr *E); ExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E); + ExprResult TransformTemplateParmRefExpr(DeclRefExpr *E, NonTypeTemplateParmDecl *D); ExprResult TransformSubstNonTypeTemplateParmPackExpr( SubstNonTypeTemplateParmPackExpr *E); - + + /// \brief Rebuild a DeclRefExpr for a ParmVarDecl reference. + ExprResult RebuildParmVarDeclRefExpr(ParmVarDecl *PD, SourceLocation Loc); + + /// \brief Transform a reference to a function parameter pack. + ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, + ParmVarDecl *PD); + + /// \brief Transform a FunctionParmPackExpr which was built when we couldn't + /// expand a function parameter pack reference which refers to an expanded + /// pack. + ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E); + QualType TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc TL); QualType TransformFunctionProtoType(TypeLocBuilder &TLB, @@ -835,7 +848,7 @@ namespace { ExprResult Result = TreeTransform<TemplateInstantiator>::TransformCallExpr(CE); getSema().CallsUndergoingInstantiation.pop_back(); - return move(Result); + return Result; } ExprResult TransformLambdaExpr(LambdaExpr *E) { @@ -1161,10 +1174,11 @@ ExprResult TemplateInstantiator::transformNonTypeTemplateParmRef( result = SemaRef.Owned(argExpr); type = argExpr->getType(); - } else if (arg.getKind() == TemplateArgument::Declaration) { + } else if (arg.getKind() == TemplateArgument::Declaration || + arg.getKind() == TemplateArgument::NullPtr) { ValueDecl *VD; - if (Decl *D = arg.getAsDecl()) { - VD = cast<ValueDecl>(D); + if (arg.getKind() == TemplateArgument::Declaration) { + VD = cast<ValueDecl>(arg.getAsDecl()); // Find the instantiation of the template argument. This is // required for nested templates. @@ -1230,8 +1244,81 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( } ExprResult +TemplateInstantiator::RebuildParmVarDeclRefExpr(ParmVarDecl *PD, + SourceLocation Loc) { + DeclarationNameInfo NameInfo(PD->getDeclName(), Loc); + return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD); +} + +ExprResult +TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) { + if (getSema().ArgumentPackSubstitutionIndex != -1) { + // We can expand this parameter pack now. + ParmVarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex); + ValueDecl *VD = cast_or_null<ValueDecl>(TransformDecl(E->getExprLoc(), D)); + if (!VD) + return ExprError(); + return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(VD), E->getExprLoc()); + } + + QualType T = TransformType(E->getType()); + if (T.isNull()) + return ExprError(); + + // Transform each of the parameter expansions into the corresponding + // parameters in the instantiation of the function decl. + llvm::SmallVector<Decl*, 8> Parms; + Parms.reserve(E->getNumExpansions()); + for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end(); + I != End; ++I) { + ParmVarDecl *D = + cast_or_null<ParmVarDecl>(TransformDecl(E->getExprLoc(), *I)); + if (!D) + return ExprError(); + Parms.push_back(D); + } + + return FunctionParmPackExpr::Create(getSema().Context, T, + E->getParameterPack(), + E->getParameterPackLocation(), Parms); +} + +ExprResult +TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E, + ParmVarDecl *PD) { + typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found + = getSema().CurrentInstantiationScope->findInstantiationOf(PD); + assert(Found && "no instantiation for parameter pack"); + + Decl *TransformedDecl; + if (DeclArgumentPack *Pack = Found->dyn_cast<DeclArgumentPack *>()) { + // If this is a reference to a function parameter pack which we can substitute + // but can't yet expand, build a FunctionParmPackExpr for it. + if (getSema().ArgumentPackSubstitutionIndex == -1) { + QualType T = TransformType(E->getType()); + if (T.isNull()) + return ExprError(); + return FunctionParmPackExpr::Create(getSema().Context, T, PD, + E->getExprLoc(), *Pack); + } + + TransformedDecl = (*Pack)[getSema().ArgumentPackSubstitutionIndex]; + } else { + TransformedDecl = Found->get<Decl*>(); + } + + // We have either an unexpanded pack or a specific expansion. + return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(TransformedDecl), + E->getExprLoc()); +} + +ExprResult TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { NamedDecl *D = E->getDecl(); + + // Handle references to non-type template parameters and non-type template + // parameter packs. if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { if (NTTP->getDepth() < TemplateArgs.getNumLevels()) return TransformTemplateParmRefExpr(E, NTTP); @@ -1240,6 +1327,11 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { // FindInstantiatedDecl will find it in the local instantiation scope. } + // Handle references to function parameter packs. + if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D)) + if (PD->isParameterPack()) + return TransformFunctionParmPackRefExpr(E, PD); + return TreeTransform<TemplateInstantiator>::TransformDeclRefExpr(E); } @@ -2159,7 +2251,7 @@ Sema::InstantiateClassTemplateSpecialization( Template->getPartialSpecializations(PartialSpecs); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; - TemplateDeductionInfo Info(Context, PointOfInstantiation); + TemplateDeductionInfo Info(PointOfInstantiation); if (TemplateDeductionResult Result = DeduceTemplateArguments(Partial, ClassTemplateSpec->getTemplateArgs(), @@ -2543,8 +2635,25 @@ bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, return Instantiator.TransformTemplateArguments(Args, NumArgs, Result); } + +static const Decl* getCanonicalParmVarDecl(const Decl *D) { + // When storing ParmVarDecls in the local instantiation scope, we always + // want to use the ParmVarDecl from the canonical function declaration, + // since the map is then valid for any redeclaration or definition of that + // function. + if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(D)) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) { + unsigned i = PV->getFunctionScopeIndex(); + return FD->getCanonicalDecl()->getParamDecl(i); + } + } + return D; +} + + llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> * LocalInstantiationScope::findInstantiationOf(const Decl *D) { + D = getCanonicalParmVarDecl(D); for (LocalInstantiationScope *Current = this; Current; Current = Current->Outer) { @@ -2576,6 +2685,7 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) { } void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) { + D = getCanonicalParmVarDecl(D); llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D]; if (Stored.isNull()) Stored = Inst; @@ -2588,11 +2698,13 @@ void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) { void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D, Decl *Inst) { + D = getCanonicalParmVarDecl(D); DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>(); Pack->push_back(Inst); } void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) { + D = getCanonicalParmVarDecl(D); llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D]; assert(Stored.isNull() && "Already instantiated this local"); DeclArgumentPack *Pack = new DeclArgumentPack; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index bdbe71d..19c46ab 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -158,6 +158,22 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D, SemaRef.MarkDeclarationsReferencedInType(D->getLocation(), DI->getType()); } + // HACK: g++ has a bug where it gets the value kind of ?: wrong. + // libstdc++ relies upon this bug in its implementation of common_type. + // If we happen to be processing that implementation, fake up the g++ ?: + // semantics. See LWG issue 2141 for more information on the bug. + const DecltypeType *DT = DI->getType()->getAs<DecltypeType>(); + CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()); + if (DT && RD && isa<ConditionalOperator>(DT->getUnderlyingExpr()) && + DT->isReferenceType() && + RD->getEnclosingNamespaceContext() == SemaRef.getStdNamespace() && + RD->getIdentifier() && RD->getIdentifier()->isStr("common_type") && + D->getIdentifier() && D->getIdentifier()->isStr("type") && + SemaRef.getSourceManager().isInSystemHeader(D->getLocStart())) + // Fold it to the (non-reference) type which g++ would have produced. + DI = SemaRef.Context.getTrivialTypeSourceInfo( + DI->getType().getNonReferenceType()); + // Create the new typedef TypedefNameDecl *Typedef; if (IsTypeAlias) @@ -510,7 +526,7 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { if (!InstTy) return 0; - FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocation(), + FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(), D->getFriendLoc(), InstTy); if (!FD) return 0; @@ -1008,6 +1024,30 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { return Record; } +/// \brief Adjust the given function type for an instantiation of the +/// given declaration, to cope with modifications to the function's type that +/// aren't reflected in the type-source information. +/// +/// \param D The declaration we're instantiating. +/// \param TInfo The already-instantiated type. +static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, + FunctionDecl *D, + TypeSourceInfo *TInfo) { + const FunctionProtoType *OrigFunc + = D->getType()->castAs<FunctionProtoType>(); + const FunctionProtoType *NewFunc + = TInfo->getType()->castAs<FunctionProtoType>(); + if (OrigFunc->getExtInfo() == NewFunc->getExtInfo()) + return TInfo->getType(); + + FunctionProtoType::ExtProtoInfo NewEPI = NewFunc->getExtProtoInfo(); + NewEPI.ExtInfo = OrigFunc->getExtInfo(); + return Context.getFunctionType(NewFunc->getResultType(), + NewFunc->arg_type_begin(), + NewFunc->getNumArgs(), + NewEPI); +} + /// Normal class members are of more specific types and therefore /// don't make it here. This function serves two purposes: /// 1) instantiating function templates @@ -1048,7 +1088,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return 0; - QualType T = TInfo->getType(); + QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { @@ -1075,7 +1115,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, FunctionDecl *Function = FunctionDecl::Create(SemaRef.Context, DC, D->getInnerLocStart(), - D->getLocation(), D->getDeclName(), T, TInfo, + D->getNameInfo(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype(), D->isConstexpr()); @@ -1366,7 +1406,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, TypeSourceInfo *TInfo = SubstFunctionType(D, Params); if (!TInfo) return 0; - QualType T = TInfo->getType(); + QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); // \brief If the type of this function, after ignoring parentheses, // is not *directly* a function type, then we're instantiating a function @@ -1657,7 +1697,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( IsExpandedParameterPack = true; DI = D->getTypeSourceInfo(); T = DI->getType(); - } else if (isa<PackExpansionTypeLoc>(TL)) { + } else if (D->isPackExpansion()) { // 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. @@ -1771,27 +1811,121 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( return Param; } +static void collectUnexpandedParameterPacks( + Sema &S, + TemplateParameterList *Params, + SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { + for (TemplateParameterList::const_iterator I = Params->begin(), + E = Params->end(); I != E; ++I) { + if ((*I)->isTemplateParameterPack()) + continue; + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*I)) + S.collectUnexpandedParameterPacks(NTTP->getTypeSourceInfo()->getTypeLoc(), + Unexpanded); + if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(*I)) + collectUnexpandedParameterPacks(S, TTP->getTemplateParameters(), + Unexpanded); + } +} + Decl * TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( TemplateTemplateParmDecl *D) { // Instantiate the template parameter list of the template template parameter. TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams; - { + SmallVector<TemplateParameterList*, 8> ExpandedParams; + + bool IsExpandedParameterPack = false; + + if (D->isExpandedParameterPack()) { + // The template template parameter pack is an already-expanded pack + // expansion of template parameters. Substitute into each of the expanded + // parameters. + ExpandedParams.reserve(D->getNumExpansionTemplateParameters()); + for (unsigned I = 0, N = D->getNumExpansionTemplateParameters(); + I != N; ++I) { + LocalInstantiationScope Scope(SemaRef); + TemplateParameterList *Expansion = + SubstTemplateParams(D->getExpansionTemplateParameters(I)); + if (!Expansion) + return 0; + ExpandedParams.push_back(Expansion); + } + + IsExpandedParameterPack = true; + InstParams = TempParams; + } else if (D->isPackExpansion()) { + // The template template parameter pack expands to a pack of template + // template parameters. Determine whether we need to expand this parameter + // pack into separate parameters. + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + collectUnexpandedParameterPacks(SemaRef, D->getTemplateParameters(), + Unexpanded); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions; + if (SemaRef.CheckParameterPacksForExpansion(D->getLocation(), + TempParams->getSourceRange(), + Unexpanded, + TemplateArgs, + Expand, RetainExpansion, + NumExpansions)) + return 0; + + if (Expand) { + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); + LocalInstantiationScope Scope(SemaRef); + TemplateParameterList *Expansion = SubstTemplateParams(TempParams); + if (!Expansion) + return 0; + ExpandedParams.push_back(Expansion); + } + + // Note that we have an expanded parameter pack. The "type" of this + // expanded parameter pack is the original expansion type, but callers + // will end up using the expanded parameter pack types for type-checking. + IsExpandedParameterPack = true; + InstParams = TempParams; + } else { + // We cannot fully expand the pack expansion now, so just substitute + // into the pattern. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); + + LocalInstantiationScope Scope(SemaRef); + InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return 0; + } + } else { // Perform the actual substitution of template parameters within a new, // local instantiation scope. LocalInstantiationScope Scope(SemaRef); InstParams = SubstTemplateParams(TempParams); if (!InstParams) - return NULL; + return 0; } // Build the template template parameter. - TemplateTemplateParmDecl *Param - = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), + TemplateTemplateParmDecl *Param; + if (IsExpandedParameterPack) + Param = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getPosition(), + D->getIdentifier(), InstParams, + ExpandedParams); + else + Param = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getLocation(), D->getDepth() - TemplateArgs.getNumLevels(), - D->getPosition(), D->isParameterPack(), - D->getIdentifier(), InstParams); + D->getPosition(), + D->isParameterPack(), + D->getIdentifier(), InstParams); Param->setDefaultArgument(D->getDefaultArgument(), false); Param->setAccess(AS_public); @@ -1813,7 +1947,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { D->getIdentLocation(), D->getNominatedNamespace(), D->getCommonAncestor()); - Owner->addDecl(Inst); + + // Add the using directive to its declaration context + // only if this is not a function or method. + if (!Owner->isFunctionOrMethod()) + Owner->addDecl(Inst); + return Inst; } @@ -2863,7 +3002,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, const MultiLevelTemplateArgumentList &TemplateArgs) { SmallVector<CXXCtorInitializer*, 4> NewInits; - bool AnyErrors = false; + bool AnyErrors = Tmpl->isInvalidDecl(); // Instantiate all the initializers. for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(), @@ -3031,7 +3170,7 @@ ExprResult Sema::SubstInitializer(Expr *Init, isa<CXXTemporaryObjectExpr>(Construct)) return SubstExpr(Init, TemplateArgs); - ASTOwningVector<Expr*> NewArgs(*this); + SmallVector<Expr*, 8> NewArgs; if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, TemplateArgs, NewArgs)) return ExprError(); @@ -3043,7 +3182,7 @@ ExprResult Sema::SubstInitializer(Expr *Init, // Build a ParenListExpr to represent anything else. // FIXME: Fake locations! SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart()); - return ActOnParenListExpr(Loc, Loc, move_arg(NewArgs)); + return ActOnParenListExpr(Loc, Loc, NewArgs); } // TODO: this could be templated if the various decl types used the @@ -3298,7 +3437,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (Decl *FD = Found->dyn_cast<Decl *>()) return cast<NamedDecl>(FD); - unsigned PackIdx = ArgumentPackSubstitutionIndex; + int PackIdx = ArgumentPackSubstitutionIndex; + assert(PackIdx != -1 && "found declaration pack but not pack expanding"); return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]); } diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index aece90b..6147d63 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -727,6 +727,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) { case TST_enum: case TST_union: case TST_struct: + case TST_interface: case TST_class: case TST_auto: case TST_unknown_anytype: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 54f8dba..4b23167 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -105,7 +105,8 @@ static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr, case AttributeList::AT_ThisCall: \ case AttributeList::AT_Pascal: \ case AttributeList::AT_Regparm: \ - case AttributeList::AT_Pcs \ + case AttributeList::AT_Pcs: \ + case AttributeList::AT_PnaclCall \ namespace { /// An object which stores processing state for the entire @@ -552,19 +553,28 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state, SourceLocation loc = declarator.getLocStart(); // ...and *prepend* it to the declarator. + SourceLocation NoLoc; declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction( - /*proto*/ true, - /*variadic*/ false, - /*ambiguous*/ false, SourceLocation(), - /*args*/ 0, 0, - /*type quals*/ 0, - /*ref-qualifier*/true, SourceLocation(), - /*const qualifier*/SourceLocation(), - /*volatile qualifier*/SourceLocation(), - /*mutable qualifier*/SourceLocation(), - /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, - /*parens*/ loc, loc, - declarator)); + /*HasProto=*/true, + /*IsAmbiguous=*/false, + /*LParenLoc=*/NoLoc, + /*ArgInfo=*/0, + /*NumArgs=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*MutableLoc=*/NoLoc, + EST_None, + /*ESpecLoc=*/NoLoc, + /*Exceptions=*/0, + /*ExceptionRanges=*/0, + /*NumExceptions=*/0, + /*NoexceptExpr=*/0, + loc, loc, declarator)); // For consistency, make sure the state still has us as processing // the decl spec. @@ -636,7 +646,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // "<proto1,proto2>" is an objc qualified ID with a missing id. if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, - (ObjCProtocolDecl**)PQ, + (ObjCProtocolDecl*const*)PQ, DS.getNumProtocolQualifiers()); Result = Context.getObjCObjectPointerType(Result); break; @@ -698,11 +708,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TSW_longlong: Result = Context.LongLongTy; - // long long is a C99 feature. - if (!S.getLangOpts().C99) - S.Diag(DS.getTypeSpecWidthLoc(), - S.getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_longlong : diag::ext_longlong); + // 'long long' is a C99 or C++11 feature. + if (!S.getLangOpts().C99) { + if (S.getLangOpts().CPlusPlus) + S.Diag(DS.getTypeSpecWidthLoc(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); + else + S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong); + } break; } } else { @@ -713,11 +727,15 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TSW_longlong: Result = Context.UnsignedLongLongTy; - // long long is a C99 feature. - if (!S.getLangOpts().C99) - S.Diag(DS.getTypeSpecWidthLoc(), - S.getLangOpts().CPlusPlus0x ? - diag::warn_cxx98_compat_longlong : diag::ext_longlong); + // 'long long' is a C99 or C++11 feature. + if (!S.getLangOpts().C99) { + if (S.getLangOpts().CPlusPlus) + S.Diag(DS.getTypeSpecWidthLoc(), + S.getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong); + else + S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong); + } break; } } @@ -753,7 +771,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { case DeclSpec::TST_class: case DeclSpec::TST_enum: case DeclSpec::TST_union: - case DeclSpec::TST_struct: { + case DeclSpec::TST_struct: + case DeclSpec::TST_interface: { TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl()); if (!D) { // This can happen in C++ with ambiguous lookups. @@ -794,18 +813,18 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { if (DS.getNumProtocolQualifiers()) Result = Context.getObjCObjectType(Result, - (ObjCProtocolDecl**) PQ, + (ObjCProtocolDecl*const*) PQ, DS.getNumProtocolQualifiers()); } else if (Result->isObjCIdType()) { // id<protocol-list> Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy, - (ObjCProtocolDecl**) PQ, + (ObjCProtocolDecl*const*) PQ, DS.getNumProtocolQualifiers()); Result = Context.getObjCObjectPointerType(Result); } else if (Result->isObjCClassType()) { // Class<protocol-list> Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy, - (ObjCProtocolDecl**) PQ, + (ObjCProtocolDecl*const*) PQ, DS.getNumProtocolQualifiers()); Result = Context.getObjCObjectPointerType(Result); } else { @@ -1853,30 +1872,31 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case TTK_Struct: Error = 1; /* Struct member */ break; case TTK_Union: Error = 2; /* Union member */ break; case TTK_Class: Error = 3; /* Class member */ break; + case TTK_Interface: Error = 4; /* Interface member */ break; } break; case Declarator::CXXCatchContext: case Declarator::ObjCCatchContext: - Error = 4; // Exception declaration + Error = 5; // Exception declaration break; case Declarator::TemplateParamContext: - Error = 5; // Template parameter + Error = 6; // Template parameter break; case Declarator::BlockLiteralContext: - Error = 6; // Block literal + Error = 7; // Block literal break; case Declarator::TemplateTypeArgContext: - Error = 7; // Template type argument + Error = 8; // Template type argument break; case Declarator::AliasDeclContext: case Declarator::AliasTemplateContext: - Error = 9; // Type alias + Error = 10; // Type alias break; case Declarator::TrailingReturnContext: - Error = 10; // Function return type + Error = 11; // Function return type break; case Declarator::TypeNameContext: - Error = 11; // Generic + Error = 12; // Generic break; case Declarator::FileContext: case Declarator::BlockContext: @@ -1887,11 +1907,11 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, } if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - Error = 8; + Error = 9; // In Objective-C it is an error to use 'auto' on a function declarator. if (D.isFunctionDeclarator()) - Error = 10; + Error = 11; // C++11 [dcl.spec.auto]p2: 'auto' is always fine if the declarator // contains a trailing return type. That is only legal at the outermost @@ -2149,16 +2169,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, ASTContext &Context = S.Context; const LangOptions &LangOpts = S.getLangOpts(); - bool ImplicitlyNoexcept = false; - if (D.getName().getKind() == UnqualifiedId::IK_OperatorFunctionId && - LangOpts.CPlusPlus0x) { - OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator; - /// In C++0x, deallocation functions (normal and array operator delete) - /// are implicitly noexcept. - if (OO == OO_Delete || OO == OO_Array_Delete) - ImplicitlyNoexcept = true; - } - // The name we're declaring, if any. DeclarationName Name; if (D.getIdentifier()) @@ -2558,12 +2568,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, Exceptions, EPI); - if (FTI.getExceptionSpecType() == EST_None && - ImplicitlyNoexcept && chunkIndex == 0) { - // Only the outermost chunk is marked noexcept, of course. - EPI.ExceptionSpecType = EST_BasicNoexcept; - } - T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI); } @@ -2657,6 +2661,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // 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 && @@ -2668,6 +2675,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, 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): @@ -2721,6 +2734,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, 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); + } } } @@ -2985,6 +3004,8 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { return AttributeList::AT_Pascal; case AttributedType::attr_pcs: return AttributeList::AT_Pcs; + case AttributedType::attr_pnaclcall: + return AttributeList::AT_PnaclCall; } llvm_unreachable("unexpected attribute kind!"); } @@ -3271,6 +3292,8 @@ namespace { TL.setLocalRangeEnd(Chunk.EndLoc); const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; + TL.setLParenLoc(FTI.getLParenLoc()); + TL.setRParenLoc(FTI.getRParenLoc()); for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) { ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param); TL.setArg(tpi++, Param); @@ -3588,7 +3611,7 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, // Forbid __weak if the runtime doesn't support it. if (lifetime == Qualifiers::OCL_Weak && - !S.getLangOpts().ObjCRuntimeHasWeak && !NonObjCPointer) { + !S.getLangOpts().ObjCARCWeak && !NonObjCPointer) { // Actually, delay this until we know what we're parsing. if (S.DelayedDiagnostics.shouldDelayDiagnostics()) { @@ -3611,11 +3634,12 @@ static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state, while (const PointerType *ptr = T->getAs<PointerType>()) T = ptr->getPointeeType(); if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) { - ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl(); - if (Class->isArcWeakrefUnavailable()) { - S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class); - S.Diag(ObjT->getInterfaceDecl()->getLocation(), - diag::note_class_declared); + if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) { + if (Class->isArcWeakrefUnavailable()) { + S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class); + S.Diag(ObjT->getInterfaceDecl()->getLocation(), + diag::note_class_declared); + } } } } @@ -3875,14 +3899,14 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, return true; } + // Delay if the type didn't work out to a function. + if (!unwrapped.isFunctionType()) return false; + // Otherwise, a calling convention. CallingConv CC; if (S.CheckCallingConvAttr(attr, CC)) return true; - // Delay if the type didn't work out to a function. - if (!unwrapped.isFunctionType()) return false; - const FunctionType *fn = unwrapped.get(); CallingConv CCOld = fn->getCallConv(); if (S.Context.getCanonicalCallConv(CC) == @@ -4429,6 +4453,20 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, return RequireCompleteType(Loc, T, Diagnoser); } +/// \brief Get diagnostic %select index for tag kind for +/// literal type diagnostic message. +/// WARNING: Indexes apply to particular diagnostics only! +/// +/// \returns diagnostic %select index. +static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) { + switch (Tag) { + case TTK_Struct: return 0; + case TTK_Interface: return 1; + case TTK_Class: return 2; + default: llvm_unreachable("Invalid tag kind for literal type diagnostic!"); + } +} + /// @brief Ensure that the type T is a literal type. /// /// This routine checks whether the type @p T is a literal type. If @p T is an @@ -4485,7 +4523,7 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, // of constexpr constructors. if (RD->getNumVBases()) { Diag(RD->getLocation(), diag::note_non_literal_virtual_base) - << RD->isStruct() << RD->getNumVBases(); + << getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) Diag(I->getLocStart(), @@ -4578,15 +4616,21 @@ static QualType getDecltypeForExpr(Sema &S, Expr *E) { // member access (5.2.5), decltype(e) is the type of the entity named // by e. If there is no such entity, or if e names a set of overloaded // functions, the program is ill-formed; + // + // We apply the same rules for Objective-C ivar and property references. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) return VD->getType(); - } - if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + } else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) return FD->getType(); + } else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) { + return IR->getDecl()->getType(); + } else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) { + if (PR->isExplicitProperty()) + return PR->getExplicitProperty()->getType(); } - + // C++11 [expr.lambda.prim]p18: // Every occurrence of decltype((x)) where x is a possibly // parenthesized id-expression that names an entity of automatic diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 619ad33..294d742 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -574,6 +574,10 @@ public: /// \brief Transform the captures and body of a lambda expression. ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator); + ExprResult TransformAddressOfOperand(Expr *E); + ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E, + bool IsAddressOfOperand); + #define STMT(Node, Parent) \ StmtResult Transform##Node(Node *S); #define EXPR(Node, Parent) \ @@ -1162,32 +1166,23 @@ public: /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildAsmStmt(SourceLocation AsmLoc, - bool IsSimple, - bool IsVolatile, - unsigned NumOutputs, - unsigned NumInputs, - IdentifierInfo **Names, - MultiExprArg Constraints, - MultiExprArg Exprs, - Expr *AsmString, - MultiExprArg Clobbers, - SourceLocation RParenLoc, - bool MSAsm) { - return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, - NumInputs, Names, move(Constraints), - Exprs, AsmString, Clobbers, - RParenLoc, MSAsm); + StmtResult RebuildGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, + bool IsVolatile, unsigned NumOutputs, + unsigned NumInputs, IdentifierInfo **Names, + MultiExprArg Constraints, MultiExprArg Exprs, + Expr *AsmString, MultiExprArg Clobbers, + SourceLocation RParenLoc) { + return getSema().ActOnGCCAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, + NumInputs, Names, Constraints, Exprs, + AsmString, Clobbers, RParenLoc); } /// \brief Build a new MS style inline asm statement. /// /// By default, performs semantic analysis to build the new statement. /// Subclasses may override this routine to provide different behavior. - StmtResult RebuildMSAsmStmt(SourceLocation AsmLoc, - SourceLocation LBraceLoc, - ArrayRef<Token> AsmToks, - SourceLocation EndLoc) { + StmtResult RebuildMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, + ArrayRef<Token> AsmToks, SourceLocation EndLoc) { return getSema().ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, EndLoc); } @@ -1199,7 +1194,7 @@ public: Stmt *TryBody, MultiStmtArg CatchStmts, Stmt *Finally) { - return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, move(CatchStmts), + return getSema().ActOnObjCAtTryStmt(AtLoc, TryBody, CatchStmts, Finally); } @@ -1325,7 +1320,7 @@ public: StmtResult RebuildCXXTryStmt(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg Handlers) { - return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, move(Handlers)); + return getSema().ActOnCXXTryBlock(TryLoc, TryBlock, Handlers); } /// \brief Build a new C++0x range-based for statement. @@ -1339,7 +1334,8 @@ public: Stmt *LoopVar, SourceLocation RParenLoc) { return getSema().BuildCXXForRangeStmt(ForLoc, ColonLoc, Range, BeginEnd, - Cond, Inc, LoopVar, RParenLoc); + Cond, Inc, LoopVar, RParenLoc, + Sema::BFRK_Rebuild); } /// \brief Build a new C++0x range-based for statement. @@ -1478,7 +1474,7 @@ public: if (Result.isInvalid()) return ExprError(); - return move(Result); + return Result; } /// \brief Build a new array subscript expression. @@ -1503,7 +1499,7 @@ public: SourceLocation RParenLoc, Expr *ExecConfig = 0) { return getSema().ActOnCallExpr(/*Scope=*/0, Callee, LParenLoc, - move(Args), RParenLoc, ExecConfig); + Args, RParenLoc, ExecConfig); } /// \brief Build a new member access expression. @@ -1638,15 +1634,15 @@ public: SourceLocation RBraceLoc, QualType ResultTy) { ExprResult Result - = SemaRef.ActOnInitList(LBraceLoc, move(Inits), RBraceLoc); + = SemaRef.ActOnInitList(LBraceLoc, Inits, RBraceLoc); if (Result.isInvalid() || ResultTy->isDependentType()) - return move(Result); + return Result; // Patch in the result type we were given, which may have been computed // when the initial InitListExpr was built. InitListExpr *ILE = cast<InitListExpr>((Expr *)Result.get()); ILE->setType(ResultTy); - return move(Result); + return Result; } /// \brief Build a new designated initializer expression. @@ -1664,8 +1660,7 @@ public: if (Result.isInvalid()) return ExprError(); - ArrayExprs.release(); - return move(Result); + return Result; } /// \brief Build a new value-initialized expression. @@ -1696,7 +1691,7 @@ public: ExprResult RebuildParenListExpr(SourceLocation LParenLoc, MultiExprArg SubExprs, SourceLocation RParenLoc) { - return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, move(SubExprs)); + return getSema().ActOnParenListExpr(LParenLoc, RParenLoc, SubExprs); } /// \brief Build a new address-of-label expression. @@ -1974,8 +1969,7 @@ public: SourceLocation LParenLoc, SourceLocation RParenLoc) { return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, - MultiExprArg(getSema(), 0, 0), - RParenLoc); + MultiExprArg(), RParenLoc); } /// \brief Build a new C++ "new" expression. @@ -1995,7 +1989,7 @@ public: Expr *Initializer) { return getSema().BuildCXXNew(StartLoc, UseGlobal, PlacementLParen, - move(PlacementArgs), + PlacementArgs, PlacementRParen, TypeIdParens, AllocatedType, @@ -2083,7 +2077,8 @@ public: NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs) { + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); @@ -2091,7 +2086,8 @@ public: return getSema().BuildQualifiedTemplateIdExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); - return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo); + return getSema().BuildQualifiedDeclarationNameExpr(SS, NameInfo, + IsAddressOfOperand); } /// \brief Build a new template-id expression. @@ -2120,13 +2116,13 @@ public: bool RequiresZeroInit, CXXConstructExpr::ConstructionKind ConstructKind, SourceRange ParenRange) { - ASTOwningVector<Expr*> ConvertedArgs(SemaRef); - if (getSema().CompleteConstructorCall(Constructor, move(Args), Loc, + SmallVector<Expr*, 8> ConvertedArgs; + if (getSema().CompleteConstructorCall(Constructor, Args, Loc, ConvertedArgs)) return ExprError(); return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable, - move_arg(ConvertedArgs), + ConvertedArgs, HadMultipleCandidates, RequiresZeroInit, ConstructKind, ParenRange); @@ -2142,7 +2138,7 @@ public: SourceLocation RParenLoc) { return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, - move(Args), + Args, RParenLoc); } @@ -2156,7 +2152,7 @@ public: SourceLocation RParenLoc) { return getSema().BuildCXXTypeConstructExpr(TSInfo, LParenLoc, - move(Args), + Args, RParenLoc); } @@ -2288,7 +2284,7 @@ public: ReceiverTypeInfo->getType(), /*SuperLoc=*/SourceLocation(), Sel, Method, LBracLoc, SelectorLocs, - RBracLoc, move(Args)); + RBracLoc, Args); } /// \brief Build a new Objective-C instance message. @@ -2303,7 +2299,7 @@ public: Receiver->getType(), /*SuperLoc=*/SourceLocation(), Sel, Method, LBracLoc, SelectorLocs, - RBracLoc, move(Args)); + RBracLoc, Args); } /// \brief Build a new Objective-C ivar reference expression. @@ -2326,7 +2322,7 @@ public: return ExprError(); if (Result.get()) - return move(Result); + return Result; return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/IvarLoc, IsArrow, @@ -2355,7 +2351,7 @@ public: return ExprError(); if (Result.get()) - return move(Result); + return Result; return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/PropertyLoc, IsArrow, @@ -2398,7 +2394,7 @@ public: return ExprError(); if (Result.get()) - return move(Result); + return Result; return getSema().BuildMemberReferenceExpr(Base.get(), Base.get()->getType(), /*FIXME:*/IsaLoc, IsArrow, @@ -2424,21 +2420,17 @@ public: // Build a reference to the __builtin_shufflevector builtin FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); - ExprResult Callee - = SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Builtin, false, - Builtin->getType(), - VK_LValue, BuiltinLoc)); - Callee = SemaRef.UsualUnaryConversions(Callee.take()); - if (Callee.isInvalid()) - return ExprError(); + Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, false, + SemaRef.Context.BuiltinFnTy, + VK_RValue, BuiltinLoc); + QualType CalleePtrTy = SemaRef.Context.getPointerType(Builtin->getType()); + Callee = SemaRef.ImpCastExprToType(Callee, CalleePtrTy, + CK_BuiltinFnToFnPtr).take(); // Build the CallExpr - unsigned NumSubExprs = SubExprs.size(); - Expr **Subs = (Expr **)SubExprs.release(); ExprResult TheCall = SemaRef.Owned( - new (SemaRef.Context) CallExpr(SemaRef.Context, Callee.take(), - Subs, NumSubExprs, - Builtin->getCallResultType(), + new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, SubExprs, + Builtin->getCallResultType(), Expr::getValueKindForType(Builtin->getResultType()), RParenLoc)); @@ -2478,6 +2470,7 @@ public: case TemplateArgument::Declaration: case TemplateArgument::Pack: case TemplateArgument::TemplateExpansion: + case TemplateArgument::NullPtr: llvm_unreachable("Pack expansion pattern has no parameter packs"); case TemplateArgument::Type: @@ -2515,10 +2508,7 @@ public: // Just create the expression; there is not any interesting semantic // analysis here because we can't actually build an AtomicExpr until // we are sure it is semantically sound. - unsigned NumSubExprs = SubExprs.size(); - Expr **Subs = (Expr **)SubExprs.release(); - return new (SemaRef.Context) AtomicExpr(BuiltinLoc, Subs, - NumSubExprs, RetTy, Op, + return new (SemaRef.Context) AtomicExpr(BuiltinLoc, SubExprs, RetTy, Op, RParenLoc); } @@ -2963,6 +2953,7 @@ void TreeTransform<Derived>::InventTemplateArgumentLoc( case TemplateArgument::Declaration: case TemplateArgument::Integral: case TemplateArgument::Pack: + case TemplateArgument::NullPtr: Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); break; } @@ -2976,8 +2967,10 @@ bool TreeTransform<Derived>::TransformTemplateArgument( switch (Arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: - Output = Input; - return false; + case TemplateArgument::Pack: + case TemplateArgument::Declaration: + case TemplateArgument::NullPtr: + llvm_unreachable("Unexpected TemplateArgument"); case TemplateArgument::Type: { TypeSourceInfo *DI = Input.getTypeSourceInfo(); @@ -2991,28 +2984,6 @@ bool TreeTransform<Derived>::TransformTemplateArgument( return false; } - case TemplateArgument::Declaration: { - // FIXME: we should never have to transform one of these. - DeclarationName Name; - if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) - Name = ND->getDeclName(); - TemporaryBase Rebase(*this, Input.getLocation(), Name); - Decl *D = getDerived().TransformDecl(Input.getLocation(), Arg.getAsDecl()); - if (!D) return true; - - Expr *SourceExpr = Input.getSourceDeclExpression(); - if (SourceExpr) { - EnterExpressionEvaluationContext Unevaluated(getSema(), - Sema::ConstantEvaluated); - ExprResult E = getDerived().TransformExpr(SourceExpr); - E = SemaRef.ActOnConstantExpression(E); - SourceExpr = (E.isInvalid() ? 0 : E.take()); - } - - Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr); - return false; - } - case TemplateArgument::Template: { NestedNameSpecifierLoc QualifierLoc = Input.getTemplateQualifierLoc(); if (QualifierLoc) { @@ -3051,35 +3022,6 @@ bool TreeTransform<Derived>::TransformTemplateArgument( Output = TemplateArgumentLoc(TemplateArgument(E.take()), E.take()); return false; } - - case TemplateArgument::Pack: { - SmallVector<TemplateArgument, 4> TransformedArgs; - TransformedArgs.reserve(Arg.pack_size()); - for (TemplateArgument::pack_iterator A = Arg.pack_begin(), - AEnd = Arg.pack_end(); - A != AEnd; ++A) { - - // FIXME: preserve source information here when we start - // caring about parameter packs. - - TemplateArgumentLoc InputArg; - TemplateArgumentLoc OutputArg; - getDerived().InventTemplateArgumentLoc(*A, InputArg); - if (getDerived().TransformTemplateArgument(InputArg, OutputArg)) - return true; - - TransformedArgs.push_back(OutputArg.getArgument()); - } - - TemplateArgument *TransformedArgsPtr - = new (getSema().Context) TemplateArgument[TransformedArgs.size()]; - std::copy(TransformedArgs.begin(), TransformedArgs.end(), - TransformedArgsPtr); - Output = TemplateArgumentLoc(TemplateArgument(TransformedArgsPtr, - TransformedArgs.size()), - Input.getLocInfo()); - return false; - } } // Work around bogus GCC warning @@ -4260,6 +4202,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result); NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i) NewTL.setArg(i, ParamDecls[i]); @@ -4283,6 +4227,8 @@ QualType TreeTransform<Derived>::TransformFunctionNoProtoType( FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result); NewTL.setLocalRangeBegin(TL.getLocalRangeBegin()); + NewTL.setLParenLoc(TL.getLParenLoc()); + NewTL.setRParenLoc(TL.getRParenLoc()); NewTL.setLocalRangeEnd(TL.getLocalRangeEnd()); return Result; @@ -4339,7 +4285,8 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB, TypeOfExprTypeLoc TL) { // typeof expressions are not potentially evaluated contexts - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, + Sema::ReuseLambdaContextDecl); ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr()); if (E.isInvalid()) @@ -5099,7 +5046,7 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, bool SubStmtInvalid = false; bool SubStmtChanged = false; - ASTOwningVector<Stmt*> Statements(getSema()); + SmallVector<Stmt*, 8> Statements; for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end(); B != BEnd; ++B) { StmtResult Result = getDerived().TransformStmt(*B); @@ -5126,7 +5073,7 @@ TreeTransform<Derived>::TransformCompoundStmt(CompoundStmt *S, return SemaRef.Owned(S); return getDerived().RebuildCompoundStmt(S->getLBracLoc(), - move_arg(Statements), + Statements, S->getRBracLoc(), IsStmtExpr); } @@ -5533,14 +5480,14 @@ TreeTransform<Derived>::TransformDeclStmt(DeclStmt *S) { template<typename Derived> StmtResult -TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) { +TreeTransform<Derived>::TransformGCCAsmStmt(GCCAsmStmt *S) { - ASTOwningVector<Expr*> Constraints(getSema()); - ASTOwningVector<Expr*> Exprs(getSema()); + SmallVector<Expr*, 8> Constraints; + SmallVector<Expr*, 8> Exprs; SmallVector<IdentifierInfo *, 4> Names; ExprResult AsmString; - ASTOwningVector<Expr*> Clobbers(getSema()); + SmallVector<Expr*, 8> Clobbers; bool ExprsChanged = false; @@ -5585,23 +5532,15 @@ TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) { // Go through the clobbers. for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I) - Clobbers.push_back(S->getClobber(I)); + Clobbers.push_back(S->getClobberStringLiteral(I)); // No need to transform the asm string literal. AsmString = SemaRef.Owned(S->getAsmString()); - - return getDerived().RebuildAsmStmt(S->getAsmLoc(), - S->isSimple(), - S->isVolatile(), - S->getNumOutputs(), - S->getNumInputs(), - Names.data(), - move_arg(Constraints), - move_arg(Exprs), - AsmString.get(), - move_arg(Clobbers), - S->getRParenLoc(), - S->isMSAsm()); + return getDerived().RebuildGCCAsmStmt(S->getAsmLoc(), S->isSimple(), + S->isVolatile(), S->getNumOutputs(), + S->getNumInputs(), Names.data(), + Constraints, Exprs, AsmString.get(), + Clobbers, S->getRParenLoc()); } template<typename Derived> @@ -5624,7 +5563,7 @@ TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) { // Transform the @catch statements (if present). bool AnyCatchChanged = false; - ASTOwningVector<Stmt*> CatchStmts(SemaRef); + SmallVector<Stmt*, 8> CatchStmts; for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { StmtResult Catch = getDerived().TransformStmt(S->getCatchStmt(I)); if (Catch.isInvalid()) @@ -5651,7 +5590,7 @@ TreeTransform<Derived>::TransformObjCAtTryStmt(ObjCAtTryStmt *S) { // Build a new statement. return getDerived().RebuildObjCAtTryStmt(S->getAtTryLoc(), TryBody.get(), - move_arg(CatchStmts), Finally.get()); + CatchStmts, Finally.get()); } template<typename Derived> @@ -5855,7 +5794,7 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { // Transform the handlers. bool HandlerChanged = false; - ASTOwningVector<Stmt*> Handlers(SemaRef); + SmallVector<Stmt*, 8> Handlers; for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) { StmtResult Handler = getDerived().TransformCXXCatchStmt(S->getHandler(I)); @@ -5872,7 +5811,7 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { return SemaRef.Owned(S); return getDerived().RebuildCXXTryStmt(S->getTryLoc(), TryBlock.get(), - move_arg(Handlers)); + Handlers); } template<typename Derived> @@ -6205,10 +6144,22 @@ TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) { E->getRParen()); } +/// \brief The operand of a unary address-of operator has special rules: it's +/// allowed to refer to a non-static member of a class even if there's no 'this' +/// object available. +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformAddressOfOperand(Expr *E) { + if (DependentScopeDeclRefExpr *DRE = dyn_cast<DependentScopeDeclRefExpr>(E)) + return getDerived().TransformDependentScopeDeclRefExpr(DRE, true); + else + return getDerived().TransformExpr(E); +} + template<typename Derived> ExprResult TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) { - ExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); + ExprResult SubExpr = TransformAddressOfOperand(E->getSubExpr()); if (SubExpr.isInvalid()) return ExprError(); @@ -6338,7 +6289,8 @@ TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr( // C++0x [expr.sizeof]p1: // The operand is either an expression, which is an unevaluated operand // [...] - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, + Sema::ReuseLambdaContextDecl); ExprResult SubExpr = getDerived().TransformExpr(E->getArgumentExpr()); if (SubExpr.isInvalid()) @@ -6386,7 +6338,7 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { // Transform arguments. bool ArgChanged = false; - ASTOwningVector<Expr*> Args(SemaRef); + SmallVector<Expr*, 8> Args; if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, &ArgChanged)) return ExprError(); @@ -6394,13 +6346,13 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { if (!getDerived().AlwaysRebuild() && Callee.get() == E->getCallee() && !ArgChanged) - return SemaRef.MaybeBindToTemporary(E);; + return SemaRef.MaybeBindToTemporary(E); // FIXME: Wrong source location information for the '('. SourceLocation FakeLParenLoc = ((Expr *)Callee.get())->getSourceRange().getBegin(); return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc, - move_arg(Args), + Args, E->getRParenLoc()); } @@ -6499,6 +6451,9 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { RHS.get() == E->getRHS()) return SemaRef.Owned(E); + Sema::FPContractStateRAII FPContractState(getSema()); + getSema().FPFeatures.fp_contract = E->isFPContractable(); + return getDerived().RebuildBinaryOperator(E->getOperatorLoc(), E->getOpcode(), LHS.get(), RHS.get()); } @@ -6645,7 +6600,7 @@ ExprResult TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { bool InitChanged = false; - ASTOwningVector<Expr*, 4> Inits(SemaRef); + SmallVector<Expr*, 4> Inits; if (getDerived().TransformExprs(E->getInits(), E->getNumInits(), false, Inits, &InitChanged)) return ExprError(); @@ -6653,7 +6608,7 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { if (!getDerived().AlwaysRebuild() && !InitChanged) return SemaRef.Owned(E); - return getDerived().RebuildInitList(E->getLBraceLoc(), move_arg(Inits), + return getDerived().RebuildInitList(E->getLBraceLoc(), Inits, E->getRBraceLoc(), E->getType()); } @@ -6668,7 +6623,7 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { return ExprError(); // transform the designators. - ASTOwningVector<Expr*, 4> ArrayExprs(SemaRef); + SmallVector<Expr*, 4> ArrayExprs; bool ExprChanged = false; for (DesignatedInitExpr::designators_iterator D = E->designators_begin(), DEnd = E->designators_end(); @@ -6720,7 +6675,7 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { !ExprChanged) return SemaRef.Owned(E); - return getDerived().RebuildDesignatedInitExpr(Desig, move_arg(ArrayExprs), + return getDerived().RebuildDesignatedInitExpr(Desig, ArrayExprs, E->getEqualOrColonLoc(), E->usesGNUSyntax(), Init.get()); } @@ -6768,13 +6723,13 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) { bool ArgumentChanged = false; - ASTOwningVector<Expr*, 4> Inits(SemaRef); + SmallVector<Expr*, 4> Inits; if (TransformExprs(E->getExprs(), E->getNumExprs(), true, Inits, &ArgumentChanged)) return ExprError(); return getDerived().RebuildParenListExpr(E->getLParenLoc(), - move_arg(Inits), + Inits, E->getRParenLoc()); } @@ -6875,13 +6830,13 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { static_cast<Expr *>(Object.get())->getLocEnd()); // Transform the call arguments. - ASTOwningVector<Expr*> Args(SemaRef); + SmallVector<Expr*, 8> Args; if (getDerived().TransformExprs(E->getArgs() + 1, E->getNumArgs() - 1, true, Args)) return ExprError(); return getDerived().RebuildCallExpr(Object.get(), FakeLParenLoc, - move_arg(Args), + Args, E->getLocEnd()); } @@ -6905,7 +6860,11 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { if (Callee.isInvalid()) return ExprError(); - ExprResult First = getDerived().TransformExpr(E->getArg(0)); + ExprResult First; + if (E->getOperator() == OO_Amp) + First = getDerived().TransformAddressOfOperand(E->getArg(0)); + else + First = getDerived().TransformExpr(E->getArg(0)); if (First.isInvalid()) return ExprError(); @@ -6922,6 +6881,9 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { (E->getNumArgs() != 2 || Second.get() == E->getArg(1))) return SemaRef.MaybeBindToTemporary(E); + Sema::FPContractStateRAII FPContractState(getSema()); + getSema().FPFeatures.fp_contract = E->isFPContractable(); + return getDerived().RebuildCXXOperatorCallExpr(E->getOperator(), E->getOperatorLoc(), Callee.get(), @@ -6950,7 +6912,7 @@ TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) { // Transform arguments. bool ArgChanged = false; - ASTOwningVector<Expr*> Args(SemaRef); + SmallVector<Expr*, 8> Args; if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, &ArgChanged)) return ExprError(); @@ -6964,7 +6926,7 @@ TreeTransform<Derived>::TransformCUDAKernelCallExpr(CUDAKernelCallExpr *E) { SourceLocation FakeLParenLoc = ((Expr *)Callee.get())->getSourceRange().getBegin(); return getDerived().RebuildCallExpr(Callee.get(), FakeLParenLoc, - move_arg(Args), + Args, E->getRParenLoc(), EC.get()); } @@ -6989,9 +6951,6 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { SourceLocation FakeLAngleLoc = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc()); SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin(); - SourceLocation FakeRParenLoc - = SemaRef.PP.getLocForEndOfToken( - E->getSubExpr()->getSourceRange().getEnd()); return getDerived().RebuildCXXNamedCastExpr(E->getOperatorLoc(), E->getStmtClass(), FakeLAngleLoc, @@ -6999,7 +6958,7 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { FakeRAngleLoc, FakeRAngleLoc, SubExpr.get(), - FakeRParenLoc); + E->getRParenLoc()); } template<typename Derived> @@ -7074,7 +7033,8 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { // after we perform semantic analysis. We speculatively assume it is // unevaluated; it will get fixed later if the subexpression is in fact // potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated, + Sema::ReuseLambdaContextDecl); ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand()); if (SubExpr.isInvalid()) @@ -7222,7 +7182,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { // Transform the placement arguments (if any). bool ArgumentChanged = false; - ASTOwningVector<Expr*> PlacementArgs(SemaRef); + SmallVector<Expr*, 8> PlacementArgs; if (getDerived().TransformExprs(E->getPlacementArgs(), E->getNumPlacementArgs(), true, PlacementArgs, &ArgumentChanged)) @@ -7313,7 +7273,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { return getDerived().RebuildCXXNewExpr(E->getLocStart(), E->isGlobalNew(), /*FIXME:*/E->getLocStart(), - move_arg(PlacementArgs), + PlacementArgs, /*FIXME:*/E->getLocStart(), E->getTypeIdParens(), AllocType, @@ -7512,7 +7472,8 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr( // If we have template arguments, rebuild them, then rebuild the // templateid expression. TemplateArgumentListInfo TransArgs(Old->getLAngleLoc(), Old->getRAngleLoc()); - if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(), + if (Old->hasExplicitTemplateArgs() && + getDerived().TransformTemplateArguments(Old->getTemplateArgs(), Old->getNumTemplateArgs(), TransArgs)) return ExprError(); @@ -7732,6 +7693,14 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( DependentScopeDeclRefExpr *E) { + return TransformDependentScopeDeclRefExpr(E, /*IsAddressOfOperand*/false); +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( + DependentScopeDeclRefExpr *E, + bool IsAddressOfOperand) { NestedNameSpecifierLoc QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(E->getQualifierLoc()); if (!QualifierLoc) @@ -7758,7 +7727,8 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, TemplateKWLoc, NameInfo, - /*TemplateArgs*/ 0); + /*TemplateArgs*/ 0, + IsAddressOfOperand); } TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); @@ -7770,7 +7740,8 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( return getDerived().RebuildDependentScopeDeclRefExpr(QualifierLoc, TemplateKWLoc, NameInfo, - &TransArgs); + &TransArgs, + IsAddressOfOperand); } template<typename Derived> @@ -7796,7 +7767,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { return ExprError(); bool ArgumentChanged = false; - ASTOwningVector<Expr*> Args(SemaRef); + SmallVector<Expr*, 8> Args; if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, &ArgumentChanged)) return ExprError(); @@ -7813,7 +7784,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(), Constructor, E->isElidable(), - move_arg(Args), + Args, E->hadMultipleCandidates(), E->requiresZeroInitialization(), E->getConstructionKind(), @@ -7857,7 +7828,7 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( return ExprError(); bool ArgumentChanged = false; - ASTOwningVector<Expr*> Args(SemaRef); + SmallVector<Expr*, 8> Args; Args.reserve(E->getNumArgs()); if (TransformExprs(E->getArgs(), E->getNumArgs(), true, Args, &ArgumentChanged)) @@ -7874,19 +7845,13 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( return getDerived().RebuildCXXTemporaryObjectExpr(T, /*FIXME:*/T->getTypeLoc().getEndLoc(), - move_arg(Args), + Args, E->getLocEnd()); } template<typename Derived> ExprResult TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { - // Create the local class that will describe the lambda. - CXXRecordDecl *Class - = getSema().createLambdaClosureType(E->getIntroducerRange(), - /*KnownDependent=*/false); - getDerived().transformedLocalDecl(E->getLambdaClass(), Class); - // Transform the type of the lambda parameters and start the definition of // the lambda itself. TypeSourceInfo *MethodTy @@ -7894,6 +7859,13 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { if (!MethodTy) return ExprError(); + // Create the local class that will describe the lambda. + CXXRecordDecl *Class + = getSema().createLambdaClosureType(E->getIntroducerRange(), + MethodTy, + /*KnownDependent=*/false); + getDerived().transformedLocalDecl(E->getLambdaClass(), Class); + // Transform lambda parameters. llvm::SmallVector<QualType, 4> ParamTypes; llvm::SmallVector<ParmVarDecl *, 4> Params; @@ -8038,7 +8010,7 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( return ExprError(); bool ArgumentChanged = false; - ASTOwningVector<Expr*> Args(SemaRef); + SmallVector<Expr*, 8> Args; Args.reserve(E->arg_size()); if (getDerived().TransformExprs(E->arg_begin(), E->arg_size(), true, Args, &ArgumentChanged)) @@ -8052,7 +8024,7 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( // FIXME: we're faking the locations of the commas return getDerived().RebuildCXXUnresolvedConstructExpr(T, E->getLParenLoc(), - move_arg(Args), + Args, E->getRParenLoc()); } @@ -8346,6 +8318,13 @@ TreeTransform<Derived>::TransformSubstNonTypeTemplateParmExpr( template<typename Derived> ExprResult +TreeTransform<Derived>::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) { + // Default behavior is to do nothing with this transformation. + return SemaRef.Owned(E); +} + +template<typename Derived> +ExprResult TreeTransform<Derived>::TransformMaterializeTemporaryExpr( MaterializeTemporaryExpr *E) { return getDerived().TransformExpr(E->GetTemporaryExpr()); @@ -8576,7 +8555,7 @@ ExprResult TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { // Transform arguments. bool ArgChanged = false; - ASTOwningVector<Expr*> Args(SemaRef); + SmallVector<Expr*, 8> Args; Args.reserve(E->getNumArgs()); if (getDerived().TransformExprs(E->getArgs(), E->getNumArgs(), false, Args, &ArgChanged)) @@ -8602,7 +8581,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { SelLocs, E->getMethodDecl(), E->getLeftLoc(), - move_arg(Args), + Args, E->getRightLoc()); } @@ -8627,7 +8606,7 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { SelLocs, E->getMethodDecl(), E->getLeftLoc(), - move_arg(Args), + Args, E->getRightLoc()); } @@ -8740,7 +8719,7 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { bool ArgumentChanged = false; - ASTOwningVector<Expr*> SubExprs(SemaRef); + SmallVector<Expr*, 8> SubExprs; SubExprs.reserve(E->getNumSubExprs()); if (getDerived().TransformExprs(E->getSubExprs(), E->getNumSubExprs(), false, SubExprs, &ArgumentChanged)) @@ -8751,7 +8730,7 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { return SemaRef.Owned(E); return getDerived().RebuildShuffleVectorExpr(E->getBuiltinLoc(), - move_arg(SubExprs), + SubExprs, E->getRParenLoc()); } @@ -8854,7 +8833,7 @@ ExprResult TreeTransform<Derived>::TransformAtomicExpr(AtomicExpr *E) { QualType RetTy = getDerived().TransformType(E->getType()); bool ArgumentChanged = false; - ASTOwningVector<Expr*> SubExprs(SemaRef); + SmallVector<Expr*, 8> SubExprs; SubExprs.reserve(E->getNumSubExprs()); if (getDerived().TransformExprs(E->getSubExprs(), E->getNumSubExprs(), false, SubExprs, &ArgumentChanged)) @@ -8864,7 +8843,7 @@ TreeTransform<Derived>::TransformAtomicExpr(AtomicExpr *E) { !ArgumentChanged) return SemaRef.Owned(E); - return getDerived().RebuildAtomicExpr(E->getBuiltinLoc(), move_arg(SubExprs), + return getDerived().RebuildAtomicExpr(E->getBuiltinLoc(), SubExprs, RetTy, E->getOp(), E->getRParenLoc()); } @@ -9185,7 +9164,7 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, if (Result.isInvalid()) return ExprError(); - return move(Result); + return Result; } } @@ -9200,7 +9179,12 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, // IsAcceptableNonMemberOperatorCandidate for each of these? Functions.append(ULE->decls_begin(), ULE->decls_end()); } else { - Functions.addDecl(cast<DeclRefExpr>(Callee)->getDecl()); + // If we've resolved this to a particular non-member function, just call + // that function. If we resolved it to a member function, + // CreateOverloaded* will find that function for us. + NamedDecl *ND = cast<DeclRefExpr>(Callee)->getDecl(); + if (!isa<CXXMethodDecl>(ND)) + Functions.addDecl(ND); } // Add any functions found via argument-dependent lookup. @@ -9240,7 +9224,7 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, if (Result.isInvalid()) return ExprError(); - return move(Result); + return Result; } template<typename Derived> |