diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/JumpDiagnostics.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 92 | ||||
-rw-r--r-- | lib/Sema/SemaAttr.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 139 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 175 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 176 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 119 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 35 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 48 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 108 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 45 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 42 |
21 files changed, 762 insertions, 337 deletions
diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index ae863f2..425d804 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -77,11 +77,11 @@ JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) { /// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a /// diagnostic that should be emitted if control goes over it. If not, return 0. -static unsigned GetDiagForGotoScopeDecl(const Decl *D) { +static unsigned GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->getType()->isVariablyModifiedType()) return diag::note_protected_by_vla; - if (VD->hasAttr<CleanupAttr>()) + if (VD->hasAttr<CleanupAttr>(Context)) return diag::note_protected_by_cleanup; } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { if (TD->getUnderlyingType()->isVariablyModifiedType()) @@ -125,7 +125,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); I != E; ++I) { // If this decl causes a new scope, push and switch to it. - if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) { + if (unsigned Diag = GetDiagForGotoScopeDecl(this->S.Context, *I)) { Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation())); ParentScope = Scopes.size()-1; } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index a5f2438..e756b41 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -125,6 +125,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { if (!PP.getLangOptions().ObjC1) return; + // Built-in ObjC types may already be set by PCHReader (hence isNull checks). if (Context.getObjCSelType().isNull()) { // Synthesize "typedef struct objc_selector *SEL;" RecordDecl *SelTag = CreateStructDecl(Context, "objc_selector"); @@ -163,7 +164,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { // Synthesize "typedef struct objc_object { Class isa; } *id;" if (Context.getObjCIdType().isNull()) { RecordDecl *ObjectTag = CreateStructDecl(Context, "objc_object"); - + QualType ObjT = Context.getPointerType(Context.getTagDeclType(ObjectTag)); PushOnScopeChains(ObjectTag, TUScope); TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext, @@ -181,7 +182,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CurContext(0), PreDeclaratorDC(0), CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()), - GlobalNewDeleteDeclared(false), + GlobalNewDeleteDeclared(false), InUnevaluatedOperand(false), CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), CurrentInstantiationScope(0) { diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0607a89..560f952 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -18,7 +18,9 @@ #include "IdentifierResolver.h" #include "CXXFieldCollector.h" #include "SemaOverload.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/Action.h" @@ -102,7 +104,7 @@ struct BlockSemaInfo { /// ReturnType - This will get set to block result type, by looking at /// return types, if any, in the block body. - Type *ReturnType; + QualType ReturnType; /// LabelMap - This is a mapping from label identifiers to the LabelStmt for /// it (which acts like the label decl in some ways). Forward referenced @@ -245,6 +247,12 @@ public: /// have been declared. bool GlobalNewDeleteDeclared; + /// A flag that indicates when we are processing an unevaluated operand + /// (C++0x [expr]). C99 has the same notion of declarations being + /// "used" and C++03 has the notion of "potentially evaluated", but we + /// adopt the C++0x terminology since it is most precise. + bool InUnevaluatedOperand; + /// \brief Whether the code handled by Sema should be considered a /// complete translation unit or not. /// @@ -312,24 +320,8 @@ public: // If we encountered an error during template argument // deduction, and that error is one of the SFINAE errors, // suppress the diagnostic. - bool Fatal = false; - switch (Diags.getDiagnosticLevel(DiagID)) { - case Diagnostic::Ignored: - case Diagnostic::Note: - case Diagnostic::Warning: - break; - - case Diagnostic::Error: - ++NumSFINAEErrors; - break; - - case Diagnostic::Fatal: - Fatal = true; - break; - } - - if (!Fatal) - return SemaDiagnosticBuilder(*this); + ++NumSFINAEErrors; + return SemaDiagnosticBuilder(*this); } DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID); @@ -375,6 +367,8 @@ public: QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, SourceLocation Loc, DeclarationName Entity); + QualType BuildExtVectorType(QualType T, ExprArg ArraySize, + SourceLocation AttrLoc); QualType BuildFunctionType(QualType T, QualType *ParamTypes, unsigned NumParamTypes, bool Variadic, unsigned Quals, @@ -468,6 +462,19 @@ public: virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body); DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body, bool IsInstantiation); + + /// \brief Diagnose any unused parameters in the given sequence of + /// ParmVarDecl pointers. + template<typename InputIterator> + void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) { + for (; Param != ParamEnd; ++Param) { + if (!(*Param)->isUsed() && (*Param)->getDeclName() && + !(*Param)->template hasAttr<UnusedAttr>(Context)) + Diag((*Param)->getLocation(), diag::warn_unused_parameter) + << (*Param)->getDeclName(); + } + } + void DiagnoseInvalidJumps(Stmt *Body); virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr); @@ -553,6 +560,12 @@ public: void PushDeclContext(Scope *S, DeclContext *DC); void PopDeclContext(); + /// EnterDeclaratorContext - Used when we must lookup names in the context + /// of a declarator's nested name specifier. + void EnterDeclaratorContext(Scope *S, DeclContext *DC); + void ExitDeclaratorContext(Scope *S); + + /// getCurFunctionDecl - If inside of a function body, this returns a pointer /// to the function decl for the function being parsed. If we're currently /// in a 'block', this returns the containing context. @@ -702,6 +715,7 @@ public: bool isBetterOverloadCandidate(const OverloadCandidate& Cand1, const OverloadCandidate& Cand2); OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet, + SourceLocation Loc, OverloadCandidateSet::iterator& Best); void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, bool OnlyViable); @@ -1132,8 +1146,8 @@ public: // More parsing and symbol table subroutines. // Decl attributes - this routine is the top level dispatcher. - void ProcessDeclAttributes(Decl *D, const Declarator &PD); - void ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList); + void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); + void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList); void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl); @@ -1320,6 +1334,14 @@ public: void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs); + virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) { + bool Result = InUnevaluatedOperand; + InUnevaluatedOperand = UnevaluatedOperand; + return Result; + } + + void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); + // Primary Expressions. virtual SourceRange getExprRange(ExprTy *E) const; @@ -1525,6 +1547,14 @@ public: const CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident); + + virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope, + SourceLocation UsingLoc, + const CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *TargetName, + AttributeList *AttrList, + bool IsTypeName); /// AddCXXDirectInitializerToDecl - This action is called immediately after /// ActOnDeclarator, when a C++ direct initializer is present. @@ -1541,6 +1571,11 @@ public: CXXConstructorDecl *Constructor, QualType DeclInitType, Expr **Exprs, unsigned NumExprs); + + /// DefineImplicitDefaultConstructor - Checks for feasibilityt of + /// defining this constructor as the default constructor. + void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor); /// MaybeBindToTemporary - If the passed in expression has a record type with /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise @@ -1677,8 +1712,8 @@ public: /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is /// non-empty, will create a new CXXExprWithTemporaries expression. /// Otherwise, just returs the passed in expression. - Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, - bool DestroyTemps = true); + Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, + bool ShouldDestroyTemporaries); virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr); @@ -1735,6 +1770,17 @@ public: /// defining scope. virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS); + /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an + /// initializer for the declaration 'Dcl'. + /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a + /// static data member of class X, names should be looked up in the scope of + /// class X. + virtual void ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl); + + /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an + /// initializer for the declaration 'Dcl'. + virtual void ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl); + // ParseObjCStringLiteral - Parse Objective-C string literals. virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, ExprTy **Strings, diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 1bf8444..cbfa56a 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -205,7 +205,7 @@ void Sema::ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs, // Otherwise, add the 'unused' attribute to each referenced declaration. for (unsigned i = 0; i < NumExprs; ++i) { DeclRefExpr *DR = (DeclRefExpr*) Exprs[i]; - DR->getDecl()->addAttr(::new (Context) UnusedAttr()); + DR->getDecl()->addAttr(Context, ::new (Context) UnusedAttr()); DR->Destroy(Context); } } diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 11ac0bd..a14bcd5 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -286,11 +286,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, /// The 'SS' should be a non-empty valid CXXScopeSpec. void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); - assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?"); - PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity()); - CurContext = computeDeclContext(SS); - assert(CurContext && "No context?"); - S->setEntity(CurContext); + EnterDeclaratorContext(S, computeDeclContext(SS)); } /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously @@ -301,12 +297,5 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); assert(S->getEntity() == computeDeclContext(SS) && "Context imbalance!"); - S->setEntity(PreDeclaratorDC); - PreDeclaratorDC = 0; - - // Reset CurContext to the nearest enclosing context. - while (!S->getEntity() && S->getParent()) - S = S->getParent(); - CurContext = static_cast<DeclContext*>(S->getEntity()); - assert(CurContext && "No context?"); + ExitDeclaratorContext(S); } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 4856e7f..a2ceafa 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -166,7 +166,7 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { // handlers. // Printf checking. - if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) { + if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>(Context)) { if (Format->getType() == "printf") { bool HasVAListArg = Format->getFirstArg() == 0; if (!HasVAListArg) { @@ -178,7 +178,8 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { HasVAListArg ? 0 : Format->getFirstArg() - 1); } } - for (const Attr *attr = FDecl->getAttrs(); attr; attr = attr->getNext()) { + for (const Attr *attr = FDecl->getAttrs(Context); + attr; attr = attr->getNext()) { if (const NonNullAttr *NonNull = dyn_cast<NonNullAttr>(attr)) CheckNonNullArguments(NonNull, TheCall); } @@ -191,7 +192,7 @@ Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { OwningExprResult TheCallResult(Owned(TheCall)); // Printf checking. - const FormatAttr *Format = NDecl->getAttr<FormatAttr>(); + const FormatAttr *Format = NDecl->getAttr<FormatAttr>(Context); if (!Format) return move(TheCallResult); const VarDecl *V = dyn_cast<VarDecl>(NDecl); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b995717..06fd1a1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -183,7 +183,7 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { DeclContext *Sema::getContainingDC(DeclContext *DC) { if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(DC)) { // A C++ out-of-line method will return to the file declaration context. - if (MD->isOutOfLineDefinition()) + if (MD->isOutOfLine()) return MD->getLexicalDeclContext(); // A C++ inline method is parsed *after* the topmost class it was declared @@ -219,6 +219,27 @@ void Sema::PopDeclContext() { CurContext = getContainingDC(CurContext); } +/// EnterDeclaratorContext - Used when we must lookup names in the context +/// of a declarator's nested name specifier. +void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { + assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?"); + PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity()); + CurContext = DC; + assert(CurContext && "No context?"); + S->setEntity(CurContext); +} + +void Sema::ExitDeclaratorContext(Scope *S) { + S->setEntity(PreDeclaratorDC); + PreDeclaratorDC = 0; + + // Reset CurContext to the nearest enclosing context. + while (!S->getEntity() && S->getParent()) + S = S->getParent(); + CurContext = static_cast<DeclContext*>(S->getEntity()); + assert(CurContext && "No context?"); +} + /// \brief Determine whether we allow overloading of the function /// PrevDecl with another declaration. /// @@ -235,7 +256,7 @@ static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) { if (isa<OverloadedFunctionDecl>(PrevDecl)) return true; - return PrevDecl->getAttr<OverloadableAttr>() != 0; + return PrevDecl->getAttr<OverloadableAttr>(Context) != 0; } /// Add this decl to the scope shadowed decl chains. @@ -590,8 +611,9 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { /// DeclhasAttr - returns true if decl Declaration already has the target /// attribute. -static bool DeclHasAttr(const Decl *decl, const Attr *target) { - for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext()) +static bool +DeclHasAttr(ASTContext &Context, const Decl *decl, const Attr *target) { + for (const Attr *attr = decl->getAttrs(Context); attr; attr = attr->getNext()) if (attr->getKind() == target->getKind()) return true; @@ -600,11 +622,11 @@ static bool DeclHasAttr(const Decl *decl, const Attr *target) { /// MergeAttributes - append attributes from the Old decl to the New one. static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) { - for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) { - if (!DeclHasAttr(New, attr) && attr->isMerged()) { + for (const Attr *attr = Old->getAttrs(C); attr; attr = attr->getNext()) { + if (!DeclHasAttr(C, New, attr) && attr->isMerged()) { Attr *NewAttr = attr->clone(C); NewAttr->setInherited(true); - New->addAttr(NewAttr); + New->addAttr(C, NewAttr); } } } @@ -1615,7 +1637,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewTD->setInvalidDecl(); // Handle attributes prior to checking for duplicates in MergeVarDecl - ProcessDeclAttributes(NewTD, D); + ProcessDeclAttributes(S, NewTD, D); // Merge the decl with the existing one if appropriate. If the decl is // in an outer scope, it isn't the same thing. if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) { @@ -1801,13 +1823,14 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, NewVD->setLexicalDeclContext(CurContext); // Handle attributes prior to checking for duplicates in MergeVarDecl - ProcessDeclAttributes(NewVD, D); + ProcessDeclAttributes(S, NewVD, D); // Handle GNU asm-label extension (encoded as an attribute). if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewVD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), + NewVD->addAttr(Context, + ::new (Context) AsmLabelAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -1886,11 +1909,11 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, } if (NewVD->hasLocalStorage() && T.isObjCGCWeak() - && !NewVD->hasAttr<BlocksAttr>()) + && !NewVD->hasAttr<BlocksAttr>(Context)) Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); bool isVM = T->isVariablyModifiedType(); - if (isVM || NewVD->hasAttr<CleanupAttr>()) + if (isVM || NewVD->hasAttr<CleanupAttr>(Context)) CurFunctionNeedsScopeChecking = true; if ((isVM && NewVD->hasLinkage()) || @@ -1945,12 +1968,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, return NewVD->setInvalidDecl(); } - if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) { + if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>(Context)) { Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); return NewVD->setInvalidDecl(); } - if (isVM && NewVD->hasAttr<BlocksAttr>()) { + if (isVM && NewVD->hasAttr<BlocksAttr>(Context)) { Diag(NewVD->getLocation(), diag::err_block_on_vm); return NewVD->setInvalidDecl(); } @@ -2180,7 +2203,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewFD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), + NewFD->addAttr(Context, + ::new (Context) AsmLabelAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -2260,7 +2284,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, Diag(NewFD->getLocation(), diag::err_out_of_line_declaration) << D.getCXXScopeSpec().getRange(); NewFD->setInvalidDecl(); - } else if (!Redeclaration) { + } else if (!Redeclaration && (!PrevDecl || !isa<UsingDecl>(PrevDecl))) { // The user tried to provide an out-of-line definition for a // function that is a member of a class or namespace, but there // was no such member function declared (C++ [class.mfct]p2, @@ -2298,10 +2322,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // (for example to check for conflicts, etc). // FIXME: This needs to happen before we merge declarations. Then, // let attribute merging cope with attribute conflicts. - ProcessDeclAttributes(NewFD, D); + ProcessDeclAttributes(S, NewFD, D); AddKnownFunctionAttributes(NewFD); - if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) { + if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>(Context)) { // If a function name is overloadable in C, then every function // with that name must be marked "overloadable". Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) @@ -2309,7 +2333,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (PrevDecl) Diag(PrevDecl->getLocation(), diag::note_attribute_overloadable_prev_overload); - NewFD->addAttr(::new (Context) OverloadableAttr()); + NewFD->addAttr(Context, ::new (Context) OverloadableAttr()); } // If this is a locally-scoped extern C function, update the @@ -2431,7 +2455,8 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, if (PrevDecl && (!AllowOverloadingOfFunction(PrevDecl, Context) || - !IsOverload(NewFD, PrevDecl, MatchedDecl))) { + !IsOverload(NewFD, PrevDecl, MatchedDecl)) && + !isa<UsingDecl>(PrevDecl)) { Redeclaration = true; Decl *OldDecl = PrevDecl; @@ -2708,8 +2733,12 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { IK_Default); if (!Constructor) Var->setInvalidDecl(); - else if (!RD->hasTrivialConstructor()) - InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0); + else { + if (!RD->hasTrivialConstructor()) + InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0); + // Check for valid construction. + DefineImplicitDefaultConstructor(Var->getLocation(), Constructor); + } } } @@ -2907,9 +2936,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (II) IdResolver.AddDecl(New); - ProcessDeclAttributes(New, D); + ProcessDeclAttributes(S, New, D); - if (New->hasAttr<BlocksAttr>()) { + if (New->hasAttr<BlocksAttr>(Context)) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } return DeclPtrTy::make(New); @@ -3035,9 +3064,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // Checking attributes of current function definition // dllimport attribute. - if (FD->getAttr<DLLImportAttr>() && (!FD->getAttr<DLLExportAttr>())) { + if (FD->getAttr<DLLImportAttr>(Context) && + (!FD->getAttr<DLLExportAttr>(Context))) { // dllimport attribute cannot be applied to definition. - if (!(FD->getAttr<DLLImportAttr>())->isInherited()) { + if (!(FD->getAttr<DLLImportAttr>(Context))->isInherited()) { Diag(FD->getLocation(), diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; @@ -3065,10 +3095,23 @@ Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg, Stmt *Body = BodyArg.takeAs<Stmt>(); if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) { FD->setBody(Body); + + if (!FD->isInvalidDecl()) + DiagnoseUnusedParameters(FD->param_begin(), FD->param_end()); + + // C++ [basic.def.odr]p2: + // [...] A virtual member function is used if it is not pure. [...] + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) + if (Method->isVirtual() && !Method->isPure()) + MarkDeclarationReferenced(Method->getLocation(), Method); + assert(FD == getCurFunctionDecl() && "Function parsing confused"); } else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) { assert(MD == getCurMethodDecl() && "Method parsing confused"); MD->setBody(Body); + + if (!MD->isInvalidDecl()) + DiagnoseUnusedParameters(MD->param_begin(), MD->param_end()); } else { Body->Destroy(Context); return DeclPtrTy(); @@ -3206,8 +3249,9 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { unsigned FormatIdx; bool HasVAListArg; if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { - if (!FD->getAttr<FormatAttr>()) - FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1, + if (!FD->getAttr<FormatAttr>(Context)) + FD->addAttr(Context, + ::new (Context) FormatAttr("printf", FormatIdx + 1, HasVAListArg ? 0 : FormatIdx + 2)); } @@ -3216,8 +3260,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // IRgen to use LLVM intrinsics for such functions. if (!getLangOptions().MathErrno && Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { - if (!FD->getAttr<ConstAttr>()) - FD->addAttr(::new (Context) ConstAttr()); + if (!FD->getAttr<ConstAttr>(Context)) + FD->addAttr(Context, ::new (Context) ConstAttr()); } } @@ -3235,15 +3279,17 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { return; if (Name->isStr("NSLog") || Name->isStr("NSLogv")) { - if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { + if (const FormatAttr *Format = FD->getAttr<FormatAttr>(Context)) { // FIXME: We known better than our headers. const_cast<FormatAttr *>(Format)->setType("printf"); } else - FD->addAttr(::new (Context) FormatAttr("printf", 1, + FD->addAttr(Context, + ::new (Context) FormatAttr("printf", 1, Name->isStr("NSLogv") ? 0 : 2)); } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { - if (!FD->getAttr<FormatAttr>()) - FD->addAttr(::new (Context) FormatAttr("printf", 2, + if (!FD->getAttr<FormatAttr>(Context)) + FD->addAttr(Context, + ::new (Context) FormatAttr("printf", 2, Name->isStr("vasprintf") ? 0 : 3)); } } @@ -3599,7 +3645,7 @@ CreateNewDecl: // the #pragma tokens are effectively skipped over during the // parsing of the struct). if (unsigned Alignment = getPragmaPackAlignment()) - New->addAttr(::new (Context) PackedAttr(Alignment * 8)); + New->addAttr(Context, ::new (Context) PackedAttr(Alignment * 8)); } if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) { @@ -3628,7 +3674,7 @@ CreateNewDecl: New->setInvalidDecl(); if (Attr) - ProcessDeclAttributeList(New, Attr); + ProcessDeclAttributeList(S, New, Attr); // If we're declaring or defining a tag in function prototype scope // in C, note that this type can only be used within the function. @@ -3786,6 +3832,14 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); + + if (PrevDecl && PrevDecl->isTemplateParameter()) { + // Maybe we will complain about the shadowed template parameter. + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + // Just pretend that we didn't see the previous declaration. + PrevDecl = 0; + } + if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) PrevDecl = 0; @@ -3878,7 +3932,8 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, // FIXME: We need to pass in the attributes given an AST // representation, not a parser representation. if (D) - ProcessDeclAttributes(NewFD, *D); + // FIXME: What to pass instead of TUScope? + ProcessDeclAttributes(TUScope, NewFD, *D); if (T.isObjCGCWeak()) Diag(Loc, diag::warn_attribute_weak_on_field); @@ -3985,7 +4040,7 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, } // Process attributes attached to the ivar. - ProcessDeclAttributes(NewID, D); + ProcessDeclAttributes(S, NewID, D); if (D.isInvalidType()) NewID->setInvalidDecl(); @@ -4151,7 +4206,7 @@ void Sema::ActOnFields(Scope* S, } if (Attr) - ProcessDeclAttributeList(Record, Attr); + ProcessDeclAttributeList(S, Record, Attr); } EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, @@ -4441,7 +4496,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, // FIXME: This implementation is an ugly hack! if (PrevDecl) { - PrevDecl->addAttr(::new (Context) WeakAttr()); + PrevDecl->addAttr(Context, ::new (Context) WeakAttr()); return; } Diag(PragmaLoc, diag::err_unsupported_pragma_weak); @@ -4457,8 +4512,8 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, // FIXME: This implementation is an ugly hack! if (PrevDecl) { - PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName())); - PrevDecl->addAttr(::new (Context) WeakAttr()); + PrevDecl->addAttr(Context, ::new (Context) AliasAttr(AliasName->getName())); + PrevDecl->addAttr(Context, ::new (Context) WeakAttr()); return; } Diag(PragmaLoc, diag::err_unsupported_pragma_weak); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 1afdb60..d57630e 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -156,8 +156,8 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { // least add some helper functions to check most argument patterns (# // and types of args). -static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr, - Sema &S) { +static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, + const AttributeList &Attr, Sema &S) { TypedefDecl *tDecl = dyn_cast<TypedefDecl>(d); if (tDecl == 0) { S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); @@ -165,37 +165,32 @@ static void HandleExtVectorTypeAttr(Decl *d, const AttributeList &Attr, } QualType curType = tDecl->getUnderlyingType(); - // check the attribute arguments. - if (Attr.getNumArgs() != 1) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; - return; - } - Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0)); - llvm::APSInt vecSize(32); - if (!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "ext_vector_type" << sizeExpr->getSourceRange(); - return; - } - // unlike gcc's vector_size attribute, we do not allow vectors to be defined - // in conjunction with complex types (pointers, arrays, functions, etc.). - if (!curType->isIntegerType() && !curType->isRealFloatingType()) { - S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << curType; - return; + + Expr *sizeExpr; + + // Special case where the argument is a template id. + if (Attr.getParameterName()) { + sizeExpr = S.ActOnDeclarationNameExpr(scope, Attr.getLoc(), + Attr.getParameterName(), + false, 0, false).takeAs<Expr>(); + } else { + // check the attribute arguments. + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + sizeExpr = static_cast<Expr *>(Attr.getArg(0)); } - // unlike gcc's vector_size attribute, the size is specified as the - // number of elements, not the number of bytes. - unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); - - if (vectorSize == 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_zero_size) - << sizeExpr->getSourceRange(); - return; + + // Instantiate/Install the vector type, and let Sema build the type for us. + // This will run the reguired checks. + QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc()); + if (!T.isNull()) { + tDecl->setUnderlyingType(T); + + // Remember this typedef decl, we will need it later for diagnostics. + S.ExtVectorDecls.push_back(tDecl); } - // Instantiate/Install the vector type, the number of elements is > 0. - tDecl->setUnderlyingType(S.Context.getExtVectorType(curType, vectorSize)); - // Remember this typedef decl, we will need it later for diagnostics. - S.ExtVectorDecls.push_back(tDecl); } @@ -289,7 +284,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { } if (TagDecl *TD = dyn_cast<TagDecl>(d)) - TD->addAttr(::new (S.Context) PackedAttr(1)); + TD->addAttr(S.Context, ::new (S.Context) PackedAttr(1)); 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. @@ -298,7 +293,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << Attr.getName() << FD->getType(); else - FD->addAttr(::new (S.Context) PackedAttr(1)); + FD->addAttr(S.Context, ::new (S.Context) PackedAttr(1)); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -313,7 +308,7 @@ static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) { // The IBOutlet attribute only applies to instance variables of Objective-C // classes. if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) - d->addAttr(::new (S.Context) IBOutletAttr()); + d->addAttr(S.Context, ::new (S.Context) IBOutletAttr()); else S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet); } @@ -385,7 +380,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned* start = &NonNullArgs[0]; unsigned size = NonNullArgs.size(); std::sort(start, start + size); - d->addAttr(::new (S.Context) NonNullAttr(start, size)); + d->addAttr(S.Context, ::new (S.Context) NonNullAttr(start, size)); } static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -410,7 +405,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: check if target symbol exists in current file - d->addAttr(::new (S.Context) AliasAttr(std::string(Alias, AliasLen))); + d->addAttr(S.Context, ::new (S.Context) AliasAttr(std::string(Alias, AliasLen))); } static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, @@ -427,7 +422,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, return; } - d->addAttr(::new (S.Context) AlwaysInlineAttr()); + d->addAttr(S.Context, ::new (S.Context) AlwaysInlineAttr()); } static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, @@ -452,13 +447,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (HandleCommonNoReturnAttr(d, Attr, S)) - d->addAttr(::new (S.Context) NoReturnAttr()); + d->addAttr(S.Context, ::new (S.Context) NoReturnAttr()); } static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (HandleCommonNoReturnAttr(d, Attr, S)) - d->addAttr(::new (S.Context) AnalyzerNoReturnAttr()); + d->addAttr(S.Context, ::new (S.Context) AnalyzerNoReturnAttr()); } static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -474,7 +469,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) UnusedAttr()); + d->addAttr(S.Context, ::new (S.Context) UnusedAttr()); } static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -495,7 +490,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) UsedAttr()); + d->addAttr(S.Context, ::new (S.Context) UsedAttr()); } static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -524,7 +519,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) ConstructorAttr(priority)); + d->addAttr(S.Context, ::new (S.Context) ConstructorAttr(priority)); } static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -553,7 +548,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) DestructorAttr(priority)); + d->addAttr(S.Context, ::new (S.Context) DestructorAttr(priority)); } static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -563,7 +558,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) DeprecatedAttr()); + d->addAttr(S.Context, ::new (S.Context) DeprecatedAttr()); } static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -573,7 +568,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) UnavailableAttr()); + d->addAttr(S.Context, ::new (S.Context) UnavailableAttr()); } static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -610,7 +605,7 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) VisibilityAttr(type)); + d->addAttr(S.Context, ::new (S.Context) VisibilityAttr(type)); } static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, @@ -626,7 +621,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, return; } - D->addAttr(::new (S.Context) ObjCExceptionAttr()); + D->addAttr(S.Context, ::new (S.Context) ObjCExceptionAttr()); } static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { @@ -642,7 +637,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { return; } } - D->addAttr(::new (S.Context) ObjCNSObjectAttr()); + D->addAttr(S.Context, ::new (S.Context) ObjCNSObjectAttr()); } static void @@ -657,7 +652,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) OverloadableAttr()); + D->addAttr(S.Context, ::new (S.Context) OverloadableAttr()); } static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -681,7 +676,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) BlocksAttr(type)); + d->addAttr(S.Context, ::new (S.Context) BlocksAttr(type)); } static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -773,7 +768,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { << Attr.getName() << 6 /*function, method or block */; return; } - d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos)); + d->addAttr(S.Context, ::new (S.Context) SentinelAttr(sentinel, nullPos)); } static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { @@ -791,7 +786,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) return; } - Fn->addAttr(::new (S.Context) WarnUnusedResultAttr()); + Fn->addAttr(S.Context, ::new (S.Context) WarnUnusedResultAttr()); } static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -808,7 +803,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) WeakAttr()); + D->addAttr(S.Context, ::new (S.Context) WeakAttr()); } static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -841,7 +836,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) WeakImportAttr()); + D->addAttr(S.Context, ::new (S.Context) WeakImportAttr()); } static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -853,7 +848,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // Attribute can be applied only to functions or variables. if (isa<VarDecl>(D)) { - D->addAttr(::new (S.Context) DLLImportAttr()); + D->addAttr(S.Context, ::new (S.Context) DLLImportAttr()); return; } @@ -881,12 +876,12 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { } } - if (D->getAttr<DLLExportAttr>()) { + if (D->getAttr<DLLExportAttr>(S.Context)) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; return; } - D->addAttr(::new (S.Context) DLLImportAttr()); + D->addAttr(S.Context, ::new (S.Context) DLLImportAttr()); } static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -898,7 +893,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // Attribute can be applied only to functions or variables. if (isa<VarDecl>(D)) { - D->addAttr(::new (S.Context) DLLExportAttr()); + D->addAttr(S.Context, ::new (S.Context) DLLExportAttr()); return; } @@ -917,7 +912,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) DLLExportAttr()); + D->addAttr(S.Context, ::new (S.Context) DLLExportAttr()); } static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -936,7 +931,8 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); return; } - D->addAttr(::new (S.Context) SectionAttr(std::string(SE->getStrData(), + D->addAttr(S.Context, + ::new (S.Context) SectionAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -955,13 +951,13 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // stdcall and fastcall attributes are mutually incompatible. - if (d->getAttr<FastCallAttr>()) { + if (d->getAttr<FastCallAttr>(S.Context)) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "stdcall" << "fastcall"; return; } - d->addAttr(::new (S.Context) StdCallAttr()); + d->addAttr(S.Context, ::new (S.Context) StdCallAttr()); } static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -978,13 +974,13 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // stdcall and fastcall attributes are mutually incompatible. - if (d->getAttr<StdCallAttr>()) { + if (d->getAttr<StdCallAttr>(S.Context)) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "fastcall" << "stdcall"; return; } - d->addAttr(::new (S.Context) FastCallAttr()); + d->addAttr(S.Context, ::new (S.Context) FastCallAttr()); } static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -994,7 +990,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) NoThrowAttr()); + d->addAttr(S.Context, ::new (S.Context) NoThrowAttr()); } static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1004,7 +1000,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) ConstAttr()); + d->addAttr(S.Context, ::new (S.Context) ConstAttr()); } static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1014,7 +1010,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) PureAttr()); + d->addAttr(S.Context, ::new (S.Context) PureAttr()); } static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1072,7 +1068,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) CleanupAttr(FD)); + d->addAttr(S.Context, ::new (S.Context) CleanupAttr(FD)); } /// Handle __attribute__((format_arg((idx)))) attribute @@ -1135,7 +1131,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue())); + d->addAttr(S.Context, ::new (S.Context) FormatArgAttr(Idx.getZExtValue())); } /// Handle __attribute__((format(type,idx,firstarg))) attributes @@ -1276,7 +1272,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen), + d->addAttr(S.Context, + ::new (S.Context) FormatAttr(std::string(Format, FormatLen), Idx.getZExtValue(), FirstArg.getZExtValue())); } @@ -1344,7 +1341,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, } } - RD->addAttr(::new (S.Context) TransparentUnionAttr()); + RD->addAttr(S.Context, ::new (S.Context) TransparentUnionAttr()); } static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1362,7 +1359,8 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); return; } - d->addAttr(::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), + d->addAttr(S.Context, + ::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -1378,7 +1376,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: This should be the target specific maximum alignment. // (For now we just use 128 bits which is the maximum on X86). Align = 128; - d->addAttr(::new (S.Context) AlignedAttr(Align)); + d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Align)); return; } @@ -1395,7 +1393,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8)); + d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8)); } /// HandleModeAttr - This attribute modifies the width of a decl with @@ -1576,7 +1574,7 @@ static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) NodebugAttr()); + d->addAttr(S.Context, ::new (S.Context) NodebugAttr()); } static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1592,7 +1590,7 @@ static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) NoinlineAttr()); + d->addAttr(S.Context, ::new (S.Context) NoinlineAttr()); } static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1614,7 +1612,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) GNUInlineAttr()); + d->addAttr(S.Context, ::new (S.Context) GNUInlineAttr()); } static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1650,7 +1648,8 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); + d->addAttr(S.Context, + ::new (S.Context) RegparmAttr(NumParams.getZExtValue())); } //===----------------------------------------------------------------------===// @@ -1683,10 +1682,10 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, assert(0 && "invalid ownership attribute"); return; case AttributeList::AT_cf_returns_retained: - d->addAttr(::new (S.Context) CFReturnsRetainedAttr()); + d->addAttr(S.Context, ::new (S.Context) CFReturnsRetainedAttr()); return; case AttributeList::AT_ns_returns_retained: - d->addAttr(::new (S.Context) NSReturnsRetainedAttr()); + d->addAttr(S.Context, ::new (S.Context) NSReturnsRetainedAttr()); return; }; } @@ -1698,7 +1697,7 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if /// the attribute applies to decls. If the attribute is a type attribute, just /// silently ignore it. -static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { +static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Attr, Sema &S) { if (Attr.isDeclspecAttribute()) // FIXME: Try to deal with __declspec attributes! return; @@ -1721,7 +1720,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { case AttributeList::AT_dllexport: HandleDLLExportAttr (D, Attr, S); break; case AttributeList::AT_dllimport: HandleDLLImportAttr (D, Attr, S); break; case AttributeList::AT_ext_vector_type: - HandleExtVectorTypeAttr(D, Attr, S); + HandleExtVectorTypeAttr(scope, D, Attr, S); break; case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; @@ -1777,9 +1776,9 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. -void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) { +void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList) { while (AttrList) { - ProcessDeclAttribute(D, *AttrList, *this); + ProcessDeclAttribute(S, D, *AttrList, *this); AttrList = AttrList->getNext(); } } @@ -1787,10 +1786,10 @@ void Sema::ProcessDeclAttributeList(Decl *D, const AttributeList *AttrList) { /// ProcessDeclAttributes - Given a declarator (PD) with attributes indicated in /// it, apply them to D. This is a bit tricky because PD can have attributes /// specified in many different places, and we need to find and apply them all. -void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) { +void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Apply decl attributes from the DeclSpec if present. if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes()) - ProcessDeclAttributeList(D, Attrs); + ProcessDeclAttributeList(S, D, Attrs); // Walk the declarator structure, applying decl attributes that were in a type // position to the decl itself. This handles cases like: @@ -1798,9 +1797,9 @@ void Sema::ProcessDeclAttributes(Decl *D, const Declarator &PD) { // when X is a decl attribute. for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) - ProcessDeclAttributeList(D, Attrs); + ProcessDeclAttributeList(S, D, Attrs); // Finally, apply any attributes on the decl itself. if (const AttributeList *Attrs = PD.getAttributes()) - ProcessDeclAttributeList(D, Attrs); + ProcessDeclAttributeList(S, D, Attrs); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 8f64e78..6d740eb 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -147,8 +147,11 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, return; } + DefaultArgPtr = MaybeCreateCXXExprWithTemporaries(DefaultArg.take(), + /*DestroyTemps=*/false); + // Okay: add the default argument to the parameter - Param->setDefaultArg(DefaultArg.take()); + Param->setDefaultArg(DefaultArgPtr); } /// ActOnParamUnparsedDefaultArgument - We've seen a default @@ -1031,9 +1034,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { DefaultCon->setAccess(AS_public); DefaultCon->setImplicit(); ClassDecl->addDecl(Context, DefaultCon); - - // Notify the class that we've added a constructor. - ClassDecl->addedConstructor(Context, DefaultCon); } if (!ClassDecl->hasUserDeclaredCopyConstructor()) { @@ -1110,8 +1110,6 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { /*IdentifierInfo=*/0, ArgType, VarDecl::None, 0); CopyConstructor->setParams(Context, &FromParam, 1); - - ClassDecl->addedConstructor(Context, CopyConstructor); ClassDecl->addDecl(Context, CopyConstructor); } @@ -1750,6 +1748,43 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { S->PushUsingDirective(DeclPtrTy::make(UDir)); } + +Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, + SourceLocation UsingLoc, + const CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *TargetName, + AttributeList *AttrList, + bool IsTypeName) { + assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); + assert(TargetName && "Invalid TargetName."); + assert(IdentLoc.isValid() && "Invalid TargetName location."); + assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + + UsingDecl *UsingAlias = 0; + + // Lookup target name. + LookupResult R = LookupParsedName(S, &SS, TargetName, + LookupOrdinaryName, false); + + if (NamedDecl *NS = R) { + if (IsTypeName && !isa<TypeDecl>(NS)) { + Diag(IdentLoc, diag::err_using_typename_non_type); + } + UsingAlias = UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(), + NS->getLocation(), UsingLoc, NS, + static_cast<NestedNameSpecifier *>(SS.getScopeRep()), + IsTypeName); + PushOnScopeChains(UsingAlias, S); + } else { + Diag(IdentLoc, diag::err_using_requires_qualname) << SS.getRange(); + } + + // FIXME: We ignore attributes for now. + delete AttrList; + return DeclPtrTy::make(UsingAlias); +} + /// getNamespaceDecl - Returns the namespace a decl represents. If the decl /// is a namespace alias, returns the namespace it points to. static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { @@ -1795,7 +1830,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy(); } - NamespaceAliasDecl *AliasDecl = + NamespaceAliasDecl *AliasDecl = NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, Alias, SS.getRange(), (NestedNameSpecifier *)SS.getScopeRep(), @@ -1805,6 +1840,81 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy::make(AliasDecl); } +void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor) { + if (!Constructor->isDefaultConstructor() || + !Constructor->isImplicit() || Constructor->isImplicitMustBeDefined()) + return; + + CXXRecordDecl *ClassDecl + = cast<CXXRecordDecl>(Constructor->getDeclContext()); + assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor"); + // Before the implicitly-declared default constructor for a class is + // implicitly defined, all the implicitly-declared default constructors + // for its base class and its non-static data members shall have been + // implicitly defined. + bool err = false; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); + if (!BaseClassDecl->hasTrivialConstructor()) { + if (CXXConstructorDecl *BaseCtor = + BaseClassDecl->getDefaultConstructor(Context)) { + if (BaseCtor->isImplicit()) + BaseCtor->setImplicitMustBeDefined(); + } + else { + Diag(CurrentLocation, diag::err_defining_default_ctor) + << Context.getTagDeclType(ClassDecl) << 1 + << Context.getTagDeclType(BaseClassDecl); + Diag(BaseClassDecl->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(BaseClassDecl); + err = true; + } + } + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); + Field != ClassDecl->field_end(Context); + ++Field) { + QualType FieldType = Context.getCanonicalType((*Field)->getType()); + if (const ArrayType *Array = Context.getAsArrayType(FieldType)) + FieldType = Array->getElementType(); + if (const RecordType *FieldClassType = FieldType->getAsRecordType()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + if (!FieldClassDecl->hasTrivialConstructor()) + if (CXXConstructorDecl *FieldCtor = + FieldClassDecl->getDefaultConstructor(Context)) { + if (FieldCtor->isImplicit()) + FieldCtor->setImplicitMustBeDefined(); + } + else { + Diag(CurrentLocation, diag::err_defining_default_ctor) + << Context.getTagDeclType(ClassDecl) << 0 << + Context.getTagDeclType(FieldClassDecl); + Diag(FieldClassDecl->getLocation(), diag::note_previous_class_decl) + << Context.getTagDeclType(FieldClassDecl); + err = true; + } + } + else if (FieldType->isReferenceType()) { + Diag(CurrentLocation, diag::err_unintialized_member) + << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString(); + Diag((*Field)->getLocation(), diag::note_declared_at); + err = true; + } + else if (FieldType.isConstQualified()) { + Diag(CurrentLocation, diag::err_unintialized_member) + << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getNameAsCString(); + Diag((*Field)->getLocation(), diag::note_declared_at); + err = true; + } + } + if (!err) + Constructor->setImplicitMustBeDefined(); +} + void Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, QualType DeclInitType, @@ -1880,6 +1990,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, VDecl->setCXXDirectInitializer(true); InitializeVarWithConstructor(VDecl, Constructor, DeclInitType, (Expr**)Exprs.release(), NumExprs); + // An implicitly-declared default constructor for a class is implicitly + // defined when it is used to creat an object of its class type. + DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor); } return; } @@ -1956,7 +2069,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, // constructors, we'll need to make them appear here. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Loc, Best)) { case OR_Success: // We found a constructor. Return it. return cast<CXXConstructorDecl>(Best->Function); @@ -2188,7 +2301,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Init->getLocStart(), Best)) { case OR_Success: // This is a direct binding. BindsDirectly = true; @@ -2668,7 +2781,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { else CurContext->addDecl(Context, ExDecl); - ProcessDeclAttributes(ExDecl, D); + ProcessDeclAttributes(S, ExDecl, D); return DeclPtrTy::make(ExDecl); } @@ -2830,3 +2943,46 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return false; } + +/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse an +/// initializer for the declaration 'Dcl'. +/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a +/// static data member of class X, names should be looked up in the scope of +/// class X. +void Sema::ActOnCXXEnterDeclInitializer(Scope *S, DeclPtrTy Dcl) { + Decl *D = Dcl.getAs<Decl>(); + // If there is no declaration, there was an error parsing it. + if (D == 0) + return; + + // Check whether it is a declaration with a nested name specifier like + // int foo::bar; + if (!D->isOutOfLine()) + return; + + // C++ [basic.lookup.unqual]p13 + // + // A name used in the definition of a static data member of class X + // (after the qualified-id of the static member) is looked up as if the name + // was used in a member function of X. + + // Change current context into the context of the initializing declaration. + EnterDeclaratorContext(S, D->getDeclContext()); +} + +/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an +/// initializer for the declaration 'Dcl'. +void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) { + Decl *D = Dcl.getAs<Decl>(); + // If there is no declaration, there was an error parsing it. + if (D == 0) + return; + + // Check whether it is a declaration with a nested name specifier like + // int foo::bar; + if (!D->isOutOfLine()) + return; + + assert(S->getEntity() == D->getDeclContext() && "Context imbalance!"); + ExitDeclaratorContext(S); +} diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 5d47516..9013726 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -116,7 +116,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IDecl = ObjCInterfaceDecl::Create(Context, CurContext, AtInterfaceLoc, ClassName, ClassLoc); if (AttrList) - ProcessDeclAttributeList(IDecl, AttrList); + ProcessDeclAttributeList(TUScope, IDecl, AttrList); PushOnScopeChains(IDecl, TUScope); } @@ -282,7 +282,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, PDecl->setForwardDecl(false); } if (AttrList) - ProcessDeclAttributeList(PDecl, AttrList); + ProcessDeclAttributeList(TUScope, PDecl, AttrList); if (NumProtoRefs) { /// Check then save referenced protocols. PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context); @@ -532,7 +532,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, PushOnScopeChains(PDecl, TUScope); } if (attrList) - ProcessDeclAttributeList(PDecl, attrList); + ProcessDeclAttributeList(TUScope, PDecl, attrList); Protocols.push_back(PDecl); } @@ -1663,7 +1663,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); // Apply the attributes to the parameter. - ProcessDeclAttributeList(Param, ArgInfo[i].ArgAttrs); + ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); Params.push_back(Param); } @@ -1674,7 +1674,7 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( const ObjCMethodDecl *PrevMethod = 0; if (AttrList) - ProcessDeclAttributeList(ObjCMethod, AttrList); + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); // For implementations (which can be very "coarse grain"), we add the // method now. This allows the AST to implement lookup methods that work @@ -1877,7 +1877,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, PDecl->setInvalidDecl(); } - ProcessDeclAttributes(PDecl, FD.D); + ProcessDeclAttributes(S, PDecl, FD.D); // Regardless of setter/getter attribute, we save the default getter/setter // selector names in anticipation of declaration of setter/getter methods. diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c01c812..692502b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -39,7 +39,7 @@ using namespace clang; /// referenced), false otherwise. bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // See if the decl is deprecated. - if (D->getAttr<DeprecatedAttr>()) { + if (D->getAttr<DeprecatedAttr>(Context)) { // Implementing deprecated stuff requires referencing deprecated // stuff. Don't warn if we are implementing a deprecated // construct. @@ -48,7 +48,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { if (NamedDecl *ND = getCurFunctionOrMethodDecl()) { // If this reference happens *in* a deprecated function or method, don't // warn. - isSilenced = ND->getAttr<DeprecatedAttr>(); + isSilenced = ND->getAttr<DeprecatedAttr>(Context); // If this is an Objective-C method implementation, check to see if the // method was deprecated on the declaration, not the definition. @@ -61,7 +61,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { MD = Impl->getClassInterface()->getMethod(Context, MD->getSelector(), MD->isInstanceMethod()); - isSilenced |= MD && MD->getAttr<DeprecatedAttr>(); + isSilenced |= MD && MD->getAttr<DeprecatedAttr>(Context); } } } @@ -80,7 +80,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { } // See if the decl is unavailable - if (D->getAttr<UnavailableAttr>()) { + if (D->getAttr<UnavailableAttr>(Context)) { Diag(Loc, diag::warn_unavailable) << D->getDeclName(); Diag(D->getLocation(), diag::note_unavailable_here) << 0; } @@ -95,7 +95,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs) { - const SentinelAttr *attr = D->getAttr<SentinelAttr>(); + const SentinelAttr *attr = D->getAttr<SentinelAttr>(Context); if (!attr) return; int sentinelPos = attr->getSentinel(); @@ -627,6 +627,7 @@ DeclRefExpr * Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, bool TypeDependent, bool ValueDependent, const CXXScopeSpec *SS) { + MarkDeclarationReferenced(Loc, D); if (SS && !SS->isEmpty()) { return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent, SS->getRange(), @@ -721,6 +722,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, // BaseObject is an anonymous struct/union variable (and is, // therefore, not part of another non-anonymous record). if (BaseObjectExpr) BaseObjectExpr->Destroy(Context); + MarkDeclarationReferenced(Loc, BaseObject); BaseObjectExpr = new (Context) DeclRefExpr(BaseObject,BaseObject->getType(), SourceLocation()); ExtraQuals @@ -777,6 +779,7 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, = MemberType.getCVRQualifiers() | ExtraQuals; MemberType = MemberType.getQualifiedType(combinedQualifiers); } + MarkDeclarationReferenced(Loc, *FI); Result = new (Context) MemberExpr(Result, BaseObjectIsPointer, *FI, OpLoc, MemberType); BaseObjectIsPointer = false; @@ -876,6 +879,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // turn this into Self->ivar, just return a BareIVarExpr or something. IdentifierInfo &II = Context.Idents.get("self"); OwningExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false); + MarkDeclarationReferenced(Loc, IV); return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, SelfExpr.takeAs<Expr>(), true, true)); @@ -1025,6 +1029,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // Build the implicit member access expression. Expr *This = new (Context) CXXThisExpr(SourceLocation(), MD->getThisType(Context)); + MarkDeclarationReferenced(Loc, D); return Owned(new (Context) MemberExpr(This, true, D, Loc, MemberType)); } @@ -1125,14 +1130,18 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // as they do not get snapshotted. // if (CurBlock && ShouldSnapshotBlockValueReference(CurBlock, VD)) { + MarkDeclarationReferenced(Loc, VD); QualType ExprTy = VD->getType().getNonReferenceType(); // The BlocksAttr indicates the variable is bound by-reference. - if (VD->getAttr<BlocksAttr>()) + if (VD->getAttr<BlocksAttr>(Context)) return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true)); - + // This is to record that a 'const' was actually synthesize and added. + bool constAdded = !ExprTy.isConstQualified(); // Variable will be bound by-copy, make it const within the closure. + ExprTy.addConst(); - return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false)); + return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false, + constAdded)); } // If this reference is not in a block or if the referenced variable is // within the block, create a normal DeclRefExpr. @@ -1576,7 +1585,7 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -1686,7 +1695,7 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, LLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -1969,13 +1978,13 @@ static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, return 0; } -static Decl *FindGetterNameDecl(const ObjCQualifiedIdType *QIdTy, +static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, IdentifierInfo &Member, const Selector &Sel, ASTContext &Context) { // Check protocols on qualified interfaces. Decl *GDecl = 0; - for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Context, &Member)) { GDecl = PD; @@ -1988,7 +1997,7 @@ static Decl *FindGetterNameDecl(const ObjCQualifiedIdType *QIdTy, } } if (!GDecl) { - for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { // Search in the protocol-qualifier list of current protocol. GDecl = FindGetterNameDeclFromProtocolList(*I, Member, Sel, Context); @@ -2313,7 +2322,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, << &Member << BaseType); } // Handle properties on qualified "id" protocols. - const ObjCQualifiedIdType *QIdTy; + const ObjCObjectPointerType *QIdTy; if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) { // Check protocols on qualified interfaces. Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); @@ -2491,8 +2500,21 @@ Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FDecl << cast<CXXRecordDecl>(FDecl->getDeclContext())->getDeclName(); Diag(UnparsedDefaultArgLocs[FDecl->getParamDecl(i)], diag::note_default_argument_declared_here); + } else { + Expr *DefaultExpr = FDecl->getParamDecl(i)->getDefaultArg(); + + // If the default expression creates temporaries, we need to + // push them to the current stack of expression temporaries so they'll + // be properly destroyed. + if (CXXExprWithTemporaries *E + = dyn_cast_or_null<CXXExprWithTemporaries>(DefaultExpr)) { + assert(!E->shouldDestroyTemporaries() && + "Can't destroy temporaries in a default argument expr!"); + for (unsigned I = 0, N = E->getNumTemporaries(); I != N; ++I) + ExprTemporaries.push_back(E->getTemporary(I)); + } } - + // We already type-checked the argument, so we know it works. Arg = new (Context) CXXDefaultArgExpr(FDecl->getParamDecl(i)); } @@ -3395,7 +3417,7 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { // If the ArgType is a Union type, we want to handle a potential // transparent_union GCC extension. const RecordType *UT = ArgType->getAsUnionType(); - if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) + if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>(Context)) return Incompatible; // The field to initialize within the transparent union. @@ -5098,7 +5120,7 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { BSI->PrevBlockInfo = CurBlock; CurBlock = BSI; - BSI->ReturnType = 0; + BSI->ReturnType = QualType(); BSI->TheScope = BlockScope; BSI->hasBlockDeclRefExprs = false; BSI->SavedFunctionNeedsScopeChecking = CurFunctionNeedsScopeChecking; @@ -5113,7 +5135,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { if (ParamInfo.getNumTypeObjects() == 0 || ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) { - ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo); + ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); QualType T = GetTypeForDeclarator(ParamInfo, CurScope); if (T->isArrayType()) { @@ -5129,7 +5151,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { CurBlock->hasPrototype = true; CurBlock->isVariadic = false; // Check for a valid sentinel attribute on this block. - if (CurBlock->TheDecl->getAttr<SentinelAttr>()) { + if (CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) { Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. @@ -5169,7 +5191,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { CurBlock->TheDecl->setParams(Context, CurBlock->Params.data(), CurBlock->Params.size()); CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); - ProcessDeclAttributes(CurBlock->TheDecl, ParamInfo); + ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); for (BlockDecl::param_iterator AI = CurBlock->TheDecl->param_begin(), E = CurBlock->TheDecl->param_end(); AI != E; ++AI) // If this has an identifier, add it to the scope stack. @@ -5177,7 +5199,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { PushOnScopeChains(*AI, CurBlock->TheScope); // Check for a valid sentinel attribute on this block. - if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) { + if (!CurBlock->isVariadic && + CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) { Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. @@ -5192,7 +5215,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { Diag(ParamInfo.getSourceRange().getBegin(), diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; } else if (!RetTy->isDependentType()) - CurBlock->ReturnType = RetTy.getTypePtr(); + CurBlock->ReturnType = RetTy; } /// ActOnBlockError - If there is an error parsing a block, this callback @@ -5226,8 +5249,8 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, CurBlock = CurBlock->PrevBlockInfo; QualType RetTy = Context.VoidTy; - if (BSI->ReturnType) - RetTy = QualType(BSI->ReturnType, 0); + if (!BSI->ReturnType.isNull()) + RetTy = BSI->ReturnType; llvm::SmallVector<QualType, 8> ArgTypes; for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i) @@ -5241,7 +5264,7 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, BSI->isVariadic, 0); // FIXME: Check that return/parameter types are complete/non-abstract - + DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end()); BlockTy = Context.getBlockPointerType(BlockTy); // If needed, diagnose invalid gotos and switches in the block. @@ -5408,3 +5431,49 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ *Result = EvalResult.Val.getInt(); return false; } + + +/// \brief Note that the given declaration was referenced in the source code. +/// +/// This routine should be invoke whenever a given declaration is referenced +/// in the source code, and where that reference occurred. If this declaration +/// reference means that the the declaration is used (C++ [basic.def.odr]p2, +/// C99 6.9p3), then the declaration will be marked as used. +/// +/// \param Loc the location where the declaration was referenced. +/// +/// \param D the declaration that has been referenced by the source code. +void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { + assert(D && "No declaration?"); + + // Mark a parameter declaration "used", regardless of whether we're in a + // template or not. + if (isa<ParmVarDecl>(D)) + D->setUsed(true); + + // Do not mark anything as "used" within a dependent context; wait for + // an instantiation. + if (CurContext->isDependentContext()) + return; + + // If we are in an unevaluated operand, don't mark any definitions as used. + if (InUnevaluatedOperand) + return; + + // Note that this declaration has been used. + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { + // FIXME: implicit template instantiation + // FIXME: keep track of references to static functions + (void)Function; + Function->setUsed(true); + return; + } + + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + (void)Var; + // FIXME: implicit template instantiation + // FIXME: keep track of references to static data? + D->setUsed(true); + } +} + diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index ed4ac55..bec595c 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -546,7 +546,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // Do the resolution. OverloadCandidateSet::iterator Best; - switch(BestViableFunction(Candidates, Best)) { + switch(BestViableFunction(Candidates, StartLoc, Best)) { case OR_Success: { // Got one! FunctionDecl *FnDecl = Best->Function; @@ -1175,7 +1175,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, Self.AddBuiltinOperatorCandidates(OO_Conditional, Args, 2, CandidateSet); OverloadCandidateSet::iterator Best; - switch (Self.BestViableFunction(CandidateSet, Best)) { + switch (Self.BestViableFunction(CandidateSet, Loc, Best)) { case Sema::OR_Success: // We found a match. Perform the conversions on the arguments and move on. if (Self.PerformImplicitConversion(LHS, Best->BuiltinTypes.ParamTypes[0], @@ -1589,7 +1589,7 @@ Expr *Sema::RemoveOutermostTemporaryBinding(Expr *E) { } Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, - bool DestroyTemps) { + bool ShouldDestroyTemps) { assert(SubExpr && "sub expression can't be null!"); if (ExprTemporaries.empty()) @@ -1598,7 +1598,7 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr, &ExprTemporaries[0], ExprTemporaries.size(), - DestroyTemps); + ShouldDestroyTemps); ExprTemporaries.clear(); return E; @@ -1607,7 +1607,8 @@ Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { Expr *FullExpr = Arg.takeAs<Expr>(); if (FullExpr) - FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr); + FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr, + /*ShouldDestroyTemps=*/true); return Owned(FullExpr); } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index b6cf9d8..f1869f9 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -130,6 +130,14 @@ Sema::ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, SourceLocation SelLoc, SourceLocation LParenLoc, SourceLocation RParenLoc) { + ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel, + SourceRange(LParenLoc, RParenLoc)); + if (!Method) + Method = LookupFactoryMethodInGlobalPool(Sel, + SourceRange(LParenLoc, RParenLoc)); + if (!Method) + Diag(SelLoc, diag::warn_undeclared_selector) << Sel; + QualType Ty = Context.getObjCSelType(); return new (Context) ObjCSelectorExpr(Ty, Sel, AtLoc, RParenLoc); } @@ -582,9 +590,10 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // We allow sending a message to a qualified ID ("id<foo>"), which is ok as // long as one of the protocols implements the selector (if not, warn). - if (ObjCQualifiedIdType *QIdTy = dyn_cast<ObjCQualifiedIdType>(ReceiverCType)) { + if (const ObjCObjectPointerType *QIdTy = + ReceiverCType->getAsObjCQualifiedIdType()) { // Search protocols for instance methods. - for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { ObjCProtocolDecl *PDecl = *I; if (PDecl && (Method = PDecl->lookupInstanceMethod(Context, Sel))) @@ -746,8 +755,8 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, return true; } - if (const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType()) { - const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); + if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) { + const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType(); const ObjCQualifiedInterfaceType *rhsQI = 0; QualType rtype; @@ -762,7 +771,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // make sure we check the class hierarchy. if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { ObjCInterfaceDecl *rhsID = IT->getDecl(); - for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), E = lhsQID->qual_end(); I != E; ++I) { // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or @@ -775,7 +784,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, } } - ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; + ObjCObjectPointerType::qual_iterator RHSProtoI, RHSProtoE; if (rhsQI) { // We have a qualified interface (e.g. "NSObject<Proto> *"). RHSProtoI = rhsQI->qual_begin(); RHSProtoE = rhsQI->qual_end(); @@ -786,7 +795,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, return false; } - for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), E = lhsQID->qual_end(); I != E; ++I) { ObjCProtocolDecl *lhsProto = *I; bool match = false; @@ -807,7 +816,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // make sure we check the class hierarchy. if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) { ObjCInterfaceDecl *rhsID = IT->getDecl(); - for (ObjCQualifiedIdType::qual_iterator I = lhsQID->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), E = lhsQID->qual_end(); I != E; ++I) { // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or @@ -826,7 +835,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, return true; } - const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); + const ObjCObjectPointerType *rhsQID = rhs->getAsObjCQualifiedIdType(); assert(rhsQID && "One of the LHS/RHS should be id<x>"); if (!lhs->isPointerType()) @@ -835,12 +844,12 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, QualType ltype = lhs->getAsPointerType()->getPointeeType(); if (const ObjCQualifiedInterfaceType *lhsQI = ltype->getAsObjCQualifiedInterfaceType()) { - ObjCQualifiedIdType::qual_iterator LHSProtoI = lhsQI->qual_begin(); - ObjCQualifiedIdType::qual_iterator LHSProtoE = lhsQI->qual_end(); + ObjCObjectPointerType::qual_iterator LHSProtoI = lhsQI->qual_begin(); + ObjCObjectPointerType::qual_iterator LHSProtoE = lhsQI->qual_end(); for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { bool match = false; ObjCProtocolDecl *lhsProto = *LHSProtoI; - for (ObjCQualifiedIdType::qual_iterator I = rhsQID->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(), E = rhsQID->qual_end(); I != E; ++I) { ObjCProtocolDecl *rhsProto = *I; if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || @@ -859,7 +868,7 @@ bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // for static type vs. qualified 'id' type, check that class implements // all of 'id's protocols. ObjCInterfaceDecl *lhsID = IT->getDecl(); - for (ObjCQualifiedIdType::qual_iterator I = rhsQID->qual_begin(), + for (ObjCObjectPointerType::qual_iterator I = rhsQID->qual_begin(), E = rhsQID->qual_end(); I != E; ++I) { if (!ClassImplementsProtocol(*I, lhsID, compare, true)) return false; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index 1d26845..37e1df3 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -685,7 +685,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, // identifier chain. if (isa<RecordDecl>(Ctx)) { R = LookupQualifiedName(Ctx, Name, NameKind, RedeclarationOnly); - if (R || RedeclarationOnly) + if (R) return std::make_pair(true, R); } if (Ctx->getParent() != Ctx->getLexicalParent() @@ -697,7 +697,7 @@ Sema::CppLookupName(Scope *S, DeclarationName Name, for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext(); OutOfLineCtx = OutOfLineCtx->getParent()) { R = LookupQualifiedName(OutOfLineCtx, Name, NameKind, RedeclarationOnly); - if (R || RedeclarationOnly) + if (R) return std::make_pair(true, R); } } @@ -894,7 +894,7 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, continue; } - if ((*I)->getAttr<OverloadableAttr>()) { + if ((*I)->getAttr<OverloadableAttr>(Context)) { // If this declaration has the "overloadable" attribute, we // might have a set of overloaded functions. @@ -1151,8 +1151,10 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, Name, NameKind, RedeclarationOnly); } - return LookupName(S, Name, NameKind, RedeclarationOnly, - AllowBuiltinCreation, Loc); + LookupResult result(LookupName(S, Name, NameKind, RedeclarationOnly, + AllowBuiltinCreation, Loc)); + + return(result); } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 98ee13a..11cd510 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1379,7 +1379,7 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType, } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, From->getLocStart(), Best)) { case OR_Success: // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor @@ -3445,14 +3445,21 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, return false; } -/// BestViableFunction - Computes the best viable function (C++ 13.3.3) -/// within an overload candidate set. If overloading is successful, -/// the result will be OR_Success and Best will be set to point to the -/// best viable function within the candidate set. Otherwise, one of -/// several kinds of errors will be returned; see -/// Sema::OverloadingResult. +/// \brief Computes the best viable function (C++ 13.3.3) +/// within an overload candidate set. +/// +/// \param CandidateSet the set of candidate functions. +/// +/// \param Loc the location of the function name (or operator symbol) for +/// which overload resolution occurs. +/// +/// \param Best f overload resolution was successful or found a deleted +/// function, Best points to the candidate function found. +/// +/// \returns The result of overload resolution. Sema::OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, + SourceLocation Loc, OverloadCandidateSet::iterator& Best) { // Find the best viable function. @@ -3484,12 +3491,17 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, // Best is the best viable function. if (Best->Function && (Best->Function->isDeleted() || - Best->Function->getAttr<UnavailableAttr>())) + Best->Function->getAttr<UnavailableAttr>(Context))) return OR_Deleted; - // If Best refers to a function that is either deleted (C++0x) or - // unavailable (Clang extension) report an error. - + // C++ [basic.def.odr]p2: + // An overloaded function is used if it is selected by overload resolution + // when referred to from a potentially-evaluated expression. [Note: this + // covers calls to named functions (5.2.2), operator overloading + // (clause 13), user-defined conversions (12.3.2), allocation function for + // placement new (5.3.4), as well as non-default initialization (8.5). + if (Best->Function) + MarkDeclarationReferenced(Loc, Best->Function); return OR_Success; } @@ -3506,7 +3518,7 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, if (Cand->Viable || !OnlyViable) { if (Cand->Function) { if (Cand->Function->isDeleted() || - Cand->Function->getAttr<UnavailableAttr>()) { + Cand->Function->getAttr<UnavailableAttr>(Context)) { // Deleted or "unavailable" function. Diag(Cand->Function->getLocation(), diag::err_ovl_candidate_deleted) << Cand->Function->isDeleted(); @@ -3709,7 +3721,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, CandidateSet); OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { case OR_Success: return Best->Function; @@ -3815,7 +3827,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -3968,7 +3980,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: { // We found a built-in operator or an overloaded operator. FunctionDecl *FnDecl = Best->Function; @@ -4094,7 +4106,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); break; @@ -4219,7 +4231,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, Object->getLocStart(), Best)) { case OR_Success: // Overload resolution succeeded; we'll build the appropriate call // below. @@ -4388,7 +4400,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, // Perform overload resolution. OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Best)) { + switch (BestViableFunction(CandidateSet, OpLoc, Best)) { case OR_Success: // Overload resolution succeeded; we'll build the call below. break; diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index aa9b8db..914839c 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -84,7 +84,7 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, SourceLocation Loc; SourceRange R1, R2; - if (!E->isUnusedResultAWarning(Loc, R1, R2)) + if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) continue; Diag(Loc, diag::warn_unused_expr) << R1 << R2; @@ -748,18 +748,25 @@ Action::OwningStmtResult Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // If this is the first return we've seen in the block, infer the type of // the block from it. - if (CurBlock->ReturnType == 0) { + if (CurBlock->ReturnType.isNull()) { if (RetValExp) { // Don't call UsualUnaryConversions(), since we don't want to do // integer promotions here. DefaultFunctionArrayConversion(RetValExp); - CurBlock->ReturnType = RetValExp->getType().getTypePtr(); + CurBlock->ReturnType = RetValExp->getType(); + if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { + // We have to remove a 'const' added to copied-in variable which was + // part of the implementation spec. and not the actual qualifier for + // the variable. + if (CDRE->isConstQualAdded()) + CurBlock->ReturnType.removeConst(); + } } else - CurBlock->ReturnType = Context.VoidTy.getTypePtr(); + CurBlock->ReturnType = Context.VoidTy; } - QualType FnRetType = QualType(CurBlock->ReturnType, 0); + QualType FnRetType = CurBlock->ReturnType; - if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) { + if (CurBlock->TheDecl->hasAttr<NoReturnAttr>(Context)) { Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr) << getCurFunctionOrMethodDecl()->getDeclName(); return StmtError(); @@ -835,7 +842,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, FullExprArg rex) { QualType FnRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getResultType(); - if (FD->hasAttr<NoReturnAttr>()) + if (FD->hasAttr<NoReturnAttr>(Context)) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << getCurFunctionOrMethodDecl()->getDeclName(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index b2a82ed..fb41b2b 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -444,6 +444,9 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, if (Previous.begin() != Previous.end()) PrevDecl = *Previous.begin(); + if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) + PrevDecl = 0; + DeclContext *SemanticContext = CurContext; if (SS.isNotEmpty() && !SS.isInvalid()) { SemanticContext = computeDeclContext(SS); @@ -548,7 +551,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, NewClass->startDefinition(); if (Attr) - ProcessDeclAttributeList(NewClass, Attr); + ProcessDeclAttributeList(S, NewClass, Attr); PushOnScopeChains(NewTemplate, S); @@ -806,6 +809,10 @@ static void CanonicalizeTemplateArguments(const TemplateArgument *TemplateArgs, Canonical.push_back(TemplateArgument(SourceLocation(), CanonType)); break; } + + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; } } } @@ -846,7 +853,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, ConvertedTemplateArgs)) return QualType(); - assert((ConvertedTemplateArgs.size() == + assert((ConvertedTemplateArgs.structuredSize() == Template->getTemplateParameters()->size()) && "Converted template argument list is too short!"); @@ -1207,6 +1214,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr); Diag((*Param)->getLocation(), diag::note_template_param_here); Invalid = true; + break; + + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; } } else { // Check template template parameters. @@ -1251,6 +1263,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, case TemplateArgument::Integral: assert(false && "Integral argument with template template parameter"); break; + + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; } } } @@ -2288,7 +2304,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, RAngleLoc, ConvertedTemplateArgs)) return true; - assert((ConvertedTemplateArgs.size() == + assert((ConvertedTemplateArgs.structuredSize() == ClassTemplate->getTemplateParameters()->size()) && "Converted template argument list is too short!"); @@ -2549,7 +2565,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, RAngleLoc, ConvertedTemplateArgs)) return true; - assert((ConvertedTemplateArgs.size() == + assert((ConvertedTemplateArgs.structuredSize() == ClassTemplate->getTemplateParameters()->size()) && "Converted template argument list is too short!"); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 84d802d..784e451 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -46,16 +46,22 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) { static Sema::TemplateDeductionResult DeduceNonTypeTemplateArgument(ASTContext &Context, NonTypeTemplateParmDecl *NTTP, - llvm::APInt Value, + llvm::APSInt Value, Sema::TemplateDeductionInfo &Info, llvm::SmallVectorImpl<TemplateArgument> &Deduced) { assert(NTTP->getDepth() == 0 && "Cannot deduce non-type template argument with depth > 0"); if (Deduced[NTTP->getIndex()].isNull()) { - Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), - llvm::APSInt(Value), - NTTP->getType()); + QualType T = NTTP->getType(); + + // FIXME: Make sure we didn't overflow our data type! + unsigned AllowedBits = Context.getTypeSize(T); + if (Value.getBitWidth() != AllowedBits) + Value.extOrTrunc(AllowedBits); + Value.setIsSigned(T->isSignedIntegerType()); + + Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), Value, T); return Sema::TDK_Success; } @@ -64,18 +70,14 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, // If the template argument was previously deduced to a negative value, // then our deduction fails. const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral(); - if (PrevValuePtr->isSigned() && PrevValuePtr->isNegative()) { - // FIXME: This is wacky; we should be dealing with APSInts and - // checking the actual signs. + if (PrevValuePtr->isNegative()) { Info.Param = NTTP; Info.FirstArg = Deduced[NTTP->getIndex()]; - Info.SecondArg = TemplateArgument(SourceLocation(), - llvm::APSInt(Value), - NTTP->getType()); + Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType()); return Sema::TDK_Inconsistent; } - llvm::APInt PrevValue = *PrevValuePtr; + llvm::APSInt PrevValue = *PrevValuePtr; if (Value.getBitWidth() > PrevValue.getBitWidth()) PrevValue.zext(Value.getBitWidth()); else if (Value.getBitWidth() < PrevValue.getBitWidth()) @@ -84,9 +86,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, if (Value != PrevValue) { Info.Param = NTTP; Info.FirstArg = Deduced[NTTP->getIndex()]; - Info.SecondArg = TemplateArgument(SourceLocation(), - llvm::APSInt(Value), - NTTP->getType()); + Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType()); return Sema::TDK_Inconsistent; } @@ -329,10 +329,11 @@ DeduceTemplateArguments(ASTContext &Context, assert(NTTP->getDepth() == 0 && "Cannot deduce non-type template argument at depth > 0"); if (const ConstantArrayType *ConstantArrayArg - = dyn_cast<ConstantArrayType>(ArrayArg)) - return DeduceNonTypeTemplateArgument(Context, NTTP, - ConstantArrayArg->getSize(), + = dyn_cast<ConstantArrayType>(ArrayArg)) { + llvm::APSInt Size(ConstantArrayArg->getSize()); + return DeduceNonTypeTemplateArgument(Context, NTTP, Size, Info, Deduced); + } if (const DependentSizedArrayType *DependentArrayArg = dyn_cast<DependentSizedArrayType>(ArrayArg)) return DeduceNonTypeTemplateArgument(Context, NTTP, @@ -597,6 +598,9 @@ DeduceTemplateArguments(ASTContext &Context, // Can't deduce anything, but that's okay. return Sema::TDK_Success; } + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; } return Sema::TDK_Success; @@ -674,35 +678,6 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, /*FlattenArgs=*/true); Info.reset(DeducedArgumentList); - // Now that we have all of the deduced template arguments, take - // another pass through them to convert any integral template - // arguments to the appropriate type. - for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { - TemplateArgument &Arg = Deduced[I]; - if (Arg.getKind() == TemplateArgument::Integral) { - const NonTypeTemplateParmDecl *Parm - = cast<NonTypeTemplateParmDecl>(Partial->getTemplateParameters() - ->getParam(I)); - QualType T = InstantiateType(Parm->getType(), *DeducedArgumentList, - Parm->getLocation(), Parm->getDeclName()); - if (T.isNull()) { - Info.Param = const_cast<NonTypeTemplateParmDecl*>(Parm); - Info.FirstArg = TemplateArgument(Parm->getLocation(), Parm->getType()); - return TDK_SubstitutionFailure; - } - - // FIXME: Make sure we didn't overflow our data type! - llvm::APSInt &Value = *Arg.getAsIntegral(); - unsigned AllowedBits = Context.getTypeSize(T); - if (Value.getBitWidth() != AllowedBits) - Value.extOrTrunc(AllowedBits); - Value.setIsSigned(T->isSignedIntegerType()); - Arg.setIntegralType(T); - } - - (*DeducedArgumentList)[I] = Arg; - } - // Substitute the deduced template arguments into the template // arguments of the class template partial specialization, and // verify that the instantiated template arguments are both valid @@ -750,12 +725,13 @@ MarkDeducedTemplateParameters(Sema &SemaRef, /// \brief Mark the template arguments that are deduced by the given /// expression. static void -MarkDeducedTemplateParameters(Expr *E, llvm::SmallVectorImpl<bool> &Deduced) { - DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); +MarkDeducedTemplateParameters(const Expr *E, + llvm::SmallVectorImpl<bool> &Deduced) { + const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); if (!E) return; - NonTypeTemplateParmDecl *NTTP + const NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl()); if (!NTTP) return; @@ -776,26 +752,26 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, switch (T->getTypeClass()) { case Type::ExtQual: MarkDeducedTemplateParameters(SemaRef, - QualType(cast<ExtQualType>(T.getTypePtr())->getBaseType(), 0), + QualType(cast<ExtQualType>(T)->getBaseType(), 0), Deduced); break; case Type::Pointer: MarkDeducedTemplateParameters(SemaRef, - cast<PointerType>(T.getTypePtr())->getPointeeType(), + cast<PointerType>(T)->getPointeeType(), Deduced); break; case Type::BlockPointer: MarkDeducedTemplateParameters(SemaRef, - cast<BlockPointerType>(T.getTypePtr())->getPointeeType(), + cast<BlockPointerType>(T)->getPointeeType(), Deduced); break; case Type::LValueReference: case Type::RValueReference: MarkDeducedTemplateParameters(SemaRef, - cast<ReferenceType>(T.getTypePtr())->getPointeeType(), + cast<ReferenceType>(T)->getPointeeType(), Deduced); break; @@ -808,27 +784,34 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, } case Type::DependentSizedArray: - MarkDeducedTemplateParameters( - cast<DependentSizedArrayType>(T.getTypePtr())->getSizeExpr(), + MarkDeducedTemplateParameters(cast<DependentSizedArrayType>(T)->getSizeExpr(), Deduced); // Fall through to check the element type case Type::ConstantArray: case Type::IncompleteArray: MarkDeducedTemplateParameters(SemaRef, - cast<ArrayType>(T.getTypePtr())->getElementType(), + cast<ArrayType>(T)->getElementType(), Deduced); break; case Type::Vector: case Type::ExtVector: MarkDeducedTemplateParameters(SemaRef, - cast<VectorType>(T.getTypePtr())->getElementType(), + cast<VectorType>(T)->getElementType(), Deduced); break; + case Type::DependentSizedExtVector: { + const DependentSizedExtVectorType *VecType + = cast<DependentSizedExtVectorType>(T); + MarkDeducedTemplateParameters(SemaRef, VecType->getElementType(), Deduced); + MarkDeducedTemplateParameters(VecType->getSizeExpr(), Deduced); + break; + } + case Type::FunctionProto: { - const FunctionProtoType *Proto = cast<FunctionProtoType>(T.getTypePtr()); + const FunctionProtoType *Proto = cast<FunctionProtoType>(T); MarkDeducedTemplateParameters(SemaRef, Proto->getResultType(), Deduced); for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I) MarkDeducedTemplateParameters(SemaRef, Proto->getArgType(I), Deduced); @@ -836,12 +819,12 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, } case Type::TemplateTypeParm: - Deduced[cast<TemplateTypeParmType>(T.getTypePtr())->getIndex()] = true; + Deduced[cast<TemplateTypeParmType>(T)->getIndex()] = true; break; case Type::TemplateSpecialization: { const TemplateSpecializationType *Spec - = cast<TemplateSpecializationType>(T.getTypePtr()); + = cast<TemplateSpecializationType>(T); if (TemplateDecl *Template = Spec->getTemplateName().getAsTemplateDecl()) if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) @@ -864,7 +847,7 @@ MarkDeducedTemplateParameters(Sema &SemaRef, QualType T, case Type::Typename: case Type::ObjCInterface: case Type::ObjCQualifiedInterface: - case Type::ObjCQualifiedId: + case Type::ObjCObjectPointer: #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) #define DEPENDENT_TYPE(Class, Base) @@ -898,6 +881,9 @@ MarkDeducedTemplateParameters(Sema &SemaRef, case TemplateArgument::Expression: MarkDeducedTemplateParameters(TemplateArg.getAsExpr(), Deduced); break; + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; } } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 18b2d75a..3992f8c 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -431,6 +431,32 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T, } QualType +TemplateTypeInstantiator:: +InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T, + unsigned Quals) const { + + // Instantiate the element type if needed. + QualType ElementType = T->getElementType(); + if (ElementType->isDependentType()) { + ElementType = Instantiate(ElementType); + if (ElementType.isNull()) + return QualType(); + } + + // Instantiate the size expression. + const Expr *SizeExpr = T->getSizeExpr(); + Sema::OwningExprResult InstantiatedArraySize = + SemaRef.InstantiateExpr(const_cast<Expr *>(SizeExpr), TemplateArgs); + if (InstantiatedArraySize.isInvalid()) + return QualType(); + + return SemaRef.BuildExtVectorType(ElementType, + SemaRef.Owned( + InstantiatedArraySize.takeAs<Expr>()), + T->getAttributeLoc()); +} + +QualType TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T, unsigned Quals) const { // FIXME: Implement this @@ -564,6 +590,7 @@ InstantiateTemplateTypeParmType(const TemplateTypeParmType *T, // parameter with the template "level" reduced by one. return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1, T->getIndex(), + T->isParameterPack(), T->getName()) .getQualifiedType(Quals); } @@ -630,24 +657,24 @@ InstantiateTypenameType(const TypenameType *T, unsigned Quals) const { QualType TemplateTypeInstantiator:: -InstantiateObjCInterfaceType(const ObjCInterfaceType *T, - unsigned Quals) const { +InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T, + unsigned Quals) const { assert(false && "Objective-C types cannot be dependent"); return QualType(); } -QualType +QualType TemplateTypeInstantiator:: -InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T, - unsigned Quals) const { +InstantiateObjCInterfaceType(const ObjCInterfaceType *T, + unsigned Quals) const { assert(false && "Objective-C types cannot be dependent"); return QualType(); } QualType TemplateTypeInstantiator:: -InstantiateObjCQualifiedIdType(const ObjCQualifiedIdType *T, - unsigned Quals) const { +InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T, + unsigned Quals) const { assert(false && "Objective-C types cannot be dependent"); return QualType(); } @@ -1153,6 +1180,10 @@ TemplateArgument Sema::Instantiate(TemplateArgument Arg, return TemplateArgument(); return TemplateArgument(E.takeAs<Expr>()); } + + case TemplateArgument::Pack: + assert(0 && "FIXME: Implement!"); + break; } assert(false && "Unhandled template argument kind"); diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 3c67f2a..bf19701 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -1165,7 +1165,10 @@ TemplateExprInstantiator::VisitCXXExprWithTemporaries( if (SubExpr.isInvalid()) return SemaRef.ExprError(); - return SemaRef.ActOnFinishFullExpr(move(SubExpr)); + Expr *Temp = + SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(), + E->shouldDestroyTemporaries()); + return SemaRef.Owned(Temp); } Sema::OwningExprResult diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 70a9270..967f650 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -543,6 +543,48 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, return T; } + +/// \brief Build an ext-vector type. +/// +/// Run the required checks for the extended vector type. +QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize, + SourceLocation AttrLoc) { + + Expr *Arg = (Expr *)ArraySize.get(); + + // unlike gcc's vector_size attribute, we do not allow vectors to be defined + // in conjunction with complex types (pointers, arrays, functions, etc.). + if (!T->isDependentType() && + !T->isIntegerType() && !T->isRealFloatingType()) { + Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T; + return QualType(); + } + + if (!Arg->isTypeDependent() && !Arg->isValueDependent()) { + llvm::APSInt vecSize(32); + if (!Arg->isIntegerConstantExpr(vecSize, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_not_int) + << "ext_vector_type" << Arg->getSourceRange(); + return QualType(); + } + + // unlike gcc's vector_size attribute, the size is specified as the + // number of elements, not the number of bytes. + unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue()); + + if (vectorSize == 0) { + Diag(AttrLoc, diag::err_attribute_zero_size) + << Arg->getSourceRange(); + return QualType(); + } + + if (!T->isDependentType()) + return Context.getExtVectorType(T, vectorSize); + } + + return Context.getDependentSizedExtVectorType(T, ArraySize.takeAs<Expr>(), + AttrLoc); +} /// \brief Build a function type. /// |