diff options
25 files changed, 3150 insertions, 2992 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ef4fc47..0dbc819 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -612,6 +612,7 @@ public: /// void addExternalSource(ExternalSemaSource *E); + /// Print out statistics about the semantic analysis. void PrintStats() const; /// Warn that the stack is nearly exhausted. @@ -657,6 +658,10 @@ public: /// in deferred diagnostics. bool hasUncompilableErrorOccurred() const; + /// Looks through the macro-expansion chain for the given + /// location, looking for a macro expansion with the given name. + /// If one is found, returns true and sets the location to that + /// expansion loc. bool findMacroSpelling(SourceLocation &loc, StringRef name); /// Calls \c Lexer::getLocForEndOfToken() @@ -687,10 +692,27 @@ public: Private }; + /// This is called before the very first declaration in the translation unit + /// is parsed. Note that the ASTContext may have already injected some + /// declarations. void ActOnStartOfTranslationUnit(); + /// ActOnEndOfTranslationUnit - This is called at the very end of the + /// translation unit when EOF is reached and all but the top-level scope is + /// popped. void ActOnEndOfTranslationUnit(); void ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind); + /// Determines the active Scope associated with the given declaration + /// context. + /// + /// This routine maps a declaration context to the active Scope object that + /// represents that declaration context in the parser. It is typically used + /// from "scope-less" code (e.g., template instantiation, lazy creation of + /// declarations) that injects a name for name-lookup purposes and, therefore, + /// must update the Scope. + /// + /// \returns The scope corresponding to the given declaraion context, or NULL + /// if no such scope is open. Scope *getScopeForContext(DeclContext *Ctx); void PushFunctionScope(); @@ -719,6 +741,14 @@ public: using PoppedFunctionScopePtr = std::unique_ptr<sema::FunctionScopeInfo, PoppedFunctionScopeDeleter>; + /// Pop a function (or block or lambda or captured region) scope from the + /// stack. + /// + /// \param WP The warning policy to use for CFG-based warnings, or null if + /// such warnings should not be produced. + /// \param D The declaration corresponding to this function scope, if + /// producing CFG-based warnings. + /// \param BlockType The type of the block expression, if D is a BlockDecl. PoppedFunctionScopePtr PopFunctionScopeInfo(const sema::AnalysisBasedWarnings::Policy *WP = nullptr, const Decl *D = nullptr, @@ -734,6 +764,8 @@ public: void PushCompoundScope(bool IsStmtExpr); void PopCompoundScope(); + /// Determine whether any errors occurred within this function/method/ + /// block. bool hasAnyUnrecoverableErrorsInThisFunction() const; /// Retrieve the current block, if any. @@ -851,6 +883,8 @@ public: const FunctionEffectWithCondition &EC, SourceLocation NewAttrLoc); + // Report a failure to merge function effects between declarations due to a + // conflict. void diagnoseFunctionEffectMergeConflicts(const FunctionEffectSet::Conflicts &Errs, SourceLocation NewLoc, @@ -862,6 +896,10 @@ public: std::optional<FunctionEffectMode> ActOnEffectExpression(Expr *CondExpr, StringRef AttributeName); + /// makeUnavailableInSystemHeader - There is an error in the current + /// context. If we're still in a system header, and we can plausibly + /// make the relevant declaration unavailable instead of erroring, do + /// so and return true. bool makeUnavailableInSystemHeader(SourceLocation loc, UnavailableAttr::ImplicitReason reason); @@ -937,6 +975,17 @@ public: bool (*IsPlausibleResult)(QualType) = nullptr); /// Figure out if an expression could be turned into a call. + /// + /// Use this when trying to recover from an error where the programmer may + /// have written just the name of a function instead of actually calling it. + /// + /// \param E - The expression to examine. + /// \param ZeroArgCallReturnTy - If the expression can be turned into a call + /// with no arguments, this parameter is set to the type returned by such a + /// call; otherwise, it is set to an empty QualType. + /// \param OverloadSet - If the expression is an overloaded function + /// name, this parameter is populated with the decls of the various + /// overloads. bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, UnresolvedSetImpl &NonTemplateOverloads); @@ -1287,23 +1336,34 @@ public: AR_delayed }; + /// SetMemberAccessSpecifier - Set the access specifier of a member. + /// Returns true on error (when the previous member decl access specifier + /// is different from the new member decl access specifier). bool SetMemberAccessSpecifier(NamedDecl *MemberDecl, NamedDecl *PrevMemberDecl, AccessSpecifier LexicalAS); + /// Perform access-control checking on a previously-unresolved member + /// access which has now been resolved to a member. AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, DeclAccessPair FoundDecl); AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, DeclAccessPair FoundDecl); + + /// Checks access to an overloaded operator new or delete. AccessResult CheckAllocationAccess(SourceLocation OperatorLoc, SourceRange PlacementRange, CXXRecordDecl *NamingClass, DeclAccessPair FoundDecl, bool Diagnose = true); + + /// Checks access to a constructor. AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, DeclAccessPair FoundDecl, const InitializedEntity &Entity, bool IsCopyBindingRefToTemp = false); + + /// Checks access to a constructor. AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, DeclAccessPair FoundDecl, const InitializedEntity &Entity, @@ -1312,10 +1372,16 @@ public: CXXDestructorDecl *Dtor, const PartialDiagnostic &PDiag, QualType objectType = QualType()); + + /// Checks access to the target of a friend declaration. AccessResult CheckFriendAccess(NamedDecl *D); + + /// Checks access to a member. AccessResult CheckMemberAccess(SourceLocation UseLoc, CXXRecordDecl *NamingClass, DeclAccessPair Found); + + /// Checks implicit access to a member in a structured binding. AccessResult CheckStructuredBindingMemberAccess(SourceLocation UseLoc, CXXRecordDecl *DecomposedClass, @@ -1323,6 +1389,9 @@ public: AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, const SourceRange &, DeclAccessPair FoundDecl); + + /// Checks access to an overloaded member operator, including + /// conversion operators. AccessResult CheckMemberOperatorAccess(SourceLocation Loc, Expr *ObjectExpr, Expr *ArgExpr, DeclAccessPair FoundDecl); @@ -1331,13 +1400,43 @@ public: DeclAccessPair FoundDecl); AccessResult CheckAddressOfMemberAccess(Expr *OvlExpr, DeclAccessPair FoundDecl); + + /// Checks access for a hierarchy conversion. + /// + /// \param ForceCheck true if this check should be performed even if access + /// control is disabled; some things rely on this for semantics + /// \param ForceUnprivileged true if this check should proceed as if the + /// context had no special privileges AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck = false, bool ForceUnprivileged = false); + + /// Checks access to all the declarations in the given result set. void CheckLookupAccess(const LookupResult &R); + + /// Checks access to Target from the given class. The check will take access + /// specifiers into account, but no member access expressions and such. + /// + /// \param Target the declaration to check if it can be accessed + /// \param NamingClass the class in which the lookup was started. + /// \param BaseType type of the left side of member access expression. + /// \p BaseType and \p NamingClass are used for C++ access control. + /// Depending on the lookup case, they should be set to the following: + /// - lhs.target (member access without a qualifier): + /// \p BaseType and \p NamingClass are both the type of 'lhs'. + /// - lhs.X::target (member access with a qualifier): + /// BaseType is the type of 'lhs', NamingClass is 'X' + /// - X::target (qualified lookup without member access): + /// BaseType is null, NamingClass is 'X'. + /// - target (unqualified lookup). + /// BaseType is null, NamingClass is the parent class of 'target'. + /// \return true if the Target is accessible from the Class, false otherwise. bool IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *NamingClass, QualType BaseType); + + /// Is the given member accessible for the purposes of deciding whether to + /// define a special member function as deleted? bool isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, DeclAccessPair Found, QualType ObjectType, SourceLocation Loc, @@ -2089,11 +2188,17 @@ public: FormatArgumentPassingKind ArgPassingKind; }; + /// Given a FunctionDecl's FormatAttr, attempts to populate the + /// FomatStringInfo parameter with the FormatAttr's correct format_idx and + /// firstDataArg. Returns true when the format fits the function and the + /// FormatStringInfo has been populated. static bool getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, bool IsVariadic, FormatStringInfo *FSI); // Used by C++ template instantiation. ExprResult BuiltinShuffleVector(CallExpr *TheCall); + + /// ConvertVectorExpr - Handle __builtin_convertvector ExprResult ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, SourceLocation BuiltinLoc, SourceLocation RParenLoc); @@ -2114,6 +2219,9 @@ public: bool FormatStringHasSArg(const StringLiteral *FExpr); + /// Check for comparisons of floating-point values using == and !=. Issue a + /// warning if the comparison is not likely to do what the programmer + /// intended. void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS, BinaryOperatorKind Opcode); @@ -2173,13 +2281,26 @@ public: /// Check to see if a given expression could have '.c_str()' called on it. bool hasCStrMethod(const Expr *E); + /// Diagnose pointers that are always non-null. + /// \param E the expression containing the pointer + /// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is + /// compared to a null pointer + /// \param IsEqual True when the comparison is equal to a null pointer + /// \param Range Extra SourceRange to highlight in the diagnostic void DiagnoseAlwaysNonNullPointer(Expr *E, Expr::NullPointerConstantKind NullType, bool IsEqual, SourceRange Range); + /// CheckParmsForFunctionDef - Check that the parameters of the given + /// function are appropriate for the definition of a function. This + /// takes care of any checks that cannot be performed on the + /// declaration itself, e.g., that the types of each of the function + /// parameters are complete. bool CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters, bool CheckParameterNames); + /// CheckCastAlign - Implements -Wcast-align, which warns when a + /// pointer cast increases the alignment requirements. void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); /// checkUnsafeAssigns - Check whether +1 expr is being assigned @@ -2203,7 +2324,7 @@ public: /// \p PossibleBody, has a suspicious null statement as a body. void DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody); - /// Warn if a value is moved to itself. + /// DiagnoseSelfMove - Emits a warning if a value is moved to itself. void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation OpLoc); @@ -2220,39 +2341,87 @@ public: bool IsPointerInterconvertibleBaseOf(const TypeSourceInfo *Base, const TypeSourceInfo *Derived); + /// CheckFunctionCall - Check a direct function call for various correctness + /// and safety properties not strictly enforced by the C type system. bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, const FunctionProtoType *Proto); bool BuiltinVectorMath(CallExpr *TheCall, QualType &Res); bool BuiltinVectorToScalarMath(CallExpr *TheCall); + /// Handles the checks for format strings, non-POD arguments to vararg + /// functions, NULL arguments passed to non-NULL parameters, diagnose_if + /// attributes and AArch64 SME attributes. void checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, const Expr *ThisArg, ArrayRef<const Expr *> Args, bool IsMemberFunction, SourceLocation Loc, SourceRange Range, VariadicCallType CallType); + /// \brief Enforce the bounds of a TCB + /// CheckTCBEnforcement - Enforces that every function in a named TCB only + /// directly calls other functions in the same TCB as marked by the + /// enforce_tcb and enforce_tcb_leaf attributes. void CheckTCBEnforcement(const SourceLocation CallExprLoc, const NamedDecl *Callee); void CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc); + /// BuiltinConstantArg - Handle a check if argument ArgNum of CallExpr + /// TheCall is a constant expression. bool BuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); + + /// BuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr + /// TheCall is a constant expression in the range [Low, High]. bool BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError = true); + + /// BuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr + /// TheCall is a constant expression is a multiple of Num.. bool BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Multiple); + + /// BuiltinConstantArgPower2 - Check if argument ArgNum of TheCall is a + /// constant expression representing a power of 2. bool BuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum); + + /// BuiltinConstantArgShiftedByte - Check if argument ArgNum of TheCall is + /// a constant expression representing an arbitrary byte value shifted left by + /// a multiple of 8 bits. bool BuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum, unsigned ArgBits); + + /// BuiltinConstantArgShiftedByteOr0xFF - Check if argument ArgNum of + /// TheCall is a constant expression representing either a shifted byte value, + /// or a value of the form 0x??FF (i.e. a member of the arithmetic progression + /// 0x00FF, 0x01FF, ..., 0xFFFF). This strange range check is needed for some + /// Arm MVE intrinsics. bool BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, unsigned ArgBits); + /// Checks that a call expression's argument count is at least the desired + /// number. This is useful when doing custom type-checking on a variadic + /// function. Returns true on error. bool checkArgCountAtLeast(CallExpr *Call, unsigned MinArgCount); + + /// Checks that a call expression's argument count is at most the desired + /// number. This is useful when doing custom type-checking on a variadic + /// function. Returns true on error. bool checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount); + + /// Checks that a call expression's argument count is in the desired range. + /// This is useful when doing custom type-checking on a variadic function. + /// Returns true on error. bool checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount); + + /// Checks that a call expression's argument count is the desired number. + /// This is useful when doing custom type-checking. Returns true on error. bool checkArgCount(CallExpr *Call, unsigned DesiredArgCount); + /// Returns true if the argument consists of one contiguous run of 1s with any + /// number of 0s on either side. The 1s are allowed to wrap from LSB to MSB, + /// so 0x000FFF0, 0x0000FFFF, 0xFF0000FF, 0x0 are all runs. 0x0F0F0000 is not, + /// since all 1s are not contiguous. bool ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum); void CheckImplicitConversion(Expr *E, QualType T, SourceLocation CC, @@ -2271,11 +2440,21 @@ private: bool CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, const FunctionProtoType *Proto); + + /// Checks function calls when a FunctionDecl or a NamedDecl is not available, + /// such as function pointers returned from functions. bool CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto); + + /// CheckConstructorCall - Check a constructor call for correctness and safety + /// properties not enforced by the C type system. void CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, ArrayRef<const Expr *> Args, const FunctionProtoType *Proto, SourceLocation Loc); + /// Warn if a pointer or reference argument passed to a function points to an + /// object that is less aligned than the parameter. This can happen when + /// creating a typedef with a lower alignment than the original type and then + /// calling functions defined in terms of the original type. void CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl, StringRef ParamName, QualType ArgTy, QualType ParamTy); @@ -2289,22 +2468,72 @@ private: void checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, CallExpr *TheCall); + /// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' + /// for validity. Emit an error and return true on failure; return false + /// on success. bool BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall); bool BuiltinVAStartARMMicrosoft(CallExpr *Call); + + /// BuiltinUnorderedCompare - Handle functions like __builtin_isgreater and + /// friends. This is declared to take (...), so we have to check everything. bool BuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID); + + /// BuiltinSemaBuiltinFPClassification - Handle functions like + /// __builtin_isnan and friends. This is declared to take (...), so we have + /// to check everything. bool BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, unsigned BuiltinID); + + /// Perform semantic analysis for a call to __builtin_complex. bool BuiltinComplex(CallExpr *TheCall); bool BuiltinOSLogFormat(CallExpr *TheCall); + /// BuiltinPrefetch - Handle __builtin_prefetch. + /// This is declared to take (const void*, ...) and can take two + /// optional constant int args. bool BuiltinPrefetch(CallExpr *TheCall); + + /// Handle __builtin_alloca_with_align. This is declared + /// as (size_t, size_t) where the second size_t must be a power of 2 greater + /// than 8. bool BuiltinAllocaWithAlign(CallExpr *TheCall); + + /// BuiltinArithmeticFence - Handle __arithmetic_fence. bool BuiltinArithmeticFence(CallExpr *TheCall); + + /// BuiltinAssume - Handle __assume (MS Extension). + /// __assume does not evaluate its arguments, and should warn if its argument + /// has side effects. bool BuiltinAssume(CallExpr *TheCall); + + /// Handle __builtin_assume_aligned. This is declared + /// as (const void*, size_t, ...) and can take one optional constant int arg. bool BuiltinAssumeAligned(CallExpr *TheCall); + + /// BuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). + /// This checks that the target supports __builtin_longjmp and + /// that val is a constant 1. bool BuiltinLongjmp(CallExpr *TheCall); + + /// BuiltinSetjmp - Handle __builtin_setjmp(void *env[5]). + /// This checks that the target supports __builtin_setjmp. bool BuiltinSetjmp(CallExpr *TheCall); + + /// We have a call to a function like __sync_fetch_and_add, which is an + /// overloaded function based on the pointer type of its first argument. + /// The main BuildCallExpr routines have already promoted the types of + /// arguments because all of these calls are prototyped as void(...). + /// + /// This function goes through and does final semantic checking for these + /// builtins, as well as generating any warnings. ExprResult BuiltinAtomicOverloaded(ExprResult TheCallResult); + + /// BuiltinNontemporalOverloaded - We have a call to + /// __builtin_nontemporal_store or __builtin_nontemporal_load, which is an + /// overloaded function based on the pointer type of its last argument. + /// + /// This function goes through and does final semantic checking for these + /// builtins. ExprResult BuiltinNontemporalOverloaded(ExprResult TheCallResult); ExprResult AtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op); @@ -2321,6 +2550,9 @@ private: ExprResult BuiltinMatrixColumnMajorStore(CallExpr *TheCall, ExprResult CallResult); + /// CheckFormatArguments - Check calls to printf and scanf (and similar + /// functions) for correct use of format strings. + /// Returns true if a format string has been fully checked. bool CheckFormatArguments(const FormatAttr *Format, ArrayRef<const Expr *> Args, bool IsCXXMember, VariadicCallType CallType, SourceLocation Loc, @@ -2335,18 +2567,32 @@ private: void CheckInfNaNFunction(const CallExpr *Call, const FunctionDecl *FDecl); + /// Warn when using the wrong abs() function. void CheckAbsoluteValueFunction(const CallExpr *Call, const FunctionDecl *FDecl); void CheckMaxUnsignedZero(const CallExpr *Call, const FunctionDecl *FDecl); + /// Check for dangerous or invalid arguments to memset(). + /// + /// This issues warnings on known problematic, dangerous or unspecified + /// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp' + /// function calls. + /// + /// \param Call The call expression to diagnose. void CheckMemaccessArguments(const CallExpr *Call, unsigned BId, IdentifierInfo *FnName); + // Warn if the user has made the 'size' argument to strlcpy or strlcat + // be the size of the source, instead of the destination. void CheckStrlcpycatArguments(const CallExpr *Call, IdentifierInfo *FnName); + // Warn on anti-patterns as the 'size' argument to strncat. + // The correct size argument should look like following: + // strncat(dst, src, sizeof(dst) - strlen(dest) - 1); void CheckStrncatArguments(const CallExpr *Call, IdentifierInfo *FnName); + /// Alerts the user that they are attempting to free a non-malloc'd object. void CheckFreeArguments(const CallExpr *E); void CheckReturnValExpr(Expr *RetValExp, QualType lhsType, @@ -2354,8 +2600,21 @@ private: const AttrVec *Attrs = nullptr, const FunctionDecl *FD = nullptr); + /// Diagnoses "dangerous" implicit conversions within the given + /// expression (which is a full expression). Implements -Wconversion + /// and -Wsign-compare. + /// + /// \param CC the "context" location of the implicit conversion, i.e. + /// the most location of the syntactic entity requiring the implicit + /// conversion void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); + + /// CheckBoolLikeConversion - Check conversion of given expression to boolean. + /// Input argument E is a logical expression. void CheckBoolLikeConversion(Expr *E, SourceLocation CC); + + /// Diagnose when expression is an integer constant expression and its + /// evaluation results in integer overflow void CheckForIntOverflow(const Expr *E); void CheckUnsequencedOperations(const Expr *E); @@ -2475,10 +2734,37 @@ public: bool RequireCompleteEnumDecl(EnumDecl *D, SourceLocation L, CXXScopeSpec *SS = nullptr); + /// Compute the DeclContext that is associated with the given type. + /// + /// \param T the type for which we are attempting to find a DeclContext. + /// + /// \returns the declaration context represented by the type T, + /// or NULL if the declaration context cannot be computed (e.g., because it is + /// dependent and not the current instantiation). DeclContext *computeDeclContext(QualType T); + + /// Compute the DeclContext that is associated with the given + /// scope specifier. + /// + /// \param SS the C++ scope specifier as it appears in the source + /// + /// \param EnteringContext when true, we will be entering the context of + /// this scope specifier, so we can retrieve the declaration context of a + /// class template or class template partial specialization even if it is + /// not the current instantiation. + /// + /// \returns the declaration context represented by the scope specifier @p SS, + /// or NULL if the declaration context cannot be computed (e.g., because it is + /// dependent and not the current instantiation). DeclContext *computeDeclContext(const CXXScopeSpec &SS, bool EnteringContext = false); bool isDependentScopeSpecifier(const CXXScopeSpec &SS); + + /// If the given nested name specifier refers to the current + /// instantiation, return the declaration that corresponds to that + /// current instantiation (C++0x [temp.dep.type]p1). + /// + /// \param NNS a dependent nested name specifier. CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); /// The parser has parsed a global nested-name-specifier '::'. @@ -2504,8 +2790,18 @@ public: bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc, SourceLocation ColonColonLoc, CXXScopeSpec &SS); + /// Determines whether the given declaration is an valid acceptable + /// result for name lookup of a nested-name-specifier. + /// \param SD Declaration checked for nested-name-specifier. + /// \param IsExtension If not null and the declaration is accepted as an + /// extension, the pointed variable is assigned true. bool isAcceptableNestedNameSpecifier(const NamedDecl *SD, bool *CanCorrect = nullptr); + + /// If the given nested-name-specifier begins with a bare identifier + /// (e.g., Base::), perform name lookup for that identifier as a + /// nested-name-specifier within the given scope, and return the result of + /// that name lookup. NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); /// Keeps information about an identifier in a nested-name-spec. @@ -2537,6 +2833,37 @@ public: IdentifierLoc(IdLoc), CCLoc(ColonColonLoc) {} }; + /// Build a new nested-name-specifier for "identifier::", as described + /// by ActOnCXXNestedNameSpecifier. + /// + /// \param S Scope in which the nested-name-specifier occurs. + /// \param IdInfo Parser information about an identifier in the + /// nested-name-spec. + /// \param EnteringContext If true, enter the context specified by the + /// nested-name-specifier. + /// \param SS Optional nested name specifier preceding the identifier. + /// \param ScopeLookupResult Provides the result of name lookup within the + /// scope of the nested-name-specifier that was computed at template + /// definition time. + /// \param ErrorRecoveryLookup Specifies if the method is called to improve + /// error recovery and what kind of recovery is performed. + /// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':' + /// are allowed. The bool value pointed by this parameter is set to + /// 'true' if the identifier is treated as if it was followed by ':', + /// not '::'. + /// \param OnlyNamespace If true, only considers namespaces in lookup. + /// + /// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in + /// that it contains an extra parameter \p ScopeLookupResult, which provides + /// the result of name lookup within the scope of the nested-name-specifier + /// that was computed at template definition time. + /// + /// If ErrorRecoveryLookup is true, then this call is used to improve error + /// recovery. This means that it should not emit diagnostics, it should + /// just return true on failure. It also means it should only return a valid + /// scope if it *knows* that the result is correct. It should not return in a + /// dependent context, for example. Nor will it extend \p SS with the scope + /// specifier. bool BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, NamedDecl *ScopeLookupResult, @@ -2608,6 +2935,12 @@ public: SourceLocation ColonColonLoc, QualType Type); + /// IsInvalidUnlessNestedName - This method is used for error recovery + /// purposes to determine whether the specified identifier is only valid as + /// a nested name specifier, for example a namespace name. It is + /// conservatively correct to always return false from this method. + /// + /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. bool IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, NestedNameSpecInfo &IdInfo, bool EnteringContext); @@ -2784,6 +3117,14 @@ public: DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType = nullptr); + /// If the identifier refers to a type name within this scope, + /// return the declaration of that type. + /// + /// This routine performs ordinary name lookup of the identifier II + /// within the given scope, with optional C++ scope specifier SS, to + /// determine whether the name refers to a type. If so, returns an + /// opaque pointer (actually a QualType) corresponding to that + /// type. Otherwise, returns NULL. ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS = nullptr, bool isClassName = false, bool HasTrailingDot = false, @@ -2794,7 +3135,28 @@ public: ImplicitTypenameContext AllowImplicitTypename = ImplicitTypenameContext::No, IdentifierInfo **CorrectedII = nullptr); + + /// isTagName() - This method is called *for error recovery purposes only* + /// to determine if the specified name is a valid tag name ("struct foo"). If + /// so, this returns the TST for the tag corresponding to it (TST_enum, + /// TST_union, TST_struct, TST_interface, TST_class). This is used to + /// diagnose cases in C where the user forgot to specify the tag. TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); + + /// isMicrosoftMissingTypename - In Microsoft mode, within class scope, + /// if a CXXScopeSpec's type is equal to the type of one of the base classes + /// then downgrade the missing typename error to a warning. + /// This is needed for MSVC compatibility; Example: + /// @code + /// template<class T> class A { + /// public: + /// typedef int TYPE; + /// }; + /// template<class T> class B : public A<T> { + /// public: + /// A<T>::TYPE a; // no typename required because A<T> is a base class. + /// }; + /// @endcode bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S); void DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc, Scope *S, CXXScopeSpec *SS, @@ -3047,11 +3409,47 @@ public: NamedDecl *HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists); + + /// Attempt to fold a variable-sized type to a constant-sized type, returning + /// true if we were successful. bool tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, QualType &T, SourceLocation Loc, unsigned FailedFoldDiagID); + + /// Register the given locally-scoped extern "C" declaration so + /// that it can be found later for redeclarations. We include any extern "C" + /// declaration that is not visible in the translation unit here, not just + /// function-scope declarations. void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S); + + /// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: + /// If T is the name of a class, then each of the following shall have a + /// name different from T: + /// - every static data member of class T; + /// - every member function of class T + /// - every member of class T that is itself a type; + /// \returns true if the declaration name violates these rules. bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); + + /// Diagnose a declaration whose declarator-id has the given + /// nested-name-specifier. + /// + /// \param SS The nested-name-specifier of the declarator-id. + /// + /// \param DC The declaration context to which the nested-name-specifier + /// resolves. + /// + /// \param Name The name of the entity being declared. + /// + /// \param Loc The location of the name of the entity being declared. + /// + /// \param IsMemberSpecialization Whether we are declaring a member + /// specialization. + /// + /// \param TemplateId The template-id, if any. + /// + /// \returns true if we cannot safely recover from this error, false + /// otherwise. bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, SourceLocation Loc, TemplateIdAnnotation *TemplateId, @@ -3059,20 +3457,43 @@ public: bool checkConstantPointerAuthKey(Expr *keyExpr, unsigned &key); + /// Diagnose function specifiers on a declaration of an identifier that + /// does not identify a function. void DiagnoseFunctionSpecifiers(const DeclSpec &DS); + + /// Return the declaration shadowed by the given typedef \p D, or null + /// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *getShadowedDeclaration(const TypedefNameDecl *D, const LookupResult &R); + + /// Return the declaration shadowed by the given variable \p D, or null + /// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *getShadowedDeclaration(const VarDecl *D, const LookupResult &R); + + /// Return the declaration shadowed by the given variable \p D, or null + /// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *getShadowedDeclaration(const BindingDecl *D, const LookupResult &R); + /// Diagnose variable or built-in function shadowing. Implements + /// -Wshadow. + /// + /// This method is called whenever a VarDecl is added to a "useful" + /// scope. + /// + /// \param ShadowedDecl the declaration that is shadowed by the given variable + /// \param R the lookup of the name void CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R); + + /// Check -Wshadow without the advantage of a previous lookup. void CheckShadow(Scope *S, VarDecl *D); /// Warn if 'E', which is an expression that is about to be modified, refers /// to a shadowing declaration. void CheckShadowingDeclModification(Expr *E, SourceLocation Loc); + /// Diagnose shadowing for variables shadowed in the lambda record \p LambdaRD + /// when these variables are captured by the lambda. void DiagnoseShadowingLambdaDecls(const sema::LambdaScopeInfo *LSI); void handleTagNumbering(const TagDecl *Tag, Scope *TagScope); @@ -3082,6 +3503,10 @@ public: NamedDecl *ActOnTypedefDeclarator(Scope *S, Declarator &D, DeclContext *DC, TypeSourceInfo *TInfo, LookupResult &Previous); + + /// ActOnTypedefNameDecl - Perform semantic checking for a declaration which + /// declares a typedef-name, either using the 'typedef' type specifier or via + /// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. NamedDecl *ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *D, LookupResult &Previous, bool &Redeclaration); NamedDecl *ActOnVariableDeclarator( @@ -3089,7 +3514,18 @@ public: LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &AddToScope, ArrayRef<BindingDecl *> Bindings = std::nullopt); - // Returns true if the variable declaration is a redeclaration + /// Perform semantic checking on a newly-created variable + /// declaration. + /// + /// This routine performs all of the type-checking required for a + /// variable declaration once it has been built. It is used both to + /// check variables after they have been parsed and their declarators + /// have been translated into a declaration, and to check variables + /// that have been instantiated from a template. + /// + /// Sets NewVD->isInvalidDecl() if an error was encountered. + /// + /// Returns true if the variable declaration is a redeclaration. bool CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous); void CheckVariableDeclarationType(VarDecl *NewVD); void CheckCompleteVariableDeclaration(VarDecl *VD); @@ -3099,22 +3535,78 @@ public: LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, bool &AddToScope); + + /// AddOverriddenMethods - See if a method overrides any in the base classes, + /// and if so, check that it's a valid override and remember it. bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); - // Returns true if the function declaration is a redeclaration + /// Perform semantic checking of a new function declaration. + /// + /// Performs semantic analysis of the new function declaration + /// NewFD. This routine performs all semantic checking that does not + /// require the actual declarator involved in the declaration, and is + /// used both for the declaration of functions as they are parsed + /// (called via ActOnDeclarator) and for the declaration of functions + /// that have been instantiated via C++ template instantiation (called + /// via InstantiateDecl). + /// + /// \param IsMemberSpecialization whether this new function declaration is + /// a member specialization (that replaces any definition provided by the + /// previous declaration). + /// + /// This sets NewFD->isInvalidDecl() to true if there was an error. + /// + /// \returns true if the function declaration is a redeclaration. bool CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, bool IsMemberSpecialization, bool DeclIsDefn); + + /// Checks if the new declaration declared in dependent context must be + /// put in the same redeclaration chain as the specified declaration. + /// + /// \param D Declaration that is checked. + /// \param PrevDecl Previous declaration found with proper lookup method for + /// the same declaration name. + /// \returns True if D must be added to the redeclaration chain which PrevDecl + /// belongs to. bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl); + + /// Determines if we can perform a correct type check for \p D as a + /// redeclaration of \p PrevDecl. If not, we can generally still perform a + /// best-effort check. + /// + /// \param NewD The new declaration. + /// \param OldD The old declaration. + /// \param NewT The portion of the type of the new declaration to check. + /// \param OldT The portion of the type of the old declaration to check. bool canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD, QualType NewT, QualType OldT); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); + + /// Returns an implicit CodeSegAttr if a __declspec(code_seg) is found on a + /// containing class. Otherwise it will return implicit SectionAttr if the + /// function is a definition and there is an active value on CodeSegStack + /// (from the current #pragma code-seg value). + /// + /// \param FD Function being declared. + /// \param IsDefinition Whether it is a definition or just a declaration. + /// \returns A CodeSegAttr or SectionAttr to apply to the function or + /// nullptr if no attribute should be added. Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); + + /// Common checks for a parameter-declaration that should apply to both + /// function parameters and non-type template parameters. void CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D); + + /// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() + /// to introduce parameters into function prototype scope. Decl *ActOnParamDeclarator(Scope *S, Declarator &D, SourceLocation ExplicitThisLoc = {}); + + /// Synthesizes a variable for a parameter arising from a + /// typedef. ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, @@ -3164,8 +3656,16 @@ public: NonTrivialCUnionContext UseContext, unsigned NonTrivialKind); + /// AddInitializerToDecl - Adds the initializer Init to the + /// declaration dcl. If DirectInit is true, this is C++ direct + /// initialization rather than copy initialization. void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit); void ActOnUninitializedDecl(Decl *dcl); + + /// ActOnInitializerError - Given that there was an error parsing an + /// initializer for the given declaration, try to at least re-establish + /// invariants such as whether a variable's type is either dependent or + /// complete. void ActOnInitializerError(Decl *Dcl); void ActOnCXXForRangeDecl(Decl *D); @@ -3173,11 +3673,19 @@ public: IdentifierInfo *Ident, ParsedAttributes &Attrs); + /// Check if VD needs to be dllexport/dllimport due to being in a + /// dllexport/import function. void CheckStaticLocalForDllExport(VarDecl *VD); void CheckThreadLocalForLargeAlignment(VarDecl *VD); + + /// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform + /// any semantic actions necessary after any initializer has been attached. void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, ArrayRef<Decl *> Group); + + /// BuildDeclaratorGroup - convert a list of declarations into a declaration + /// group, performing any necessary semantic checking. DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef<Decl *> Group); /// Should be called on all declarations that might have attached @@ -3234,6 +3742,18 @@ public: /// \c constexpr in C++11 or has an 'auto' return type in C++14). bool canSkipFunctionBody(Decl *D); + /// Given the set of return statements within a function body, + /// compute the variables that are subject to the named return value + /// optimization. + /// + /// Each of the variables that is subject to the named return value + /// optimization will be marked as NRVO variables in the AST, and any + /// return statement that has a marked NRVO variable as its NRVO candidate can + /// use the named return value optimization. + /// + /// This function applies a very simplistic algorithm for NRVO: if every + /// return statement in the scope of a variable has the same NRVO candidate, + /// that candidate is an NRVO variable. void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); @@ -3263,15 +3783,25 @@ public: void ActOnPopScope(SourceLocation Loc, Scope *S); + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with + /// no declarator (e.g. "struct foo;") is parsed. Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, const ParsedAttributesView &DeclAttrs, RecordDecl *&AnonRecord); + + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with + /// no declarator (e.g. "struct foo;") is parsed. It also accepts template + /// parameters to cope with template friend declarations. Decl *ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, const ParsedAttributesView &DeclAttrs, MultiTemplateParamsArg TemplateParams, bool IsExplicitInstantiation, RecordDecl *&AnonRecord); + /// BuildAnonymousStructOrUnion - Handle the declaration of an + /// anonymous structure or union. Anonymous unions are a C++ feature + /// (C++ [class.union]) and a C11 feature; anonymous structures + /// are a C11 feature and GNU C++ extension. Decl *BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, RecordDecl *Record, const PrintingPolicy &Policy); @@ -3280,8 +3810,24 @@ public: /// a tag declaration is an anonymous union or struct. void ActOnDefinedDeclarationSpecifier(Decl *D); + /// Emit diagnostic warnings for placeholder members. + /// We can only do that after the class is fully constructed, + /// as anonymous union/structs can insert placeholders + /// in their parent scope (which might be a Record). void DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record); + /// BuildMicrosoftCAnonymousStruct - Handle the declaration of an + /// Microsoft C anonymous structure. + /// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx + /// Example: + /// + /// struct A { int a; }; + /// struct B { struct A; int b; }; + /// + /// void foo() { + /// B var; + /// var.a = 3; + /// } Decl *BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, RecordDecl *Record); @@ -3303,6 +3849,10 @@ public: /// what kind of non-tag type this is. NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK); + /// Determine whether a tag with a given kind is acceptable + /// as a redeclaration of the given tag declaration. + /// + /// \returns true if the new tag kind is acceptable, false otherwise. bool isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag, bool isDefinition, SourceLocation NewTagLoc, const IdentifierInfo *Name); @@ -3317,6 +3867,16 @@ public: OOK_Macro, }; + /// This is invoked when we see 'struct foo' or 'struct {'. In the + /// former case, Name will be non-null. In the later case, Name will be null. + /// TagSpec indicates what kind of tag this is. TUK indicates whether this is + /// a reference/declaration/definition of a tag. + /// + /// \param IsTypeSpecifier \c true if this is a type-specifier (or + /// trailing-type-specifier) other than one in an alias-declaration. + /// + /// \param SkipBody If non-null, will be set to indicate if the caller should + /// skip the definition of this tag and treat it as if it were a declaration. DeclResult ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -3329,13 +3889,26 @@ public: bool IsTypeSpecifier, bool IsTemplateParamOrArg, OffsetOfKind OOK, SkipBodyInfo *SkipBody = nullptr); + /// ActOnField - Each field of a C struct/union is passed into this in order + /// to create a FieldDecl object for it. Decl *ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth); + /// HandleField - Analyze a field of a C struct or a C++ data member. FieldDecl *HandleField(Scope *S, RecordDecl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS); + /// Build a new FieldDecl and check its well-formedness. + /// + /// This routine builds a new FieldDecl given the fields name, type, + /// record, etc. \p PrevDecl should refer to any previous declaration + /// with the same name and in the same scope as the field to be + /// created. + /// + /// \returns a new FieldDecl. + /// + /// \todo The Declarator argument is a hack. It will be removed once FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, RecordDecl *Record, SourceLocation Loc, bool Mutable, @@ -3345,6 +3918,10 @@ public: bool CheckNontrivialField(FieldDecl *FD); + /// ActOnLastBitfield - This routine handles synthesized bitfields rules for + /// class and class extensions. For every class \@interface and class + /// extension \@interface, if the last ivar is a bitfield of any type, + /// then add an implicit `char :0` ivar to the end of that interface. void ActOnLastBitfield(SourceLocation DeclStart, SmallVectorImpl<Decl *> &AllIvarDecls); @@ -3392,7 +3969,12 @@ public: EnumConstantDecl *LastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, Expr *val); + + /// Check that this is a valid underlying type for an enum declaration. bool CheckEnumUnderlyingType(TypeSourceInfo *TI); + + /// Check whether this is a valid redeclaration of a previous enumeration. + /// \return true if the redeclaration was invalid. bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy, bool IsFixed, const EnumDecl *Prev); @@ -3469,26 +4051,101 @@ public: AMK_OptionalProtocolImplementation }; + /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void mergeDeclAttributes(NamedDecl *New, Decl *Old, AvailabilityMergeKind AMK = AMK_Redeclaration); + + /// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the + /// same name and scope as a previous declaration 'Old'. Figure out + /// how to resolve this situation, merging decls or emitting + /// diagnostics as appropriate. If there was an error, set New to be invalid. void MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, LookupResult &OldDecls); + + /// MergeFunctionDecl - We just parsed a function 'New' from + /// declarator D which has the same name and scope as a previous + /// declaration 'Old'. Figure out how to resolve this situation, + /// merging decls or emitting diagnostics as appropriate. + /// + /// In C++, New and Old must be declarations that are not + /// overloaded. Use IsOverload to determine whether New and Old are + /// overloaded, and to select the Old declaration that New should be + /// merged with. + /// + /// Returns true if there was an error, false otherwise. bool MergeFunctionDecl(FunctionDecl *New, NamedDecl *&Old, Scope *S, bool MergeTypeWithOld, bool NewDeclIsDefn); + + /// Completes the merge of two function declarations that are + /// known to be compatible. + /// + /// This routine handles the merging of attributes and other + /// properties of function declarations from the old declaration to + /// the new declaration, once we know that New is in fact a + /// redeclaration of Old. + /// + /// \returns false bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, Scope *S, bool MergeTypeWithOld); void mergeObjCMethodDecls(ObjCMethodDecl *New, ObjCMethodDecl *Old); + + /// MergeVarDecl - We just parsed a variable 'New' which has the same name + /// and scope as a previous declaration 'Old'. Figure out how to resolve this + /// situation, merging decls or emitting diagnostics as appropriate. + /// + /// Tentative definition rules (C99 6.9.2p2) are checked by + /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative + /// definitions here, since the initializer hasn't been attached. void MergeVarDecl(VarDecl *New, LookupResult &Previous); + + /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and + /// scope as a previous declaration 'Old'. Figure out how to merge their + /// types, emitting diagnostics as appropriate. + /// + /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call + /// back to here in AddInitializerToDecl. We can't check them before the + /// initializer is attached. void MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld); + + /// We've just determined that \p Old and \p New both appear to be definitions + /// of the same variable. Either diagnose or fix the problem. bool checkVarDeclRedefinition(VarDecl *OldDefn, VarDecl *NewDefn); void notePreviousDefinition(const NamedDecl *Old, SourceLocation New); + /// Filters out lookup results that don't fall within the given scope + /// as determined by isDeclInScope. void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace); + /// We've determined that \p New is a redeclaration of \p Old. Check that they + /// have compatible owning modules. bool CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old); + + /// [module.interface]p6: + /// A redeclaration of an entity X is implicitly exported if X was introduced + /// by an exported declaration; otherwise it shall not be exported. bool CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old); + + /// A wrapper function for checking the semantic restrictions of + /// a redeclaration within a module. bool CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old); + + /// Check the redefinition in C++20 Modules. + /// + /// [basic.def.odr]p14: + /// For any definable item D with definitions in multiple translation units, + /// - if D is a non-inline non-templated function or variable, or + /// - if the definitions in different translation units do not satisfy the + /// following requirements, + /// the program is ill-formed; a diagnostic is required only if the + /// definable item is attached to a named module and a prior definition is + /// reachable at the point where a later definition occurs. + /// - Each such definition shall not be attached to a named module + /// ([module.unit]). + /// - Each such definition shall consist of the same sequence of tokens, ... + /// ... + /// + /// Return true if the redefinition is not allowed. Return false otherwise. bool IsRedefinitionInModule(const NamedDecl *New, const NamedDecl *Old) const; bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; @@ -3504,16 +4161,47 @@ public: void DiagnoseUnusedNestedTypedefs(const RecordDecl *D, DiagReceiverTy DiagReceiver); void DiagnoseUnusedDecl(const NamedDecl *ND); + + /// DiagnoseUnusedDecl - Emit warnings about declarations that are not used + /// unless they are marked attr(unused). void DiagnoseUnusedDecl(const NamedDecl *ND, DiagReceiverTy DiagReceiver); /// If VD is set but not otherwise used, diagnose, for a parameter or a /// variable. void DiagnoseUnusedButSetDecl(const VarDecl *VD, DiagReceiverTy DiagReceiver); + /// getNonFieldDeclScope - Retrieves the innermost scope, starting + /// from S, where a non-field would be declared. This routine copes + /// with the difference between C and C++ scoping rules in structs and + /// unions. For example, the following code is well-formed in C but + /// ill-formed in C++: + /// @code + /// struct S6 { + /// enum { BAR } e; + /// }; + /// + /// void test_S6() { + /// struct S6 a; + /// a.e = BAR; + /// } + /// @endcode + /// For the declaration of BAR, this routine will return a different + /// scope. The scope S will be the scope of the unnamed enumeration + /// within S6. In C++, this routine will return the scope associated + /// with S6, because the enumeration's scope is a transparent + /// context but structures can contain non-field names. In C, this + /// routine will return the translation unit scope, since the + /// enumeration's scope is a transparent context and structures cannot + /// contain non-field names. Scope *getNonFieldDeclScope(Scope *S); FunctionDecl *CreateBuiltin(IdentifierInfo *II, QualType Type, unsigned ID, SourceLocation Loc); + + /// LazilyCreateBuiltin - The specified Builtin-ID was first used at + /// file scope. lazily create a decl for it. ForRedeclaration is true + /// if we're creating this built-in in anticipation of redeclaring the + /// built-in. NamedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S, bool ForRedeclaration, SourceLocation Loc); @@ -3521,7 +4209,11 @@ public: /// Valid types should not have multiple attributes with different CCs. const AttributedType *getCallingConvAttributedType(QualType T) const; + /// GetNameForDeclarator - Determine the full declaration name for the + /// given Declarator. DeclarationNameInfo GetNameForDeclarator(Declarator &D); + + /// Retrieves the declaration name from a parsed unqualified-id. DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name); /// ParsingInitForAutoVars - a set of declarations with auto types for which @@ -3533,6 +4225,8 @@ public: void deduceOpenCLAddressSpace(ValueDecl *decl); + /// Adjust the \c DeclContext for a function or variable that might be a + /// function-local external declaration. static bool adjustContextForLocalExternDecl(DeclContext *&DC); void MarkTypoCorrectedFunctionDefinition(const NamedDecl *F); @@ -3565,10 +4259,29 @@ public: static bool CanBeGetReturnObject(const FunctionDecl *FD); static bool CanBeGetReturnTypeOnAllocFailure(const FunctionDecl *FD); + /// ImplicitlyDefineFunction - An undeclared identifier was used in a function + /// call, forming a call to an implicitly defined function (per C99 6.5.1p2). NamedDecl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S); + + /// If this function is a C++ replaceable global allocation function + /// (C++2a [basic.stc.dynamic.allocation], C++2a [new.delete]), + /// adds any function attributes that we know a priori based on the standard. + /// + /// We need to check for duplicate attributes both here and where user-written + /// attributes are applied to declarations. void AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction( FunctionDecl *FD); + + /// Adds any function attributes that we know a priori based on + /// the declaration of this function. + /// + /// These attributes can apply both to implicitly-declared builtins + /// (like __builtin___printf_chk) or to library-declared functions + /// like NSLog or printf. + /// + /// We need to check for duplicate attributes both here and where user-written + /// attributes are applied to declarations. void AddKnownFunctionAttributes(FunctionDecl *FD); /// VerifyBitField - verifies that a bit field expression is an ICE and has @@ -3625,6 +4338,18 @@ private: /// it looks like the user is trying to modify the shadowing declaration. llvm::DenseMap<const NamedDecl *, const NamedDecl *> ShadowingDecls; + // We need this to handle + // + // typedef struct { + // void *foo() { return 0; } + // } A; + // + // When we see foo we don't know if after the typedef we will get 'A' or '*A' + // for example. If 'A', foo will have external linkage. If we have '*A', + // foo will have no linkage. Since we can't know until we get to the end + // of the typedef, this function finds out if D might have non-external + // linkage. Callers should verify at the end of the TU if it D has external + // linkage or not. static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); ///@} @@ -3740,9 +4465,17 @@ public: /// This is only necessary for issuing pretty diagnostics. ExtVectorDeclsType ExtVectorDecls; + /// Check if the argument \p E is a ASCII string literal. If not emit an error + /// and return false, otherwise set \p Str to the value of the string literal + /// and return true. bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation = nullptr); + + /// Check if the argument \p ArgNum of \p Attr is a ASCII string literal. + /// If not emit an error and return false. If the argument is an identifier it + /// will emit an error with a fixit hint and treat it as if it was a string + /// literal. bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum, StringRef &Str, SourceLocation *ArgLocation = nullptr); @@ -3781,12 +4514,25 @@ public: SectionAttr *mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, StringRef Name); + /// Used to implement to perform semantic checking on + /// attribute((section("foo"))) specifiers. + /// + /// In this case, "foo" is passed in to be checked. If the section + /// specifier is invalid, return an Error that indicates the problem. + /// + /// This is a simple quality of implementation feature to catch errors + /// and give good diagnostics in cases when the assembler or code generator + /// would otherwise reject the section specifier. llvm::Error isValidSectionSpecifier(StringRef Str); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); CodeSegAttr *mergeCodeSegAttr(Decl *D, const AttributeCommonInfo &CI, StringRef Name); + // Check for things we'd like to warn about. Multiversioning issues are + // handled later in the process, once we know how many exist. bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); + + /// Check Target Version attrs bool checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, StringRef &Str, bool &isDefault); bool checkTargetClonesAttrString( @@ -3840,6 +4586,8 @@ public: const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr, CUDAFunctionTarget CFT = CUDAFunctionTarget::InvalidTarget); + /// Checks a regparm attribute, returning true if it is ill-formed and + /// otherwise setting numParams to the appropriate value. bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value); /// Create an CUDALaunchBoundsAttr attribute. @@ -3871,7 +4619,8 @@ public: EnforceTCBLeafAttr *mergeEnforceTCBLeafAttr(Decl *D, const EnforceTCBLeafAttr &AL); - // Helper for delayed processing of attributes. + /// Helper for delayed processing TransparentUnion or + /// BPFPreserveAccessIndexAttr attribute. void ProcessDeclAttributeDelayed(Decl *D, const ParsedAttributesView &AttrList); @@ -3902,17 +4651,30 @@ public: bool IgnoreTypeAttributes; }; + /// ProcessDeclAttributeList - Apply all the decl attributes in the specified + /// attribute list to the specified decl, ignoring any type attributes. void ProcessDeclAttributeList(Scope *S, Decl *D, const ParsedAttributesView &AttrList, const ProcessDeclAttributeOptions &Options = ProcessDeclAttributeOptions()); + + /// Annotation attributes are the only attributes allowed after an access + /// specifier. bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList); + /// checkUnusedDeclAttributes - Given a declarator which is not being + /// used to build a declaration, complain about any decl attributes + /// which might be lying around on it. void checkUnusedDeclAttributes(Declarator &D); + /// DeclClonePragmaWeak - clone existing decl (maybe definition), + /// \#pragma weak needs a non-definition decl and source may not have one. NamedDecl *DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II, SourceLocation Loc); + + /// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak + /// applied to it, possibly with an alias. void DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W); void ProcessPragmaWeak(Scope *S, Decl *D); @@ -3921,6 +4683,9 @@ public: void PopParsingDeclaration(ParsingDeclState state, Decl *decl); + /// Given a set of delayed diagnostics, re-emit them as if they had + /// been delayed in the current context instead of in the given pool. + /// Essentially, this just moves them to the current pool. void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); /// Check if IdxExpr is a valid parameter index for a function or @@ -4000,9 +4765,15 @@ public: SourceLocation LBrace, const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UsingDecl, bool IsNested); + + /// ActOnFinishNamespaceDef - This callback is called after a namespace is + /// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); NamespaceDecl *getStdNamespace() const; + + /// Retrieve the special "std" namespace, which may require us to + /// implicitly define the namespace. NamespaceDecl *getOrCreateStdNamespace(); CXXRecordDecl *getStdBadAlloc() const; @@ -4058,20 +4829,70 @@ public: CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *Ident); + /// Remove decls we can't actually see from a lookup being used to declare + /// shadow using decls. + /// + /// \param S - The scope of the potential shadow decl + /// \param Previous - The lookup of a potential shadow decl's name. void FilterUsingLookup(Scope *S, LookupResult &lookup); + + /// Hides a using shadow declaration. This is required by the current + /// using-decl implementation when a resolvable using declaration in a + /// class is followed by a declaration which would hide or override + /// one or more of the using decl's targets; for example: + /// + /// struct Base { void foo(int); }; + /// struct Derived : Base { + /// using Base::foo; + /// void foo(int); + /// }; + /// + /// The governing language is C++03 [namespace.udecl]p12: + /// + /// When a using-declaration brings names from a base class into a + /// derived class scope, member functions in the derived class + /// override and/or hide member functions with the same name and + /// parameter types in a base class (rather than conflicting). + /// + /// There are two ways to implement this: + /// (1) optimistically create shadow decls when they're not hidden + /// by existing declarations, or + /// (2) don't create any shadow decls (or at least don't make them + /// visible) until we've fully parsed/instantiated the class. + /// The problem with (1) is that we might have to retroactively remove + /// a shadow decl, which requires several O(n) operations because the + /// decl structures are (very reasonably) not designed for removal. + /// (2) avoids this but is very fiddly and phase-dependent. void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow); + + /// Determines whether to create a using shadow decl for a particular + /// decl, given the set of decls existing prior to this using lookup. bool CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Target, const LookupResult &PreviousDecls, UsingShadowDecl *&PrevShadow); + + /// Builds a shadow declaration corresponding to a 'using' declaration. UsingShadowDecl *BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD, NamedDecl *Target, UsingShadowDecl *PrevDecl); + /// Checks that the given using declaration is not an invalid + /// redeclaration. Note that this is checking only for the using decl + /// itself, not for any ill-formedness among the UsingShadowDecls. bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc, bool HasTypenameKeyword, const CXXScopeSpec &SS, SourceLocation NameLoc, const LookupResult &Previous); + + /// Checks that the given nested-name qualifier used in a using decl + /// in the current context is appropriately related to the current + /// scope. If an error is found, diagnoses it and returns true. + /// R is nullptr, if the caller has not (yet) done a lookup, otherwise it's + /// the result of that lookup. UD is likewise nullptr, except when we have an + /// already-populated UsingDecl whose shadow decls contain the same + /// information (i.e. we're instantiating a UsingDecl with non-dependent + /// scope). bool CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, @@ -4079,6 +4900,11 @@ public: const LookupResult *R = nullptr, const UsingDecl *UD = nullptr); + /// Builds a using declaration. + /// + /// \param IsInstantiation - Whether this call arises from an + /// instantiation of an unresolved using declaration. We treat + /// the lookup differently for these declarations. NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, bool HasTypenameKeyword, @@ -4095,6 +4921,7 @@ public: NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, ArrayRef<NamedDecl *> Expansions); + /// Additional checks for a using declaration referring to a constructor name. bool CheckInheritingConstructorUsingDecl(UsingDecl *UD); /// Given a derived-class using shadow declaration for a constructor and the @@ -4374,6 +5201,11 @@ public: void DiagnoseImmediateEscalatingReason(FunctionDecl *FD); + /// Given a constructor and the set of arguments provided for the + /// constructor, convert the arguments and add any required default arguments + /// to form a proper call to this constructor. + /// + /// \returns true if an error occurred, false otherwise. bool CompleteConstructorCall(CXXConstructorDecl *Constructor, QualType DeclInitType, MultiExprArg ArgsPtr, SourceLocation Loc, @@ -4413,34 +5245,78 @@ public: void DefineImplicitLambdaToBlockPointerConversion(SourceLocation CurrentLoc, CXXConversionDecl *Conv); + /// ActOnStartLinkageSpecification - Parsed the beginning of a C++ + /// linkage specification, including the language and (if present) + /// the '{'. ExternLoc is the location of the 'extern', Lang is the + /// language string literal. LBraceLoc, if valid, provides the location of + /// the '{' brace. Otherwise, this linkage specification does not + /// have any braces. Decl *ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, Expr *LangStr, SourceLocation LBraceLoc); + + /// ActOnFinishLinkageSpecification - Complete the definition of + /// the C++ linkage specification LinkageSpec. If RBraceLoc is + /// valid, it's the position of the closing '}' brace in a linkage + /// specification that uses braces. Decl *ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec, SourceLocation RBraceLoc); //===--------------------------------------------------------------------===// // C++ Classes // + + /// Get the class that is directly named by the current context. This is the + /// class for which an unqualified-id in this scope could name a constructor + /// or destructor. + /// + /// If the scope specifier denotes a class, this will be that class. + /// If the scope specifier is empty, this will be the class whose + /// member-specification we are currently within. Otherwise, there + /// is no such class. CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS); + + /// isCurrentClassName - Determine whether the identifier II is the + /// name of the class type currently being defined. In the case of + /// nested classes, this will only return true if II is the name of + /// the innermost class. bool isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS = nullptr); + + /// Determine whether the identifier II is a typo for the name of + /// the class type currently being defined. If so, update it to the identifier + /// that should have been used. bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); + /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, const ParsedAttributesView &Attrs); + /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member + /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the + /// bitfield width if there is one, 'InitExpr' specifies the initializer if + /// one has been parsed, and 'InitStyle' is set if an in-class initializer is + /// present (but parsing it has been deferred). NamedDecl * ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, Expr *BitfieldWidth, const VirtSpecifiers &VS, InClassInitStyle InitStyle); + /// Enter a new C++ default initializer scope. After calling this, the + /// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if + /// parsing or instantiating the initializer failed. void ActOnStartCXXInClassMemberInitializer(); + + /// This is invoked after parsing an in-class initializer for a + /// non-static C++ class member, and after instantiating an in-class + /// initializer in a class template. Such actions are deferred until the class + /// is complete. void ActOnFinishCXXInClassMemberInitializer(Decl *VarDecl, SourceLocation EqualLoc, Expr *Init); + /// Handle a C++ member initializer using parentheses syntax. MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, ParsedType TemplateTypeTy, @@ -4448,6 +5324,7 @@ public: SourceLocation LParenLoc, ArrayRef<Expr *> Args, SourceLocation RParenLoc, SourceLocation EllipsisLoc); + /// Handle a C++ member initializer using braced-init-list syntax. MemInitResult ActOnMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, @@ -4455,6 +5332,7 @@ public: const DeclSpec &DS, SourceLocation IdLoc, Expr *InitList, SourceLocation EllipsisLoc); + /// Handle a C++ member initializer. MemInitResult BuildMemInitializer(Decl *ConstructorD, Scope *S, CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, @@ -4542,8 +5420,14 @@ public: /// \returns true if any work was done, false otherwise. bool DefineUsedVTables(); + /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared + /// special functions, such as the default constructor, copy + /// constructor, or destructor, to the given C++ class (C++ + /// [special]p1). This routine can only be executed just before the + /// definition of the class is complete. void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); + /// ActOnMemInitializers - Handle the member initializers for a constructor. void ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, ArrayRef<CXXCtorInitializer *> MemInits, bool AnyErrors); @@ -4556,11 +5440,20 @@ public: void referenceDLLExportedClassMethods(); + /// Perform propagation of DLL attributes from a derived class to a + /// templated base class for MS compatibility. void propagateDLLAttrToBaseClassTemplate( CXXRecordDecl *Class, Attr *ClassAttr, ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc); + /// Perform semantic checks on a class definition that has been + /// completing, introducing implicitly-declared members, checking for + /// abstract types, etc. + /// + /// \param S The scope in which the class was parsed. Null if we didn't just + /// parse a class definition. + /// \param Record The completed class. void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record); /// Check that the C++ class annoated with "trivial_abi" satisfies all the @@ -4575,16 +5468,38 @@ public: Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, const ParsedAttributesView &AttrList); + + /// Perform any semantic analysis which needs to be delayed until all + /// pending class member declarations have been parsed. void ActOnFinishCXXMemberDecls(); void ActOnFinishCXXNonNestedClass(); + /// This is used to implement the constant expression evaluation part of the + /// attribute enable_if extension. There is nothing in standard C++ which + /// would require reentering parameters. void ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param); unsigned ActOnReenterTemplateScope(Decl *Template, llvm::function_ref<Scope *()> EnterScope); void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); + + /// ActOnStartDelayedCXXMethodDeclaration - We have completed + /// parsing a top-level (non-nested) C++ class, and we are now + /// parsing those parts of the given Method declaration that could + /// not be parsed earlier (C++ [class.mem]p2), such as default + /// arguments. This action should enter the scope of the given + /// Method declaration as if we had just parsed the qualified method + /// name. However, it should not bring the parameters into scope; + /// that will be performed by ActOnDelayedCXXMethodParameter. void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record); + + /// ActOnFinishDelayedCXXMethodDeclaration - We have finished + /// processing the delayed method declaration for Method. The method + /// declaration is now considered finished. There may be a separate + /// ActOnStartOfFunctionDef action later (not necessarily + /// immediately!) for this method, if it was also defined inside the + /// class body. void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnFinishDelayedMemberInitializers(Decl *Record); @@ -4597,21 +5512,79 @@ public: Decl *BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, Expr *AssertMessageExpr, SourceLocation RParenLoc, bool Failed); + + /// Try to print more useful information about a failed static_assert + /// with expression \E void DiagnoseStaticAssertDetails(const Expr *E); + /// Handle a friend type declaration. This works in tandem with + /// ActOnTag. + /// + /// Notes on friend class templates: + /// + /// We generally treat friend class declarations as if they were + /// declaring a class. So, for example, the elaborated type specifier + /// in a friend declaration is required to obey the restrictions of a + /// class-head (i.e. no typedefs in the scope chain), template + /// parameters are required to match up with simple template-ids, &c. + /// However, unlike when declaring a template specialization, it's + /// okay to refer to a template specialization without an empty + /// template parameter declaration, e.g. + /// friend class A<T>::B<unsigned>; + /// We permit this as a special case; if there are any template + /// parameters present at all, require proper matching, i.e. + /// template <> template \<class T> friend class A<int>::B; Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TemplateParams); NamedDecl *ActOnFriendFunctionDecl(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParams); + /// CheckConstructorDeclarator - Called by ActOnDeclarator to check + /// the well-formedness of the constructor declarator @p D with type @p + /// R. If there are any errors in the declarator, this routine will + /// emit diagnostics and set the invalid bit to true. In any case, the type + /// will be updated to reflect a well-formed type for the constructor and + /// returned. QualType CheckConstructorDeclarator(Declarator &D, QualType R, StorageClass &SC); + + /// CheckConstructor - Checks a fully-formed constructor for + /// well-formedness, issuing any diagnostics required. Returns true if + /// the constructor declarator is invalid. void CheckConstructor(CXXConstructorDecl *Constructor); + + /// CheckDestructorDeclarator - Called by ActOnDeclarator to check + /// the well-formednes of the destructor declarator @p D with type @p + /// R. If there are any errors in the declarator, this routine will + /// emit diagnostics and set the declarator to invalid. Even if this happens, + /// will be updated to reflect a well-formed type for the destructor and + /// returned. QualType CheckDestructorDeclarator(Declarator &D, QualType R, StorageClass &SC); + + /// CheckDestructor - Checks a fully-formed destructor definition for + /// well-formedness, issuing any diagnostics required. Returns true + /// on error. bool CheckDestructor(CXXDestructorDecl *Destructor); + + /// CheckConversionDeclarator - Called by ActOnDeclarator to check the + /// well-formednes of the conversion function declarator @p D with + /// type @p R. If there are any errors in the declarator, this routine + /// will emit diagnostics and return true. Otherwise, it will return + /// false. Either way, the type @p R will be updated to reflect a + /// well-formed type for the conversion operator. void CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass &SC); + + /// ActOnConversionDeclarator - Called by ActOnDeclarator to complete + /// the declaration of the given C++ conversion function. This routine + /// is responsible for recording the conversion function in the C++ + /// class, if possible. Decl *ActOnConversionDeclarator(CXXConversionDecl *Conversion); + + /// Check the validity of a declarator that we parsed for a deduction-guide. + /// These aren't actually declarators in the grammar, so we need to check that + /// the user didn't specify any pieces that are not part of the + /// deduction-guide grammar. Return true on invalid deduction-guide. bool CheckDeductionGuideDeclarator(Declarator &D, QualType &R, StorageClass &SC); @@ -4658,25 +5631,44 @@ public: // C++ Derived Classes // - /// ActOnBaseSpecifier - Parsed a base specifier + /// Check the validity of a C++ base class specifier. + /// + /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics + /// and returns NULL otherwise. CXXBaseSpecifier *CheckBaseSpecifier(CXXRecordDecl *Class, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, TypeSourceInfo *TInfo, SourceLocation EllipsisLoc); + /// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is + /// one entry in the base class list of a class specifier, for + /// example: + /// class foo : public bar, virtual private baz { + /// 'public bar' and 'virtual private baz' are each base-specifiers. BaseResult ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, const ParsedAttributesView &Attrs, bool Virtual, AccessSpecifier Access, ParsedType basetype, SourceLocation BaseLoc, SourceLocation EllipsisLoc); + /// Performs the actual work of attaching the given base class + /// specifiers to a C++ class. bool AttachBaseSpecifiers(CXXRecordDecl *Class, MutableArrayRef<CXXBaseSpecifier *> Bases); + + /// ActOnBaseSpecifiers - Attach the given base specifiers to the + /// class, after checking whether there are any duplicate base + /// classes. void ActOnBaseSpecifiers(Decl *ClassDecl, MutableArrayRef<CXXBaseSpecifier *> Bases); + /// Determine whether the type \p Derived is a C++ class that is + /// derived from the type \p Base. bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base); + + /// Determine whether the type \p Derived is a C++ class that is + /// derived from the type \p Base. bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, CXXBasePaths &Paths); @@ -4687,6 +5679,19 @@ public: SourceLocation Loc, SourceRange Range, CXXCastPath *BasePath = nullptr, bool IgnoreAccess = false); + + /// CheckDerivedToBaseConversion - Check whether the Derived-to-Base + /// conversion (where Derived and Base are class types) is + /// well-formed, meaning that the conversion is unambiguous (and + /// that all of the base classes are accessible). Returns true + /// and emits a diagnostic if the code is ill-formed, returns false + /// otherwise. Loc is the location where this routine should point to + /// if there is an error, and Range is the source range to highlight + /// if there is an error. + /// + /// If either InaccessibleBaseID or AmbiguousBaseConvID are 0, then the + /// diagnostic for the respective type of error will be suppressed, but the + /// check for ill-formed code will still be performed. bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned InaccessibleBaseID, unsigned AmbiguousBaseConvID, @@ -4694,6 +5699,18 @@ public: DeclarationName Name, CXXCastPath *BasePath, bool IgnoreAccess = false); + /// Builds a string representing ambiguous paths from a + /// specific derived class to different subobjects of the same base + /// class. + /// + /// This function builds a string that can be used in error messages + /// to show the different paths that one can take through the + /// inheritance hierarchy to go from the derived class to different + /// subobjects of a base class. The result looks something like this: + /// @code + /// struct D -> struct B -> struct A + /// struct D -> struct C -> struct A + /// @endcode std::string getAmbiguousPathsDisplayString(CXXBasePaths &Paths); bool CheckOverridingFunctionAttributes(CXXMethodDecl *New, @@ -4708,6 +5725,11 @@ public: bool CheckExplicitObjectOverride(CXXMethodDecl *New, const CXXMethodDecl *Old); + /// Mark the given method pure. + /// + /// \param Method the method to be marked pure. + /// + /// \param InitRange the source range that covers the "0" initializer. bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange); /// CheckOverrideControl - Check C++11 override control semantics. @@ -4717,8 +5739,8 @@ public: /// not used in the declaration of an overriding method. void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent); - /// CheckForFunctionMarkedFinal - Checks whether a virtual member function - /// overrides a virtual member function marked 'final', according to + /// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member + /// function overrides a virtual member function marked 'final', according to /// C++11 [class.virtual]p4. bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old); @@ -4752,8 +5774,14 @@ public: // C++ Overloaded Operators [C++ 13.5] // + /// CheckOverloadedOperatorDeclaration - Check whether the declaration + /// of this overloaded operator is well-formed. If so, returns false; + /// otherwise, emits appropriate diagnostics and returns true. bool CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl); + /// CheckLiteralOperatorDeclaration - Check whether the declaration + /// of this literal operator function is well-formed. If so, returns + /// false; otherwise, emits appropriate diagnostics and returns true. bool CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl); /// ActOnExplicitBoolSpecifier - Build an ExplicitSpecifier from an expression @@ -4764,6 +5792,9 @@ public: /// Returns true if the explicit specifier is now resolved. bool tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec); + /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a + /// C++ if/switch/while/for statement. + /// e.g: "if (int x = f()) {...}" DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D); // Emitting members of dllexported classes is delayed until the class @@ -4771,26 +5802,49 @@ public: SmallVector<CXXRecordDecl *, 4> DelayedDllExportClasses; SmallVector<CXXMethodDecl *, 4> DelayedDllExportMemberFunctions; + /// Merge the exception specifications of two variable declarations. + /// + /// This is called when there's a redeclaration of a VarDecl. The function + /// checks if the redeclaration might have an exception specification and + /// validates compatibility and merges the specs if necessary. void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); + + /// MergeCXXFunctionDecl - Merge two declarations of the same C++ + /// function, once we already know that they have the same + /// type. Subroutine of MergeFunctionDecl. Returns true if there was an + /// error, false otherwise. bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S); /// Helpers for dealing with blocks and functions. void CheckCXXDefaultArguments(FunctionDecl *FD); + + /// CheckExtraCXXDefaultArguments - Check for any extra default + /// arguments in the declarator, which is not a function declaration + /// or definition and therefore is not permitted to have default + /// arguments. This routine should be invoked for every declarator + /// that is not a function declaration or definition. void CheckExtraCXXDefaultArguments(Declarator &D); CXXSpecialMemberKind getSpecialMember(const CXXMethodDecl *MD) { return getDefaultedFunctionKind(MD).asSpecialMember(); } + /// Perform semantic analysis for the variable declaration that + /// occurs within a C++ catch clause, returning the newly-created + /// variable. VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id); + /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch + /// handler. Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D); void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); + /// Handle a friend tag declaration where the scope specifier was + /// templated. DeclResult ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, IdentifierInfo *Name, @@ -4805,6 +5859,8 @@ public: AccessSpecifier AS, const ParsedAttr &MSPropertyAttr); + /// Diagnose why the specified class does not have a trivial special member of + /// the given kind. void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMemberKind CSM); @@ -4816,6 +5872,9 @@ public: TAH_ConsiderTrivialABI }; + /// Determine whether a defaulted or deleted special member function is + /// trivial, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, + /// C++11 [class.copy]p25, and C++11 [class.dtor]p5. bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, TrivialABIHandling TAH = TAH_IgnoreTrivialABI, bool Diagnose = false); @@ -4868,6 +5927,13 @@ public: } }; + /// Determine the kind of defaulting that would be done for a given function. + /// + /// If the function is both a default constructor and a copy / move + /// constructor (due to having a default argument for the first parameter), + /// this picks CXXSpecialMemberKind::DefaultConstructor. + /// + /// FIXME: Check that case is properly handled by all callers. DefaultedFunctionKind getDefaultedFunctionKind(const FunctionDecl *FD); /// Handle a C++11 empty-declaration and attribute-declaration. @@ -4882,20 +5948,43 @@ public: CheckValid }; + // Check whether a function declaration satisfies the requirements of a + // constexpr function definition or a constexpr constructor definition. If so, + // return true. If not, produce appropriate diagnostics (unless asked not to + // by Kind) and return false. + // + // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. bool CheckConstexprFunctionDefinition(const FunctionDecl *FD, CheckConstexprKind Kind); + /// Diagnose methods which overload virtual methods in a base class + /// without overriding any. void DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD); + + /// Check if a method overloads virtual methods in a base class without + /// overriding any. void FindHiddenVirtualMethods(CXXMethodDecl *MD, SmallVectorImpl<CXXMethodDecl *> &OverloadedMethods); void NoteHiddenVirtualMethods(CXXMethodDecl *MD, SmallVectorImpl<CXXMethodDecl *> &OverloadedMethods); + + /// ActOnParamDefaultArgument - Check whether the default argument + /// provided for a function parameter is well-formed. If so, attach it + /// to the parameter declaration. void ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, Expr *defarg); + + /// ActOnParamUnparsedDefaultArgument - We've seen a default + /// argument for a function parameter, but we can't parse it yet + /// because we're inside a class definition. Note that this default + /// argument will be parsed later. void ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc, SourceLocation ArgLoc); + + /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of + /// the default argument for the parameter param failed. void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc, Expr *DefaultArg); ExprResult ConvertParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg, @@ -5056,9 +6145,26 @@ public: const FunctionProtoType *FPT); void UpdateExceptionSpec(FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI); + + /// CheckSpecifiedExceptionType - Check if the given type is valid in an + /// exception specification. Incomplete types, or pointers to incomplete types + /// other than void are not allowed. + /// + /// \param[in,out] T The exception type. This will be decayed to a pointer + /// type + /// when the input is an array or a function type. bool CheckSpecifiedExceptionType(QualType &T, SourceRange Range); + + /// CheckDistantExceptionSpec - Check if the given type is a pointer or + /// pointer to member to a function with an exception specification. This + /// means that it is invalid to add another level of indirection. bool CheckDistantExceptionSpec(QualType T); bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); + + /// CheckEquivalentExceptionSpec - Check if the two types have equivalent + /// exception specifications. Exception specifications are equivalent if + /// they allow exactly the same set of exception types. It does not matter how + /// that is achieved. See C++ [except.spec]p2. bool CheckEquivalentExceptionSpec(const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, @@ -5070,12 +6176,22 @@ public: const FunctionProtoType *New, SourceLocation NewLoc); bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); + + /// CheckExceptionSpecSubset - Check whether the second function type's + /// exception specification is a subset (or equivalent) of the first function + /// type. This is used by override and pointer assignment checks. bool CheckExceptionSpecSubset( const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, const FunctionProtoType *Superset, bool SkipSupersetFirstParameter, SourceLocation SuperLoc, const FunctionProtoType *Subset, bool SkipSubsetFirstParameter, SourceLocation SubLoc); + + /// CheckParamExceptionSpec - Check if the parameter and return types of the + /// two functions have equivalent exception specs. This is part of the + /// assignment and override compatibility check. We do not check the + /// parameters of parameter function pointers recursively, as no sane + /// programmer would even be able to write such a function type. bool CheckParamExceptionSpec( const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, const FunctionProtoType *Target, bool SkipTargetFirstParameter, @@ -5370,6 +6486,8 @@ public: AA_Passing_CFAudited }; + /// Determine whether the use of this declaration is valid, without + /// emitting diagnostics. bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid); // A version of DiagnoseUseOfDecl that should be used if overload resolution // has been used to find this declaration, which means we don't have to bother @@ -5381,14 +6499,31 @@ public: /*SkipTrailingRequiresClause=*/true); } + /// Determine whether the use of this declaration is valid, and + /// emit any corresponding diagnostics. + /// + /// This routine diagnoses various problems with referencing + /// declarations that can occur when using a declaration. For example, + /// it might warn if a deprecated or unavailable declaration is being + /// used, or produce an error (and return true) if a C++0x deleted + /// function is being used. + /// + /// \returns true if there was an error (this declaration cannot be + /// referenced), false otherwise. bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass = nullptr, bool ObjCPropertyAccess = false, bool AvoidPartialAvailabilityChecks = false, ObjCInterfaceDecl *ClassReciever = nullptr, bool SkipTrailingRequiresClause = false); + + /// Emit a note explaining that this function is deleted. void NoteDeletedFunction(FunctionDecl *FD); + /// DiagnoseSentinelCalls - This routine checks whether a call or + /// message-send is to a declaration with the sentinel attribute, and + /// if so, it checks that the requirements of the sentinel are + /// satisfied. void DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc, ArrayRef<Expr *> Args); @@ -5409,6 +6544,10 @@ public: TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo); ExprResult HandleExprEvaluationContextForTypeof(Expr *E); + /// Check whether E, which is either a discarded-value expression or an + /// unevaluated operand, is a simple-assignment to a volatlie-qualified + /// lvalue, and if so, remove it from the list of volatile-qualified + /// assignments that we are going to warn are deprecated. void CheckUnusedVolatileAssignment(Expr *E); ExprResult ActOnConstantExpression(ExprResult Res); @@ -5426,11 +6565,27 @@ public: // because the name denotes a virtual function and was written without an // explicit nested-name-specifier). void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool MightBeOdrUse); + + /// Mark a function referenced, and check whether it is odr-used + /// (C++ [basic.def.odr]p2, C99 6.9p3) void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse = true); + + /// Mark a variable referenced, and check whether it is odr-used + /// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be + /// used directly for normal expressions referring to VarDecl. void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); + + /// Perform reference-marking and odr-use handling for a DeclRefExpr. + /// + /// Note, this may change the dependence of the DeclRefExpr, and so needs to + /// be handled with care if the DeclRefExpr is not newly-created. void MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base = nullptr); + + /// Perform reference-marking and odr-use handling for a MemberExpr. void MarkMemberReferenced(MemberExpr *E); + + /// Perform reference-marking and odr-use handling for a FunctionParmPackExpr. void MarkFunctionParmPackReferenced(FunctionParmPackExpr *E); void MarkCaptureUsedInEnclosingContext(ValueDecl *Capture, SourceLocation Loc, unsigned CapturingScopeIndex); @@ -5499,6 +6654,13 @@ public: /// referenced. Used when template instantiation instantiates a non-dependent /// type -- entities referenced by the type are now referenced. void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); + + /// Mark any declarations that appear within this expression or any + /// potentially-evaluated subexpressions as "referenced". + /// + /// \param SkipLocalVariables If true, don't mark local variables as + /// 'referenced'. + /// \param StopAt Subexpressions that we shouldn't recurse into. void MarkDeclarationsReferencedInExpr( Expr *E, bool SkipLocalVariables = false, ArrayRef<const Expr *> StopAt = std::nullopt); @@ -5541,13 +6703,33 @@ public: bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr); + /// Decomposes the given name into a DeclarationNameInfo, its location, and + /// possibly a list of template arguments. + /// + /// If this produces template arguments, it is permitted to call + /// DecomposeTemplateName. + /// + /// This actually loses a lot of source location information for + /// non-standard name kinds; we should consider preserving that in + /// some way. void DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *&TemplateArgs); + /// Diagnose a lookup that found results in an enclosing class during error + /// recovery. This usually indicates that the results were found in a + /// dependent base class that could not be searched as part of a template + /// definition. Always issues a diagnostic (though this may be only a warning + /// in MS compatibility mode). + /// + /// Return \c true if the error is unrecoverable, or \c false if the caller + /// should attempt to recover using these lookup results. bool DiagnoseDependentMemberLookup(const LookupResult &R); + /// Diagnose an empty lookup. + /// + /// \return false if new lookup candidates were found bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, @@ -5570,6 +6752,9 @@ public: NamedDecl *FoundD = nullptr, SourceLocation TemplateKWLoc = SourceLocation(), const TemplateArgumentListInfo *TemplateArgs = nullptr); + + /// BuildDeclRefExpr - Build an expression that references a + /// declaration that does not require a closure capture. DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, @@ -5580,6 +6765,10 @@ public: bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen); + /// BuildQualifiedDeclarationNameExpr - Build a C++ qualified + /// declaration name, generally during template instantiation. + /// There's a large number of things which don't need to be done along + /// this path. ExprResult BuildQualifiedDeclarationNameExpr( CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); @@ -5587,6 +6776,8 @@ public: ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl = false); + + /// Complete semantic analysis for a reference to the given declaration. ExprResult BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD = nullptr, @@ -5612,7 +6803,10 @@ public: MultiExprArg Val); /// ActOnStringLiteral - The specified tokens were lexed as pasted string - /// fragments (e.g. "foo" "bar" L"baz"). + /// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle + /// string concatenation ([C99 5.1.1.2, translation phase #6]), so it may come + /// from multiple tokens. However, the common case is that StringToks points + /// to one string. ExprResult ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope = nullptr); @@ -5647,36 +6841,88 @@ public: Expr *InputExpr, bool IsAfterAmp = false); ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp = false); + + /// Unary Operators. 'Tok' is the token for the operator. ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input, bool IsAfterAmp = false); + /// Determine whether the given expression is a qualified member + /// access expression, of a form that could be turned into a pointer to member + /// with the address-of operator. bool isQualifiedMemberAccess(Expr *E); bool CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc, const Expr *Op, const CXXMethodDecl *MD); + /// CheckAddressOfOperand - The operand of & must be either a function + /// designator or an lvalue designating an object. If it is an lvalue, the + /// object cannot be declared with storage class register or be a bit field. + /// Note: The usual conversions are *not* applied to the operand of the & + /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue. + /// In C++, the operand might be an overloaded function name, in which case + /// we allow the '&' but retain the overloaded-function type. QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc); + /// ActOnAlignasTypeArgument - Handle @c alignas(type-id) and @c + /// _Alignas(type-name) . + /// [dcl.align] An alignment-specifier of the form + /// alignas(type-id) has the same effect as alignas(alignof(type-id)). + /// + /// [N1570 6.7.5] _Alignas(type-name) is equivalent to + /// _Alignas(_Alignof(type-name)). bool ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty, SourceLocation OpLoc, SourceRange R); bool CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo, SourceLocation OpLoc, SourceRange R); + /// Build a sizeof or alignof expression given a type operand. ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, SourceRange R); + + /// Build a sizeof or alignof expression given an expression + /// operand. ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind); + + /// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c + /// expr and the same for @c alignof and @c __alignof + /// Note that the ArgRange is invalid if isType is false. ExprResult ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, bool IsType, void *TyOrEx, SourceRange ArgRange); + /// Check for operands with placeholder types and complain if found. + /// Returns ExprError() if there was an error and no recovery was possible. ExprResult CheckPlaceholderExpr(Expr *E); bool CheckVecStepExpr(Expr *E); + /// Check the constraints on expression operands to unary type expression + /// and type traits. + /// + /// Completes any types necessary and validates the constraints on the operand + /// expression. The logic mostly mirrors the type-based overload, but may + /// modify the expression as it completes the type for that expression through + /// template instantiation, etc. bool CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind); + + /// Check the constraints on operands to unary expression and type + /// traits. + /// + /// This will complete any types necessary, and validate the various + /// constraints on those operands. + /// + /// The UsualUnaryConversions() function is *not* called by this routine. + /// C99 6.3.2.1p[2-4] all state: + /// Except when it is the operand of the sizeof operator ... + /// + /// C++ [expr.sizeof]p4 + /// The lvalue-to-rvalue, array-to-pointer, and function-to-pointer + /// standard conversions are not applied to the operand of sizeof. + /// + /// This policy is followed for all of the unary trait expressions. bool CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc, SourceRange ExprRange, UnaryExprOrTypeTrait ExprKind, @@ -5695,10 +6941,26 @@ public: Expr *ColumnIdx, SourceLocation RBLoc); + /// ConvertArgumentsForCall - Converts the arguments specified in + /// Args/NumArgs to the parameter types of the function FDecl with + /// function prototype Proto. Call is the call expression itself, and + /// Fn is the function expression. For a C++ member function, this + /// routine does not attempt to convert the object argument. Returns + /// true if the call is ill-formed. bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl, const FunctionProtoType *Proto, ArrayRef<Expr *> Args, SourceLocation RParenLoc, bool ExecConfig = false); + + /// CheckStaticArrayArgument - If the given argument corresponds to a static + /// array parameter, check that it is non-null, and that if it is formed by + /// array-to-pointer decay, the underlying array is sufficiently large. + /// + /// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of + /// the array type derivation, then for each call to the function, the value + /// of the corresponding actual argument shall provide access to the first + /// element of an array with at least as many elements as specified by the + /// size expression. void CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param, const Expr *ArgExpr); @@ -5708,16 +6970,29 @@ public: ExprResult ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig = nullptr); + + /// BuildCallExpr - Handle a call to Fn with the specified array of arguments. + /// This provides the location of the left/right parens and a list of comma + /// locations. ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig = nullptr, bool IsExecConfig = false, bool AllowRecovery = false); + + /// BuildBuiltinCallExpr - Create a call to a builtin function specified by Id + // with the specified CallArgs Expr *BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs); using ADLCallKind = CallExpr::ADLCallKind; + /// BuildResolvedCallExpr - Build a call to a resolved expression, + /// i.e. an expression not of \p OverloadTy. The expression should + /// unary-convert to an expression of function-pointer or + /// block-pointer type. + /// + /// \param NDecl the declaration being called, if available ExprResult BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, ArrayRef<Expr *> Arg, SourceLocation RParenLoc, @@ -5728,6 +7003,8 @@ public: ParsedType &Ty, SourceLocation RParenLoc, Expr *CastExpr); + /// Prepares for a scalar cast, performing all the necessary stages + /// except the final cast and returning the kind required. CastKind PrepareScalarCast(ExprResult &src, QualType destType); /// Build an altivec or OpenCL literal. @@ -5735,6 +7012,8 @@ public: SourceLocation RParenLoc, Expr *E, TypeSourceInfo *TInfo); + /// This is not an AltiVec-style cast or or C++ direct-initialization, so turn + /// the ParenListExpr into a sequence of comma binary operators. ExprResult MaybeConvertParenListExprToParenExpr(Scope *S, Expr *ME); ExprResult ActOnCompoundLiteral(SourceLocation LParenLoc, ParsedType Ty, @@ -5751,15 +7030,23 @@ public: ExprResult BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, SourceLocation RBraceLoc); + /// Binary Operators. 'Tok' is the token for the operator. ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr); ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); + + /// CreateBuiltinBinOp - Creates a new built-in binary operation with + /// operator @p Opc at location @c TokLoc. This routine only supports + /// built-in operations; ActOnBinOp handles overloaded operators. ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr); void LookupBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, UnresolvedSetImpl &Functions); + /// Look for instances where it is likely the comma operator is confused with + /// another operator. There is an explicit list of acceptable expressions for + /// the left hand side of the comma operator, otherwise emit a warning. void DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc); /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null @@ -5855,17 +7142,26 @@ public: //===---------------------------- Clang Extensions ----------------------===// - /// __builtin_convertvector(...) + /// ActOnConvertVectorExpr - create a new convert-vector expression from the + /// provided arguments. + /// + /// __builtin_convertvector( value, dst type ) + /// ExprResult ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc); //===---------------------------- OpenCL Features -----------------------===// - /// __builtin_astype(...) + /// Parse a __builtin_astype expression. + /// + /// __builtin_astype( value, dst type ) + /// ExprResult ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc); + + /// Create a new AsTypeExpr node (bitcast) from the arguments. ExprResult BuildAsTypeExpr(Expr *E, QualType DestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc); @@ -5875,6 +7171,26 @@ public: ArrayRef<Expr *> SubExprs, QualType T = QualType()); + /// Cast a base object to a member's actual type. + /// + /// There are two relevant checks: + /// + /// C++ [class.access.base]p7: + /// + /// If a class member access operator [...] is used to access a non-static + /// data member or non-static member function, the reference is ill-formed + /// if the left operand [...] cannot be implicitly converted to a pointer to + /// the naming class of the right operand. + /// + /// C++ [expr.ref]p7: + /// + /// If E2 is a non-static data member or a non-static member function, the + /// program is ill-formed if the class of which E2 is directly a member is + /// an ambiguous base (11.8) of the naming class (11.9.3) of E2. + /// + /// Note that the latter check does not consider access; the access of the + /// "real" base class is checked as appropriate when checking the access of + /// the member name. ExprResult PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, @@ -5908,6 +7224,7 @@ public: void MarkExpressionAsImmediateEscalating(Expr *E); + // Check that the SME attributes for PSTATE.ZA and PSTATE.SM are compatible. bool IsInvalidSMECallConversion(QualType FromType, QualType ToType); /// Abstract base class used for diagnosing integer constant @@ -6047,6 +7364,9 @@ public: ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation QuestionLoc); + /// Emit a specialized diagnostic when one expression is a null pointer + /// constant and the other is not a pointer. Returns true if a diagnostic is + /// emitted. bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation QuestionLoc); @@ -6055,8 +7375,19 @@ public: SourceLocation Loc, bool IsCompAssign, bool AllowBothBool, bool AllowBoolConversion, bool AllowBoolOperation, bool ReportInvalid); + + /// Return a signed ext_vector_type that is of identical size and number of + /// elements. For floating point vectors, return an integer type of identical + /// size and number of elements. In the non ext_vector_type case, search from + /// the largest type to the smallest type to avoid cases where long long == + /// long, where long gets picked over long long. QualType GetSignedVectorType(QualType V); QualType GetSignedSizelessVectorType(QualType V); + + /// CheckVectorCompareOperands - vector comparisons are a clang extension that + /// operates on extended vector types. Instead of producing an IntTy result, + /// like a scalar comparison, a vector comparison produces a vector of integer + /// types. QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc); @@ -6092,17 +7423,40 @@ public: QualType CheckMatrixMultiplyOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, bool IsCompAssign); + /// Are the two types SVE-bitcast-compatible types? I.e. is bitcasting from + /// the first SVE type (e.g. an SVE VLAT) to the second type (e.g. an SVE + /// VLST) allowed? + /// + /// This will also return false if the two given types do not make sense from + /// the perspective of SVE bitcasts. bool isValidSveBitcast(QualType srcType, QualType destType); + /// Are the two types matrix types and do they have the same dimensions i.e. + /// do they have the same number of rows and the same number of columns? bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy); bool areVectorTypesSameSize(QualType srcType, QualType destType); + + /// Are the two types lax-compatible vector types? That is, given + /// that one of them is a vector, do they have equal storage sizes, + /// where the storage size is the number of elements times the element + /// size? + /// + /// This will also return false if either of the types is neither a + /// vector nor a real type. bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType); + + /// Is this a legal conversion between two types, one of which is + /// known to be a vector type? bool isLaxVectorConversion(QualType srcType, QualType destType); + + // This returns true if at least one of the types is an altivec vector. bool anyAltivecTypes(QualType srcType, QualType destType); // type checking C++ declaration initializers (C++ [dcl.init]). + /// Check a cast of an unknown-any type. We intentionally only + /// trigger this for C-style casts. ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, Expr *CastExpr, CastKind &CastKind, ExprValueKind &VK, CXXCastPath &Path); @@ -6188,7 +7542,9 @@ public: VAK_Invalid }; - // Determines which VarArgKind fits an expression. + /// Determine the degree of POD-ness for an expression. + /// Incomplete types are considered POD, since this check can be performed + /// when we're in an unevaluated context. VarArgKind isValidVarArgType(const QualType &Ty); /// Check to see if the given expression is a valid argument to a variadic @@ -6358,6 +7714,10 @@ public: /// type checking binary operators (subroutines of CreateBuiltinBinOp). QualType InvalidOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS); + + /// Diagnose cases where a scalar was implicitly converted to a vector and + /// diagnose the underlying types. Otherwise, diagnose the error + /// as invalid vector logical operands for non-C++ cases. QualType InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS); @@ -6576,6 +7936,7 @@ public: llvm::SmallVector<std::pair<SourceLocation, const BlockDecl *>, 1> ImplicitlyRetainedSelfLocs; + /// Do an explicit extend of the given block pointer if we're in ARC. void maybeExtendBlockObject(ExprResult &E); private: @@ -6626,6 +7987,10 @@ public: /// used in initializer of the field. llvm::MapVector<FieldDecl *, DeleteLocs> DeleteExprs; + /// Handle the result of the special case name lookup for inheriting + /// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as + /// constructor names in member using declarations, even if 'X' is not the + /// name of the corresponding type. ParsedType getInheritingConstructorName(CXXScopeSpec &SS, SourceLocation NameLoc, const IdentifierInfo &Name); @@ -6640,8 +8005,11 @@ public: ParsedType getDestructorTypeForDecltype(const DeclSpec &DS, ParsedType ObjectType); + /// Build a C++ typeid expression with a type operand. ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc); + + /// Build a C++ typeid expression with an expression operand. ExprResult BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *Operand, SourceLocation RParenLoc); @@ -6650,8 +8018,11 @@ public: bool isType, void *TyOrExpr, SourceLocation RParenLoc); + /// Build a Microsoft __uuidof expression with a type operand. ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, SourceLocation RParenLoc); + + /// Build a Microsoft __uuidof expression with an expression operand. ExprResult BuildCXXUuidof(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *Operand, SourceLocation RParenLoc); @@ -6733,6 +8104,8 @@ public: ExprResult ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *expr); ExprResult BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, bool IsThrownVarInScope); + + /// CheckCXXThrowOperand - Validate the operand of a throw. bool CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ThrowTy, Expr *E); /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. @@ -6751,7 +8124,22 @@ public: SourceLocation RParenLoc, bool ListInitialization); - /// ActOnCXXNew - Parsed a C++ 'new' expression. + /// Parsed a C++ 'new' expression (C++ 5.3.4). + /// + /// E.g.: + /// @code new (memory) int[size][4] @endcode + /// or + /// @code ::new Foo(23, "hello") @endcode + /// + /// \param StartLoc The first location of the expression. + /// \param UseGlobal True if 'new' was prefixed with '::'. + /// \param PlacementLParen Opening paren of the placement arguments. + /// \param PlacementArgs Placement new arguments. + /// \param PlacementRParen Closing paren of the placement arguments. + /// \param TypeIdParens If the type is in parens, the source range. + /// \param D The type to be allocated, as well as array dimensions. + /// \param Initializer The initializing expression or initializer-list, or + /// null if there is none. ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, @@ -6774,6 +8162,8 @@ public: void diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, SourceLocation Loc); + /// Checks that a type is suitable as the allocated type + /// in a new-expression. bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R); @@ -6799,6 +8189,30 @@ public: FunctionDecl *&OperatorNew, FunctionDecl *&OperatorDelete, bool Diagnose = true); + + /// DeclareGlobalNewDelete - Declare the global forms of operator new and + /// delete. These are: + /// @code + /// // C++03: + /// void* operator new(std::size_t) throw(std::bad_alloc); + /// void* operator new[](std::size_t) throw(std::bad_alloc); + /// void operator delete(void *) throw(); + /// void operator delete[](void *) throw(); + /// // C++11: + /// void* operator new(std::size_t); + /// void* operator new[](std::size_t); + /// void operator delete(void *) noexcept; + /// void operator delete[](void *) noexcept; + /// // C++1y: + /// void* operator new(std::size_t); + /// void* operator new[](std::size_t); + /// void operator delete(void *) noexcept; + /// void operator delete[](void *) noexcept; + /// void operator delete(void *, std::size_t) noexcept; + /// void operator delete[](void *, std::size_t) noexcept; + /// @endcode + /// Note that the placement and nothrow forms of new are *not* implicitly + /// declared. Their use requires including \<new\>. void DeclareGlobalNewDelete(); void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, ArrayRef<QualType> Params); @@ -6814,7 +8228,10 @@ public: FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc, CXXRecordDecl *RD); - /// ActOnCXXDelete - Parsed a C++ 'delete' expression + /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: + /// @code ::delete ptr; @endcode + /// or + /// @code delete [] ptr; @endcode ExprResult ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, bool ArrayForm, Expr *Operand); void CheckVirtualDtorCall(CXXDestructorDecl *dtor, SourceLocation Loc, @@ -6865,6 +8282,10 @@ public: bool IsTemplateArgument = false); StmtResult ActOnFinishFullStmt(Stmt *Stmt); + /// Process the expression contained within a decltype. For such expressions, + /// certain semantic checks on temporaries are delayed until this point, and + /// are omitted for the 'topmost' call in the decltype expression. If the + /// topmost call bound a temporary, strip that temporary off the expression. ExprResult ActOnDecltypeExpression(Expr *E); bool checkLiteralOperatorId(const CXXScopeSpec &SS, const UnqualifiedId &Id, @@ -6876,18 +8297,35 @@ public: SourceLocation StmtLoc, ConditionKind CK); + /// Check the use of the given variable as a C++ condition in an if, + /// while, do-while, or switch statement. ExprResult CheckConditionVariable(VarDecl *ConditionVar, SourceLocation StmtLoc, ConditionKind CK); /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. ExprResult CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr = false); + /// Helper function to determine whether this is the (deprecated) C++ + /// conversion from a string literal to a pointer to non-const char or + /// non-const wchar_t (for narrow and wide string literals, + /// respectively). bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType); + /// PerformImplicitConversion - Perform an implicit conversion of the + /// expression From to the type ToType using the pre-computed implicit + /// conversion sequence ICS. Returns the converted + /// expression. Action is the kind of conversion we're performing, + /// used in the error message. ExprResult PerformImplicitConversion( Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK = CheckedConversionKind::Implicit); + + /// PerformImplicitConversion - Perform an implicit conversion of the + /// expression From to the type ToType by following the standard + /// conversion sequence SCS. Returns the converted + /// expression. Flavor is the context in which we're performing this + /// conversion, for use in error messages. ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const StandardConversionSequence &SCS, AssignmentAction Action, @@ -6932,10 +8370,42 @@ public: ExprResult &LHS, ExprResult &RHS, SourceLocation QuestionLoc); + /// Check the operands of ?: under C++ semantics. + /// + /// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y + /// extension. In this case, LHS == Cond. (But they're not aliases.) + /// + /// This function also implements GCC's vector extension and the + /// OpenCL/ext_vector_type extension for conditionals. The vector extensions + /// permit the use of a?b:c where the type of a is that of a integer vector + /// with the same number of elements and size as the vectors of b and c. If + /// one of either b or c is a scalar it is implicitly converted to match the + /// type of the vector. Otherwise the expression is ill-formed. If both b and + /// c are scalars, then b and c are checked and converted to the type of a if + /// possible. + /// + /// The expressions are evaluated differently for GCC's and OpenCL's + /// extensions. For the GCC extension, the ?: operator is evaluated as + /// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]). + /// For the OpenCL extensions, the ?: operator is evaluated as + /// (most-significant-bit-set(a[0]) ? b[0] : c[0], .. , + /// most-significant-bit-set(a[n]) ? b[n] : c[n]). QualType CXXCheckConditionalOperands( // C++ 5.16 ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); + /// Find a merged pointer type and convert the two expressions to it. + /// + /// This finds the composite pointer type for \p E1 and \p E2 according to + /// C++2a [expr.type]p3. It converts both expressions to this type and returns + /// it. It does not emit diagnostics (FIXME: that's not true if \p + /// ConvertArgs is \c true). + /// + /// \param Loc The location of the operator requiring these two expressions to + /// be converted to the composite pointer type. + /// + /// \param ConvertArgs If \c false, do not convert E1 and E2 to the target + /// type. QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool ConvertArgs = true); QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1, @@ -7083,10 +8553,15 @@ public: bool isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, LookupResult &R, bool IsAddressOfOperand); + /// Builds an expression which might be an implicit member expression. ExprResult BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, const Scope *S); + /// Builds an implicit member access expression. The current context + /// is known to be an instance method, and the given unqualified lookup + /// set is known to contain only instance members, at least one of which + /// is from an appropriate type. ExprResult BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, @@ -7099,6 +8574,16 @@ public: NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs); + /// The main callback when the parser finds something like + /// expression . [nested-name-specifier] identifier + /// expression -> [nested-name-specifier] identifier + /// where 'identifier' encompasses a fairly broad spectrum of + /// possibilities, including destructor and operator references. + /// + /// \param OpKind either tok::arrow or tok::period + /// \param ObjCImpDecl the current Objective-C \@implementation + /// decl; this is an ugly hack around the fact that Objective-C + /// \@implementations aren't properly put in the context chain ExprResult ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, @@ -7113,6 +8598,18 @@ public: ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs = nullptr); + // Check whether the declarations we found through a nested-name + // specifier in a member expression are actually members of the base + // type. The restriction here is: + // + // C++ [expr.ref]p2: + // ... In these cases, the id-expression shall name a + // member of the class or of one of its base classes. + // + // So it's perfectly legitimate for the nested-name specifier to name + // an unrelated class, and for us to find an overload set including + // decls from classes which are not superclasses, as long as the decl + // we actually pick through overload resolution is from a superclass. bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, const CXXScopeSpec &SS, const LookupResult &R); @@ -7150,6 +8647,7 @@ public: DeclAccessPair FoundDecl, const DeclarationNameInfo &MemberNameInfo); + /// Perform conversions on the LHS of a member access expression. ExprResult PerformMemberExprBaseConversion(Expr *Base, bool IsArrow); ExprResult BuildAnonymousStructUnionMemberReference( @@ -7183,6 +8681,8 @@ public: bool IsStringInit(Expr *Init, const ArrayType *AT); + /// Determine whether we can perform aggregate initialization for the purposes + /// of overload resolution. bool CanPerformAggregateInitializationForOverloadResolution( const InitializedEntity &Entity, InitListExpr *From); @@ -7585,35 +9085,158 @@ public: Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration); + + /// Lookup a builtin function, when name lookup would otherwise + /// fail. bool LookupBuiltin(LookupResult &R); void LookupNecessaryTypesForBuiltin(Scope *S, unsigned ID); + + /// Perform unqualified name lookup starting from a given + /// scope. + /// + /// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is + /// used to find names within the current scope. For example, 'x' in + /// @code + /// int x; + /// int f() { + /// return x; // unqualified name look finds 'x' in the global scope + /// } + /// @endcode + /// + /// Different lookup criteria can find different names. For example, a + /// particular scope can have both a struct and a function of the same + /// name, and each can be found by certain lookup criteria. For more + /// information about lookup criteria, see the documentation for the + /// class LookupCriteria. + /// + /// @param S The scope from which unqualified name lookup will + /// begin. If the lookup criteria permits, name lookup may also search + /// in the parent scopes. + /// + /// @param [in,out] R Specifies the lookup to perform (e.g., the name to + /// look up and the lookup kind), and is updated with the results of lookup + /// including zero or more declarations and possibly additional information + /// used to diagnose ambiguities. + /// + /// @returns \c true if lookup succeeded and false otherwise. bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation = false, bool ForceNoCPlusPlus = false); + + /// Perform qualified name lookup into a given context. + /// + /// Qualified name lookup (C++ [basic.lookup.qual]) is used to find + /// names when the context of those names is explicit specified, e.g., + /// "std::vector" or "x->member", or as part of unqualified name lookup. + /// + /// Different lookup criteria can find different names. For example, a + /// particular scope can have both a struct and a function of the same + /// name, and each can be found by certain lookup criteria. For more + /// information about lookup criteria, see the documentation for the + /// class LookupCriteria. + /// + /// \param R captures both the lookup criteria and any lookup results found. + /// + /// \param LookupCtx The context in which qualified name lookup will + /// search. If the lookup criteria permits, name lookup may also search + /// in the parent contexts or (for C++ classes) base classes. + /// + /// \param InUnqualifiedLookup true if this is qualified name lookup that + /// occurs as part of unqualified name lookup. + /// + /// \returns true if lookup succeeded, false if it failed. bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup = false); + + /// Performs qualified name lookup or special type of lookup for + /// "__super::" scope specifier. + /// + /// This routine is a convenience overload meant to be called from contexts + /// that need to perform a qualified name lookup with an optional C++ scope + /// specifier that might require special kind of lookup. + /// + /// \param R captures both the lookup criteria and any lookup results found. + /// + /// \param LookupCtx The context in which qualified name lookup will + /// search. + /// + /// \param SS An optional C++ scope-specifier. + /// + /// \returns true if lookup succeeded, false if it failed. bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, CXXScopeSpec &SS); + + /// Performs name lookup for a name that was parsed in the + /// source code, and may contain a C++ scope specifier. + /// + /// This routine is a convenience routine meant to be called from + /// contexts that receive a name and an optional C++ scope specifier + /// (e.g., "N::M::x"). It will then perform either qualified or + /// unqualified name lookup (with LookupQualifiedName or LookupName, + /// respectively) on the given name and return those results. It will + /// perform a special type of lookup for "__super::" scope specifier. + /// + /// @param S The scope from which unqualified name lookup will + /// begin. + /// + /// @param SS An optional C++ scope-specifier, e.g., "::N::M". + /// + /// @param EnteringContext Indicates whether we are going to enter the + /// context of the scope-specifier SS (if present). + /// + /// @returns True if any decls were found (but possibly ambiguous) bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation = false, bool EnteringContext = false); + + /// Perform qualified name lookup into all base classes of the given + /// class. + /// + /// \param R captures both the lookup criteria and any lookup results found. + /// + /// \param Class The context in which qualified name lookup will + /// search. Name lookup will search in all base classes merging the results. + /// + /// @returns True if any decls were found (but possibly ambiguous) bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class); void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, UnresolvedSetImpl &Functions); + /// LookupOrCreateLabel - Do a name lookup of a label with the specified name. + /// If GnuLabelLoc is a valid source location, then this is a definition + /// of an __label__ label name, otherwise it is a normal label definition + /// or use. LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, SourceLocation GnuLabelLoc = SourceLocation()); + /// Look up the constructors for the given class. DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); + + /// Look up the default constructor for the given class. CXXConstructorDecl *LookupDefaultConstructor(CXXRecordDecl *Class); + + /// Look up the copying constructor for the given class. CXXConstructorDecl *LookupCopyingConstructor(CXXRecordDecl *Class, unsigned Quals); + + /// Look up the copying assignment operator for the given class. CXXMethodDecl *LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals, bool RValueThis, unsigned ThisQuals); + + /// Look up the moving constructor for the given class. CXXConstructorDecl *LookupMovingConstructor(CXXRecordDecl *Class, unsigned Quals); + + /// Look up the moving assignment operator for the given class. CXXMethodDecl *LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals, bool RValueThis, unsigned ThisQuals); + + /// Look for the destructor of the given class. + /// + /// During semantic analysis, this routine should be used in lieu of + /// CXXRecordDecl::getDestructor(). + /// + /// \returns The destructor for this class. CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); /// Force the declaration of any implicitly-declared members of this @@ -7702,18 +9325,49 @@ public: const PartialDiagnostic &TypoDiag, bool ErrorRecovery = true); + /// Diagnose a successfully-corrected typo. Separated from the correction + /// itself to allow external validation of the result, etc. + /// + /// \param Correction The result of performing typo correction. + /// \param TypoDiag The diagnostic to produce. This will have the corrected + /// string added to it (and usually also a fixit). + /// \param PrevNote A note to use when indicating the location of the entity + /// to which we are correcting. Will have the correction string added + /// to it. + /// \param ErrorRecovery If \c true (the default), the caller is going to + /// recover from the typo as if the corrected string had been typed. + /// In this case, \c PDiag must be an error, and we will attach a fixit + /// to it. void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, const PartialDiagnostic &PrevNote, bool ErrorRecovery = true); + /// Find the associated classes and namespaces for + /// argument-dependent lookup for a call with the given set of + /// arguments. + /// + /// This routine computes the sets of associated classes and associated + /// namespaces searched by argument-dependent lookup + /// (C++ [basic.lookup.argdep]) for a given set of arguments. void FindAssociatedClassesAndNamespaces( SourceLocation InstantiationLoc, ArrayRef<Expr *> Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses); + /// Produce a diagnostic describing the ambiguity that resulted + /// from name lookup. + /// + /// \param Result The result of the ambiguous lookup to be diagnosed. void DiagnoseAmbiguousLookup(LookupResult &Result); + /// LookupLiteralOperator - Determine which literal operator should be used + /// for a user-defined literal, per C++11 [lex.ext]. + /// + /// Normal overload resolution is not used to select which literal operator to + /// call for a user-defined literal. Look up the provided literal operator + /// name, and filter the results to the appropriate set for the given argument + /// types. LiteralOperatorLookupResult LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, bool AllowRaw, bool AllowTemplate, @@ -7738,6 +9392,37 @@ public: CTK_ErrorRecovery // CorrectTypo used in normal error recovery. }; + /// Try to "correct" a typo in the source code by finding + /// visible declarations whose names are similar to the name that was + /// present in the source code. + /// + /// \param TypoName the \c DeclarationNameInfo structure that contains + /// the name that was present in the source code along with its location. + /// + /// \param LookupKind the name-lookup criteria used to search for the name. + /// + /// \param S the scope in which name lookup occurs. + /// + /// \param SS the nested-name-specifier that precedes the name we're + /// looking for, if present. + /// + /// \param CCC A CorrectionCandidateCallback object that provides further + /// validation of typo correction candidates. It also provides flags for + /// determining the set of keywords permitted. + /// + /// \param MemberContext if non-NULL, the context in which to look for + /// a member access expression. + /// + /// \param EnteringContext whether we're entering the context described by + /// the nested-name-specifier SS. + /// + /// \param OPT when non-NULL, the search for visible declarations will + /// also walk the protocols in the qualified interfaces of \p OPT. + /// + /// \returns a \c TypoCorrection containing the corrected name if the typo + /// along with information such as the \c NamedDecl where the corrected name + /// was declared, and any additional \c NestedNameSpecifier needed to access + /// it (C++ only). The \c TypoCorrection is empty if there is no correction. TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, @@ -7747,6 +9432,44 @@ public: const ObjCObjectPointerType *OPT = nullptr, bool RecordFailure = true); + /// Try to "correct" a typo in the source code by finding + /// visible declarations whose names are similar to the name that was + /// present in the source code. + /// + /// \param TypoName the \c DeclarationNameInfo structure that contains + /// the name that was present in the source code along with its location. + /// + /// \param LookupKind the name-lookup criteria used to search for the name. + /// + /// \param S the scope in which name lookup occurs. + /// + /// \param SS the nested-name-specifier that precedes the name we're + /// looking for, if present. + /// + /// \param CCC A CorrectionCandidateCallback object that provides further + /// validation of typo correction candidates. It also provides flags for + /// determining the set of keywords permitted. + /// + /// \param TDG A TypoDiagnosticGenerator functor that will be used to print + /// diagnostics when the actual typo correction is attempted. + /// + /// \param TRC A TypoRecoveryCallback functor that will be used to build an + /// Expr from a typo correction candidate. + /// + /// \param MemberContext if non-NULL, the context in which to look for + /// a member access expression. + /// + /// \param EnteringContext whether we're entering the context described by + /// the nested-name-specifier SS. + /// + /// \param OPT when non-NULL, the search for visible declarations will + /// also walk the protocols in the qualified interfaces of \p OPT. + /// + /// \returns a new \c TypoExpr that will later be replaced in the AST with an + /// Expr representing the result of performing typo correction, or nullptr if + /// typo correction is not possible. If nullptr is returned, no diagnostics + /// will be emitted and it is the responsibility of the caller to emit any + /// that are needed. TypoExpr *CorrectTypoDelayed( const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, @@ -7805,6 +9528,7 @@ private: bool CppLookupName(LookupResult &R, Scope *S); + /// Determine if we could use all the declarations in the module. bool isUsableModule(const Module *M); /// Helper for CorrectTypo and CorrectTypoDelayed used to create and @@ -7963,8 +9687,12 @@ public: void createImplicitModuleImportForErrorRecovery(SourceLocation Loc, Module *Mod); + /// We have parsed the start of an export declaration, including the '{' + /// (if present). Decl *ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, SourceLocation LBraceLoc); + + /// Complete the definition of an export declaration. Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl, SourceLocation RBraceLoc); @@ -8066,6 +9794,40 @@ public: /// non-function. Ovl_NonFunction }; + + /// Determine whether the given New declaration is an overload of the + /// declarations in Old. This routine returns Ovl_Match or Ovl_NonFunction if + /// New and Old cannot be overloaded, e.g., if New has the same signature as + /// some function in Old (C++ 1.3.10) or if the Old declarations aren't + /// functions (or function templates) at all. When it does return Ovl_Match or + /// Ovl_NonFunction, MatchedDecl will point to the decl that New cannot be + /// overloaded with. This decl may be a UsingShadowDecl on top of the + /// underlying declaration. + /// + /// Example: Given the following input: + /// + /// void f(int, float); // #1 + /// void f(int, int); // #2 + /// int f(int, int); // #3 + /// + /// When we process #1, there is no previous declaration of "f", so IsOverload + /// will not be used. + /// + /// When we process #2, Old contains only the FunctionDecl for #1. By + /// comparing the parameter types, we see that #1 and #2 are overloaded (since + /// they have different signatures), so this routine returns Ovl_Overload; + /// MatchedDecl is unchanged. + /// + /// When we process #3, Old is an overload set containing #1 and #2. We + /// compare the signatures of #3 to #1 (they're overloaded, so we do nothing) + /// and then #3 to #2. Since the signatures of #3 and #2 are identical (return + /// types of functions are not part of the signature), IsOverload returns + /// Ovl_Match and MatchedDecl will be set to point to the FunctionDecl for #2. + /// + /// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced into a + /// class by a using declaration. The rules for whether to hide shadow + /// declarations ignore some properties which otherwise figure into a function + /// template's signature. OverloadKind CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &OldDecls, NamedDecl *&OldDecl, bool UseMemberUsingDeclRules); @@ -8091,21 +9853,68 @@ public: AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion); + /// PerformImplicitConversion - Perform an implicit conversion of the + /// expression From to the type ToType. Returns the + /// converted expression. Flavor is the kind of conversion we're + /// performing, used in the error message. If @p AllowExplicit, + /// explicit user-defined conversions are permitted. ExprResult PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit = false); + /// IsIntegralPromotion - Determines whether the conversion from the + /// expression From (whose potentially-adjusted type is FromType) to + /// ToType is an integral promotion (C++ 4.5). If so, returns true and + /// sets PromotedType to the promoted type. bool IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType); + + /// IsFloatingPointPromotion - Determines whether the conversion from + /// FromType to ToType is a floating point promotion (C++ 4.6). If so, + /// returns true and sets PromotedType to the promoted type. bool IsFloatingPointPromotion(QualType FromType, QualType ToType); + + /// Determine if a conversion is a complex promotion. + /// + /// A complex promotion is defined as a complex -> complex conversion + /// where the conversion between the underlying real types is a + /// floating-point or integral promotion. bool IsComplexPromotion(QualType FromType, QualType ToType); + + /// IsPointerConversion - Determines whether the conversion of the + /// expression From, which has the (possibly adjusted) type FromType, + /// can be converted to the type ToType via a pointer conversion (C++ + /// 4.10). If so, returns true and places the converted type (that + /// might differ from ToType in its cv-qualifiers at some level) into + /// ConvertedType. + /// + /// This routine also supports conversions to and from block pointers + /// and conversions with Objective-C's 'id', 'id<protocols...>', and + /// pointers to interfaces. FIXME: Once we've determined the + /// appropriate overloading rules for Objective-C, we may want to + /// split the Objective-C checks into a different routine; however, + /// GCC seems to consider all of these conversions to be pointer + /// conversions, so for now they live here. IncompatibleObjC will be + /// set if the conversion is an allowed Objective-C conversion that + /// should result in a warning. bool IsPointerConversion(Expr *From, QualType FromType, QualType ToType, bool InOverloadResolution, QualType &ConvertedType, bool &IncompatibleObjC); + + /// isObjCPointerConversion - Determines whether this is an + /// Objective-C pointer conversion. Subroutine of IsPointerConversion, + /// with the same arguments and return values. bool isObjCPointerConversion(QualType FromType, QualType ToType, QualType &ConvertedType, bool &IncompatibleObjC); bool IsBlockPointerConversion(QualType FromType, QualType ToType, QualType &ConvertedType); + /// FunctionParamTypesAreEqual - This routine checks two function proto types + /// for equality of their parameter types. Caller has already checked that + /// they have same number of parameters. If the parameters are different, + /// ArgPos will have the parameter index of the first different parameter. + /// If `Reversed` is true, the parameters of `NewType` will be compared in + /// reverse order. That's useful if one of the functions is being used as a + /// C++20 synthesized operator overload with a reversed parameter order. bool FunctionParamTypesAreEqual(ArrayRef<QualType> Old, ArrayRef<QualType> New, unsigned *ArgPos = nullptr, @@ -8121,20 +9930,54 @@ public: unsigned *ArgPos = nullptr, bool Reversed = false); + /// HandleFunctionTypeMismatch - Gives diagnostic information for differeing + /// function types. Catches different number of parameter, mismatch in + /// parameter types, and different return types. void HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, QualType FromType, QualType ToType); + /// CheckPointerConversion - Check the pointer conversion from the + /// expression From to the type ToType. This routine checks for + /// ambiguous or inaccessible derived-to-base pointer + /// conversions for which IsPointerConversion has already returned + /// true. It returns true and produces a diagnostic if there was an + /// error, or returns false otherwise. bool CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind, CXXCastPath &BasePath, bool IgnoreBaseAccess, bool Diagnose = true); + + /// IsMemberPointerConversion - Determines whether the conversion of the + /// expression From, which has the (possibly adjusted) type FromType, can be + /// converted to the type ToType via a member pointer conversion (C++ 4.11). + /// If so, returns true and places the converted type (that might differ from + /// ToType in its cv-qualifiers at some level) into ConvertedType. bool IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, bool InOverloadResolution, QualType &ConvertedType); + + /// CheckMemberPointerConversion - Check the member pointer conversion from + /// the expression From to the type ToType. This routine checks for ambiguous + /// or virtual or inaccessible base-to-derived member pointer conversions for + /// which IsMemberPointerConversion has already returned true. It returns true + /// and produces a diagnostic if there was an error, or returns false + /// otherwise. bool CheckMemberPointerConversion(Expr *From, QualType ToType, CastKind &Kind, CXXCastPath &BasePath, bool IgnoreBaseAccess); + + /// IsQualificationConversion - Determines whether the conversion from + /// an rvalue of type FromType to ToType is a qualification conversion + /// (C++ 4.4). + /// + /// \param ObjCLifetimeConversion Output parameter that will be set to + /// indicate when the qualification conversion involves a change in the + /// Objective-C object lifetime. bool IsQualificationConversion(QualType FromType, QualType ToType, bool CStyle, bool &ObjCLifetimeConversion); + + /// Determine whether the conversion from FromType to ToType is a valid + /// conversion that strips "noexcept" or "noreturn" off the nested function + /// type. bool IsFunctionConversion(QualType FromType, QualType ToType, QualType &ResultTy); bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); @@ -8150,7 +9993,13 @@ public: Expr *From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, CXXMethodDecl *Method); + /// PerformContextuallyConvertToBool - Perform a contextual conversion + /// of the expression From to bool (C++0x [conv]p3). ExprResult PerformContextuallyConvertToBool(Expr *From); + + /// PerformContextuallyConvertToObjCPointer - Perform a contextual + /// conversion of the expression From to an Objective-C pointer type. + /// Returns a valid but null ExprResult if no conversion sequence exists. ExprResult PerformContextuallyConvertToObjCPointer(Expr *From); /// Contexts in which a converted constant expression is required. @@ -8177,6 +10026,9 @@ public: APValue &Value, CCEKind CCE, NamedDecl *Dest = nullptr); + /// EvaluateConvertedConstantExpression - Evaluate an Expression + /// That is a converted constant expression + /// (which was built with BuildConvertedConstantExpression) ExprResult EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, CCEKind CCE, bool RequireInt, @@ -8297,10 +10149,24 @@ public: }; using ReferenceConversions = ReferenceConversionsScope::ReferenceConversions; + /// CompareReferenceRelationship - Compare the two types T1 and T2 to + /// determine whether they are reference-compatible, + /// reference-related, or incompatible, for use in C++ initialization by + /// reference (C++ [dcl.ref.init]p4). Neither type can be a reference + /// type, and the first type (T1) is the pointee type of the reference + /// type being initialized. ReferenceCompareResult CompareReferenceRelationship(SourceLocation Loc, QualType T1, QualType T2, ReferenceConversions *Conv = nullptr); + /// AddOverloadCandidate - Adds the given function to the set of + /// candidate functions, using the given function call arguments. If + /// @p SuppressUserConversions, then don't allow user-defined + /// conversions via constructors or conversion operators. + /// + /// \param PartialOverloading true if we are performing "partial" overloading + /// based on an incomplete set of function arguments. This feature is used by + /// code completion. void AddOverloadCandidate( FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, @@ -8310,18 +10176,32 @@ public: ConversionSequenceList EarlyConversions = std::nullopt, OverloadCandidateParamOrder PO = {}, bool AggregateCandidateDeduction = false); + + /// Add all of the function declarations in the given function set to + /// the overload candidate set. void AddFunctionCandidates( const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, bool SuppressUserConversions = false, bool PartialOverloading = false, bool FirstArgumentIsBase = false); + + /// AddMethodCandidate - Adds a named decl (which is some kind of + /// method) as a method candidate to the given overload set. void AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversion = false, OverloadCandidateParamOrder PO = {}); + + /// AddMethodCandidate - Adds the given C++ member function to the set + /// of candidate functions, using the given function call arguments + /// and the object argument (@c Object). For example, in a call + /// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain + /// both @c a1 and @c a2. If @p SuppressUserConversions, then don't + /// allow user-defined conversions via constructors or conversion + /// operators. void AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, @@ -8331,6 +10211,10 @@ public: bool PartialOverloading = false, ConversionSequenceList EarlyConversions = std::nullopt, OverloadCandidateParamOrder PO = {}); + + /// Add a C++ member function template as a candidate to the candidate + /// set, using template argument deduction to produce an appropriate member + /// function template specialization. void AddMethodTemplateCandidate( FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -8338,6 +10222,10 @@ public: Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions = false, bool PartialOverloading = false, OverloadCandidateParamOrder PO = {}); + + /// Add a C++ function template specialization as a candidate + /// in the candidate set, using template argument deduction to produce + /// an appropriate function template specialization. void AddTemplateOverloadCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, @@ -8346,6 +10234,10 @@ public: ADLCallKind IsADLCandidate = ADLCallKind::NotADL, OverloadCandidateParamOrder PO = {}, bool AggregateCandidateDeduction = false); + + /// Check that implicit conversion sequences can be formed for each argument + /// whose corresponding parameter has a non-dependent type, per DR1391's + /// [temp.deduct.call]p10. bool CheckNonDependentConversions( FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -8353,37 +10245,91 @@ public: CXXRecordDecl *ActingContext = nullptr, QualType ObjectType = QualType(), Expr::Classification ObjectClassification = {}, OverloadCandidateParamOrder PO = {}); + + /// AddConversionCandidate - Add a C++ conversion function as a + /// candidate in the candidate set (C++ [over.match.conv], + /// C++ [over.match.copy]). From is the expression we're converting from, + /// and ToType is the type that we're eventually trying to convert to + /// (which may or may not be the same type as the type that the + /// conversion function produces). void AddConversionCandidate( CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, bool AllowExplicit, bool AllowResultConversion = true); + + /// Adds a conversion function template specialization + /// candidate to the overload set, using template argument deduction + /// to deduce the template arguments of the conversion function + /// template from the type that we are converting to (C++ + /// [temp.deduct.conv]). void AddTemplateConversionCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, bool AllowExplicit, bool AllowResultConversion = true); + + /// AddSurrogateCandidate - Adds a "surrogate" candidate function that + /// converts the given @c Object to a function pointer via the + /// conversion function @c Conversion, and then attempts to call it + /// with the given arguments (C++ [over.call.object]p2-4). Proto is + /// the type of function that we'll eventually be calling. void AddSurrogateCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, Expr *Object, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet); + + /// Add all of the non-member operator function declarations in the given + /// function set to the overload candidate set. void AddNonMemberOperatorCandidates( const UnresolvedSetImpl &Functions, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); + + /// Add overload candidates for overloaded operators that are + /// member functions. + /// + /// Add the overloaded operator candidates that are member functions + /// for the operator Op that was used in an operator expression such + /// as "x Op y". , Args/NumArgs provides the operator arguments, and + /// CandidateSet will store the added overload candidates. (C++ + /// [over.match.oper]). void AddMemberOperatorCandidates(OverloadedOperatorKind Op, SourceLocation OpLoc, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, OverloadCandidateParamOrder PO = {}); + + /// AddBuiltinCandidate - Add a candidate for a built-in + /// operator. ResultTy and ParamTys are the result and parameter types + /// of the built-in candidate, respectively. Args and NumArgs are the + /// arguments being passed to the candidate. IsAssignmentOperator + /// should be true when this built-in candidate is an assignment + /// operator. NumContextualBoolArguments is the number of arguments + /// (at the beginning of the argument list) that will be contextually + /// converted to bool. void AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool IsAssignmentOperator = false, unsigned NumContextualBoolArguments = 0); + + /// AddBuiltinOperatorCandidates - Add the appropriate built-in + /// operator overloads to the candidate set (C++ [over.built]), based + /// on the operator @p Op and the arguments given. For example, if the + /// operator is a binary '+', this routine might add "int + /// operator+(int, int)" to cover integer addition. void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, SourceLocation OpLoc, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet); + + /// Add function candidates found via argument-dependent lookup + /// to the set of overloading candidates. + /// + /// This routine performs argument-dependent name lookup based on the + /// given function name (which may also be an operator name) and adds + /// all of the overload candidates found by ADL to the overload + /// candidate set (C++ [basic.lookup.argdep]). void AddArgumentDependentLookupCandidates( DeclarationName Name, SourceLocation Loc, ArrayRef<Expr *> Args, TemplateArgumentListInfo *ExplicitTemplateArgs, @@ -8453,31 +10399,83 @@ public: // R (S::*)(A) --> R (A) QualType ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType); + /// ResolveAddressOfOverloadedFunction - Try to resolve the address of + /// an overloaded function (C++ [over.over]), where @p From is an + /// expression with overloaded function type and @p ToType is the type + /// we're trying to resolve to. For example: + /// + /// @code + /// int f(double); + /// int f(int); + /// + /// int (*pfd)(double) = f; // selects f(double) + /// @endcode + /// + /// This routine returns the resulting FunctionDecl if it could be + /// resolved, and NULL otherwise. When @p Complain is true, this + /// routine will emit diagnostics if there is an error. FunctionDecl * ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, bool Complain, DeclAccessPair &Found, bool *pHadMultipleCandidates = nullptr); + /// Given an expression that refers to an overloaded function, try to + /// resolve that function to a single function that can have its address + /// taken. This will modify `Pair` iff it returns non-null. + /// + /// This routine can only succeed if from all of the candidates in the + /// overload set for SrcExpr that can have their addresses taken, there is one + /// candidate that is more constrained than the rest. FunctionDecl * resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &FoundResult); + /// Given an overloaded function, tries to turn it into a non-overloaded + /// function reference using resolveAddressOfSingleOverloadCandidate. This + /// will perform access checks, diagnose the use of the resultant decl, and, + /// if requested, potentially perform a function-to-pointer decay. + /// + /// Returns false if resolveAddressOfSingleOverloadCandidate fails. + /// Otherwise, returns true. This may emit diagnostics and return true. bool resolveAndFixAddressOfSingleOverloadCandidate( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false); + /// Given an expression that refers to an overloaded function, try to + /// resolve that overloaded function expression down to a single function. + /// + /// This routine can only resolve template-ids that refer to a single function + /// template, where that template-id refers to a single template whose + /// template arguments are either provided by the template-id or have + /// defaults, as described in C++0x [temp.arg.explicit]p3. + /// + /// If no template-ids are found, no diagnostics are emitted and NULL is + /// returned. FunctionDecl *ResolveSingleFunctionTemplateSpecialization( OverloadExpr *ovl, bool Complain = false, DeclAccessPair *Found = nullptr, TemplateSpecCandidateSet *FailedTSC = nullptr); + // Resolve and fix an overloaded expression that can be resolved + // because it identifies a single function template specialization. + // + // Last three arguments should only be supplied if Complain = true + // + // Return true if it was logically possible to so resolve the + // expression, regardless of whether or not it succeeded. Always + // returns true if 'complain' is set. bool ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool DoFunctionPointerConversion = false, bool Complain = false, SourceRange OpRangeForComplaining = SourceRange(), QualType DestTypeForComplaining = QualType(), unsigned DiagIDForComplaining = 0); + /// Add the overload candidates named by callee and/or found by argument + /// dependent lookup to the given overload set. void AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool PartialOverloading = false); + + /// Add the call candidates from the given set of lookup results to the given + /// overload set. Non-function lookup results are ignored. void AddOverloadedCallCandidates( LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet); @@ -8490,6 +10488,13 @@ public: FRS_DiagnosticIssued }; + /// Build a call to 'begin' or 'end' for a C++11 for-range statement. If the + /// given LookupResult is non-empty, it is assumed to describe a member which + /// will be invoked. Otherwise, the function will be found via argument + /// dependent lookup. + /// CallExpr is set to a valid expression and FRS_Success returned on success, + /// otherwise CallExpr is set to ExprError() and some non-success value + /// is returned. ForRangeStatus BuildForRangeBeginEndCall(SourceLocation Loc, SourceLocation RangeLoc, const DeclarationNameInfo &NameInfo, @@ -8497,11 +10502,20 @@ public: OverloadCandidateSet *CandidateSet, Expr *Range, ExprResult *CallExpr); + /// BuildOverloadedCallExpr - Given the call expression that calls Fn + /// (which eventually refers to the declaration Func) and the call + /// arguments Args/NumArgs, attempt to resolve the function call down + /// to a specific function. If overload resolution succeeds, returns + /// the call expression produced by overload resolution. + /// Otherwise, emits diagnostics and returns ExprError. ExprResult BuildOverloadedCallExpr( Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig, bool AllowTypoCorrection = true, bool CalleesAddressIsTaken = false); + /// Constructs and populates an OverloadedCandidateSet from + /// the given function. + /// \returns true when an the ExprResult output parameter has been set. bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, MultiExprArg Args, SourceLocation RParenLoc, OverloadCandidateSet *CandidateSet, @@ -8513,15 +10527,55 @@ public: const UnresolvedSetImpl &Fns, bool PerformADL = true); + /// Create a unary operation that may resolve to an overloaded + /// operator. + /// + /// \param OpLoc The location of the operator itself (e.g., '*'). + /// + /// \param Opc The UnaryOperatorKind that describes this operator. + /// + /// \param Fns The set of non-member functions that will be + /// considered by overload resolution. The caller needs to build this + /// set based on the context using, e.g., + /// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This + /// set should not contain any member functions; those will be added + /// by CreateOverloadedUnaryOp(). + /// + /// \param Input The input argument. ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *input, bool RequiresADL = true); + /// Perform lookup for an overloaded binary operator. void LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet, OverloadedOperatorKind Op, const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, bool RequiresADL = true); + + /// Create a binary operation that may resolve to an overloaded + /// operator. + /// + /// \param OpLoc The location of the operator itself (e.g., '+'). + /// + /// \param Opc The BinaryOperatorKind that describes this operator. + /// + /// \param Fns The set of non-member functions that will be + /// considered by overload resolution. The caller needs to build this + /// set based on the context using, e.g., + /// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This + /// set should not contain any member functions; those will be added + /// by CreateOverloadedBinOp(). + /// + /// \param LHS Left-hand argument. + /// \param RHS Right-hand argument. + /// \param PerformADL Whether to consider operator candidates found by ADL. + /// \param AllowRewrittenCandidates Whether to consider candidates found by + /// C++20 operator rewrites. + /// \param DefaultedFn If we are synthesizing a defaulted operator function, + /// the function in question. Such a function is never a candidate in + /// our overload resolution. This also enables synthesizing a three-way + /// comparison from < and == as described in C++20 [class.spaceship]p1. ExprResult CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS, bool RequiresADL = true, @@ -8536,15 +10590,30 @@ public: SourceLocation RLoc, Expr *Base, MultiExprArg Args); + /// BuildCallToMemberFunction - Build a call to a member + /// function. MemExpr is the expression that refers to the member + /// function (and includes the object parameter), Args/NumArgs are the + /// arguments to the function call (not including the object + /// parameter). The caller needs to validate that the member + /// expression refers to a non-static member function or an overloaded + /// member function. ExprResult BuildCallToMemberFunction( Scope *S, Expr *MemExpr, SourceLocation LParenLoc, MultiExprArg Args, SourceLocation RParenLoc, Expr *ExecConfig = nullptr, bool IsExecConfig = false, bool AllowRecovery = false); + + /// BuildCallToObjectOfClassType - Build a call to an object of class + /// type (C++ [over.call.object]), which can end up invoking an + /// overloaded function call operator (@c operator()) or performing a + /// user-defined conversion on the object argument. ExprResult BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc, MultiExprArg Args, SourceLocation RParenLoc); + /// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> + /// (if one exists), where @c Base is an expression of class type and + /// @c Member is the name of the member we're trying to find. ExprResult BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound = nullptr); @@ -8553,11 +10622,18 @@ public: CXXConversionDecl *Method, bool HadMultipleCandidates); + /// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call + /// to a literal operator described by the provided lookup results. ExprResult BuildLiteralOperatorCall( LookupResult &R, DeclarationNameInfo &SuffixInfo, ArrayRef<Expr *> Args, SourceLocation LitEndLoc, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr); + /// FixOverloadedFunctionReference - E is an expression that refers to + /// a C++ overloaded function (possibly with some parentheses and + /// perhaps a '&' around it). We have resolved the overloaded function + /// to the function declaration Fn, so patch up the expression E to + /// refer (possibly indirectly) to Fn. Returns the new expr. ExprResult FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, FunctionDecl *Fn); ExprResult FixOverloadedFunctionReference(ExprResult, @@ -8612,6 +10688,8 @@ public: StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS, SourceLocation DotDotDotLoc, ExprResult RHS, SourceLocation ColonLoc); + + /// ActOnCaseStmtBody - This installs a statement as the body of a case. void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt); StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, @@ -8666,6 +10744,10 @@ public: FullExprArg Third, SourceLocation RParenLoc, Stmt *Body); + /// In an Objective C collection iteration statement: + /// for (x in y) + /// x can be an arbitrary l-value expression. Bind it up as a + /// full-expression. StmtResult ActOnForEachLValueExpr(Expr *E); enum BuildForRangeKind { @@ -8679,17 +10761,42 @@ public: BFRK_Check }; + /// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement. + /// + /// C++11 [stmt.ranged]: + /// A range-based for statement is equivalent to + /// + /// { + /// auto && __range = range-init; + /// for ( auto __begin = begin-expr, + /// __end = end-expr; + /// __begin != __end; + /// ++__begin ) { + /// for-range-declaration = *__begin; + /// statement + /// } + /// } + /// + /// The body of the loop is not available yet, since it cannot be analysed + /// until we have determined the type of the for-range-declaration. StmtResult ActOnCXXForRangeStmt( Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, Stmt *LoopVar, SourceLocation ColonLoc, Expr *Collection, SourceLocation RParenLoc, BuildForRangeKind Kind, ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps = {}); + + /// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. StmtResult BuildCXXForRangeStmt( SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, Expr *Cond, Expr *Inc, Stmt *LoopVarDecl, SourceLocation RParenLoc, BuildForRangeKind Kind, ArrayRef<MaterializeTemporaryExpr *> LifetimeExtendTemps = {}); + + /// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. + /// This is a separate step from ActOnCXXForRangeStmt because analysis of the + /// body cannot be performed until after the type of the range variable is + /// determined. StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body); StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, @@ -8709,12 +10816,54 @@ public: bool isCopyElidable() const { return S == MoveEligibleAndCopyElidable; } }; enum class SimplerImplicitMoveMode { ForceOff, Normal, ForceOn }; + + /// Determine whether the given expression might be move-eligible or + /// copy-elidable in either a (co_)return statement or throw expression, + /// without considering function return type, if applicable. + /// + /// \param E The expression being returned from the function or block, + /// being thrown, or being co_returned from a coroutine. This expression + /// might be modified by the implementation. + /// + /// \param Mode Overrides detection of current language mode + /// and uses the rules for C++23. + /// + /// \returns An aggregate which contains the Candidate and isMoveEligible + /// and isCopyElidable methods. If Candidate is non-null, it means + /// isMoveEligible() would be true under the most permissive language + /// standard. NamedReturnInfo getNamedReturnInfo( Expr *&E, SimplerImplicitMoveMode Mode = SimplerImplicitMoveMode::Normal); + + /// Determine whether the given NRVO candidate variable is move-eligible or + /// copy-elidable, without considering function return type. + /// + /// \param VD The NRVO candidate variable. + /// + /// \returns An aggregate which contains the Candidate and isMoveEligible + /// and isCopyElidable methods. If Candidate is non-null, it means + /// isMoveEligible() would be true under the most permissive language + /// standard. NamedReturnInfo getNamedReturnInfo(const VarDecl *VD); + + /// Updates given NamedReturnInfo's move-eligible and + /// copy-elidable statuses, considering the function + /// return type criteria as applicable to return statements. + /// + /// \param Info The NamedReturnInfo object to update. + /// + /// \param ReturnType This is the return type of the function. + /// \returns The copy elision candidate, in case the initial return expression + /// was copy elidable, or nullptr otherwise. const VarDecl *getCopyElisionCandidate(NamedReturnInfo &Info, QualType ReturnType); + /// Perform the initialization of a potentially-movable value, which + /// is the result of return value. + /// + /// This routine implements C++20 [class.copy.elision]p3, which attempts to + /// treat returned lvalues as rvalues in certain cases (to prefer move + /// construction), then falls back to treating them as lvalues if that failed. ExprResult PerformMoveOrCopyInitialization(const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value, @@ -8722,6 +10871,8 @@ public: TypeLoc getReturnTypeLoc(FunctionDecl *FD) const; + /// Deduce the return type for a function from a returned expression, per + /// C++1y [dcl.spec.auto]p6. bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, Expr *RetExpr, const AutoType *AT); @@ -8730,12 +10881,20 @@ public: Scope *CurScope); StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, bool AllowRecovery = false); + + /// ActOnCapScopeReturnStmt - Utility routine to type-check return statements + /// for capturing scopes. StmtResult ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, NamedReturnInfo &NRInfo, bool SupressSimplerImplicitMoves); + /// ActOnCXXCatchBlock - Takes an exception declaration and a handler block + /// and creates a proper catch handler from them. StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock); + + /// ActOnCXXTryBlock - Takes a try compound-statement and a number of + /// handlers and creates a try statement from them. StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, ArrayRef<Stmt *> Handlers); @@ -9001,6 +11160,8 @@ public: TemplateTy &SuggestedTemplate, TemplateNameKind &SuggestedKind); + /// Determine whether we would be unable to instantiate this template (because + /// it either has no definition, or is in the process of being instantiated). bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, NamedDecl *Instantiation, bool InstantiatedFromMember, @@ -9024,8 +11185,22 @@ public: /// Ignored when MSVC compatibility is enabled. void DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl, bool SupportedForCompatibility = false); + + /// AdjustDeclIfTemplate - If the given decl happens to be a template, reset + /// the parameter D to reference the templated declaration and return a + /// pointer to the template declaration. Otherwise, do nothing to D and return + /// null. TemplateDecl *AdjustDeclIfTemplate(Decl *&Decl); + /// ActOnTypeParameter - Called when a C++ template type parameter + /// (e.g., "typename T") has been parsed. Typename specifies whether + /// the keyword "typename" was used to declare the type parameter + /// (otherwise, "class" was used), and KeyLoc is the location of the + /// "class" or "typename" keyword. ParamName is the name of the + /// parameter (NULL indicates an unnamed template parameter) and + /// ParamNameLoc is the location of the parameter name (if any). + /// If the type parameter has a default argument, it will be added + /// later via ActOnTypeParameterDefault. NamedDecl *ActOnTypeParameter(Scope *S, bool Typename, SourceLocation EllipsisLoc, SourceLocation KeyLoc, @@ -9046,6 +11221,10 @@ public: SourceLocation EllipsisLoc, bool AllowUnexpandedPack); + /// Attach a type-constraint to a template parameter. + /// \returns true if an error occurred. This can happen if the + /// immediately-declared constraint could not be formed (e.g. incorrect number + /// of arguments for the named concept). bool AttachTypeConstraint(NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo, ConceptDecl *NamedConcept, NamedDecl *FoundDecl, @@ -9058,8 +11237,16 @@ public: NonTypeTemplateParmDecl *OrigConstrainedParm, SourceLocation EllipsisLoc); + /// Require the given type to be a structural type, and diagnose if it is not. + /// + /// \return \c true if an error was produced. bool RequireStructuralType(QualType T, SourceLocation Loc); + /// Check that the type of a non-type template parameter is + /// well-formed. + /// + /// \returns the (possibly-promoted) parameter type if valid; + /// otherwise, produces a diagnostic and returns a NULL type. QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, SourceLocation Loc); QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc); @@ -9068,12 +11255,19 @@ public: unsigned Depth, unsigned Position, SourceLocation EqualLoc, Expr *DefaultArg); + + /// ActOnTemplateTemplateParameter - Called when a C++ template template + /// parameter (e.g. T in template <template \<typename> class T> class array) + /// has been parsed. S is the current scope. NamedDecl *ActOnTemplateTemplateParameter( Scope *S, SourceLocation TmpLoc, TemplateParameterList *Params, bool Typename, SourceLocation EllipsisLoc, IdentifierInfo *ParamName, SourceLocation ParamNameLoc, unsigned Depth, unsigned Position, SourceLocation EqualLoc, ParsedTemplateArgument DefaultArg); + /// ActOnTemplateParameterList - Builds a TemplateParameterList, optionally + /// constrained by RequiresClause, that contains the template parameters in + /// Params. TemplateParameterList *ActOnTemplateParameterList( unsigned Depth, SourceLocation ExportLoc, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef<NamedDecl *> Params, @@ -9091,10 +11285,72 @@ public: TPC_TypeAliasTemplate }; + /// Checks the validity of a template parameter list, possibly + /// considering the template parameter list from a previous + /// declaration. + /// + /// If an "old" template parameter list is provided, it must be + /// equivalent (per TemplateParameterListsAreEqual) to the "new" + /// template parameter list. + /// + /// \param NewParams Template parameter list for a new template + /// declaration. This template parameter list will be updated with any + /// default arguments that are carried through from the previous + /// template parameter list. + /// + /// \param OldParams If provided, template parameter list from a + /// previous declaration of the same template. Default template + /// arguments will be merged from the old template parameter list to + /// the new template parameter list. + /// + /// \param TPC Describes the context in which we are checking the given + /// template parameter list. + /// + /// \param SkipBody If we might have already made a prior merged definition + /// of this template visible, the corresponding body-skipping information. + /// Default argument redefinition is not an error when skipping such a body, + /// because (under the ODR) we can assume the default arguments are the same + /// as the prior merged definition. + /// + /// \returns true if an error occurred, false otherwise. bool CheckTemplateParameterList(TemplateParameterList *NewParams, TemplateParameterList *OldParams, TemplateParamListContext TPC, SkipBodyInfo *SkipBody = nullptr); + + /// Match the given template parameter lists to the given scope + /// specifier, returning the template parameter list that applies to the + /// name. + /// + /// \param DeclStartLoc the start of the declaration that has a scope + /// specifier or a template parameter list. + /// + /// \param DeclLoc The location of the declaration itself. + /// + /// \param SS the scope specifier that will be matched to the given template + /// parameter lists. This scope specifier precedes a qualified name that is + /// being declared. + /// + /// \param TemplateId The template-id following the scope specifier, if there + /// is one. Used to check for a missing 'template<>'. + /// + /// \param ParamLists the template parameter lists, from the outermost to the + /// innermost template parameter lists. + /// + /// \param IsFriend Whether to apply the slightly different rules for + /// matching template parameters to scope specifiers in friend + /// declarations. + /// + /// \param IsMemberSpecialization will be set true if the scope specifier + /// denotes a fully-specialized type, and therefore this is a declaration of + /// a member specialization. + /// + /// \returns the template parameter list, if any, that corresponds to the + /// name that is preceded by the scope specifier @p SS. This template + /// parameter list may have template parameters (if we're declaring a + /// template) or may have no template parameters (if we're declaring a + /// template specialization), or may be NULL (if what we're declaring isn't + /// itself a template). TemplateParameterList *MatchTemplateParametersToScopeSpecifier( SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId, @@ -9111,9 +11367,15 @@ public: TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody = nullptr); + /// Translates template arguments as provided by the parser + /// into template arguments used by semantic analysis. void translateTemplateArguments(const ASTTemplateArgsPtr &In, TemplateArgumentListInfo &Out); + /// Convert a parsed type into a parsed template argument. This is mostly + /// trivial, except that we may have parsed a C++17 deduced class template + /// specialization type, in which case we should form a template template + /// argument instead of a type template argument. ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType); void NoteAllFoundTemplates(TemplateName Name); @@ -9177,12 +11439,28 @@ public: bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs); + // We actually only call this from template instantiation. ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, bool IsAddressOfOperand); + /// Form a template name from a name that is syntactically required to name a + /// template, either due to use of the 'template' keyword or because a name in + /// this syntactic context is assumed to name a template (C++ + /// [temp.names]p2-4). + /// + /// This action forms a template name given the name of the template and its + /// optional scope specifier. This is used when the 'template' keyword is used + /// or when the parsing context unambiguously treats a following '<' as + /// introducing a template argument list. Note that this may produce a + /// non-dependent template name if we can perform the lookup now and identify + /// the named template. + /// + /// For example, given "x.MetaFun::template apply", the scope specifier + /// \p SS will be "MetaFun::", \p TemplateKWLoc contains the location + /// of the "template" keyword, and "apply" is the \p Name. TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const UnqualifiedId &Name, @@ -9197,6 +11475,17 @@ public: MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody = nullptr); + /// Check the non-type template arguments of a class template + /// partial specialization according to C++ [temp.class.spec]p9. + /// + /// \param TemplateNameLoc the location of the template name. + /// \param PrimaryTemplate the template parameters of the primary class + /// template. + /// \param NumExplicit the number of explicitly-specified template arguments. + /// \param TemplateArgs the template arguments of the class template + /// partial specialization. + /// + /// \returns \c true if there was an error, \c false otherwise. bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, TemplateDecl *PrimaryTemplate, unsigned NumExplicitArgs, @@ -9210,22 +11499,99 @@ public: MultiTemplateParamsArg TemplateParameterLists, Declarator &D); + /// Diagnose cases where we have an explicit template specialization + /// before/after an explicit template instantiation, producing diagnostics + /// for those cases where they are required and determining whether the + /// new specialization/instantiation will have any effect. + /// + /// \param NewLoc the location of the new explicit specialization or + /// instantiation. + /// + /// \param NewTSK the kind of the new explicit specialization or + /// instantiation. + /// + /// \param PrevDecl the previous declaration of the entity. + /// + /// \param PrevTSK the kind of the old explicit specialization or + /// instantiatin. + /// + /// \param PrevPointOfInstantiation if valid, indicates where the previous + /// declaration was instantiated (either implicitly or explicitly). + /// + /// \param HasNoEffect will be set to true to indicate that the new + /// specialization or instantiation has no effect and should be ignored. + /// + /// \returns true if there was an error that should prevent the introduction + /// of the new declaration into the AST, false otherwise. bool CheckSpecializationInstantiationRedecl( SourceLocation NewLoc, TemplateSpecializationKind ActOnExplicitInstantiationNewTSK, NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK, SourceLocation PrevPtOfInstantiation, bool &SuppressNew); + /// Perform semantic analysis for the given dependent function + /// template specialization. + /// + /// The only possible way to get a dependent function template specialization + /// is with a friend declaration, like so: + /// + /// \code + /// template \<class T> void foo(T); + /// template \<class T> class A { + /// friend void foo<>(T); + /// }; + /// \endcode + /// + /// There really isn't any useful analysis we can do here, so we + /// just store the information. bool CheckDependentFunctionTemplateSpecialization( FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous); + /// Perform semantic analysis for the given function template + /// specialization. + /// + /// This routine performs all of the semantic analysis required for an + /// explicit function template specialization. On successful completion, + /// the function declaration \p FD will become a function template + /// specialization. + /// + /// \param FD the function declaration, which will be updated to become a + /// function template specialization. + /// + /// \param ExplicitTemplateArgs the explicitly-provided template arguments, + /// if any. Note that this may be valid info even when 0 arguments are + /// explicitly provided as in, e.g., \c void sort<>(char*, char*); + /// as it anyway contains info on the angle brackets locations. + /// + /// \param Previous the set of declarations that may be specialized by + /// this function specialization. + /// + /// \param QualifiedFriend whether this is a lookup for a qualified friend + /// declaration with no explicit template argument list that might be + /// befriending a function template specialization. bool CheckFunctionTemplateSpecialization( FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous, bool QualifiedFriend = false); + + /// Perform semantic analysis for the given non-template member + /// specialization. + /// + /// This routine performs all of the semantic analysis required for an + /// explicit member function specialization. On successful completion, + /// the function declaration \p FD will become a member function + /// specialization. + /// + /// \param Member the member declaration, which will be updated to become a + /// specialization. + /// + /// \param Previous the set of declarations, one of which may be specialized + /// by this function specialization; the set will be modified to contain the + /// redeclared member. bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); + // Explicit instantiation of a class template specialization DeclResult ActOnExplicitInstantiation( Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, @@ -9233,6 +11599,7 @@ public: SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc, const ParsedAttributesView &Attr); + // Explicit instantiation of a member class of a class template. DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, @@ -9244,12 +11611,19 @@ public: SourceLocation TemplateLoc, Declarator &D); + /// If the given template parameter has a default template + /// argument, substitute into that default template argument and + /// return the corresponding template argument. TemplateArgumentLoc SubstDefaultTemplateArgumentIfAvailable( TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, Decl *Param, ArrayRef<TemplateArgument> SugaredConverted, ArrayRef<TemplateArgument> CanonicalConverted, bool &HasDefaultArg); + /// Returns the top most location responsible for the definition of \p N. + /// If \p N is a a template specialization, this is the location + /// of the top of the instantiation stack. + /// Otherwise, the location of \p N is returned. SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const; /// Specifies the context in which a particular template @@ -9268,6 +11642,32 @@ public: CTAK_DeducedFromArrayBound }; + /// Check that the given template argument corresponds to the given + /// template parameter. + /// + /// \param Param The template parameter against which the argument will be + /// checked. + /// + /// \param Arg The template argument, which may be updated due to conversions. + /// + /// \param Template The template in which the template argument resides. + /// + /// \param TemplateLoc The location of the template name for the template + /// whose argument list we're matching. + /// + /// \param RAngleLoc The location of the right angle bracket ('>') that closes + /// the template argument list. + /// + /// \param ArgumentPackIndex The index into the argument pack where this + /// argument will be placed. Only valid if the parameter is a parameter pack. + /// + /// \param Converted The checked, converted argument will be added to the + /// end of this small vector. + /// + /// \param CTAK Describes how we arrived at this particular template argument: + /// explicitly written, deduced, etc. + /// + /// \returns true on error, false otherwise. bool CheckTemplateArgument(NamedDecl *Param, TemplateArgumentLoc &Arg, NamedDecl *Template, SourceLocation TemplateLoc, @@ -9324,12 +11724,31 @@ public: SmallVectorImpl<TemplateArgument> &SugaredConverted, SmallVectorImpl<TemplateArgument> &CanonicalConverted); + /// Check a template argument against its corresponding + /// template type parameter. + /// + /// This routine implements the semantics of C++ [temp.arg.type]. It + /// returns true if an error occurred, and false otherwise. bool CheckTemplateArgument(TypeSourceInfo *Arg); + + /// Check a template argument against its corresponding + /// non-type template parameter. + /// + /// This routine implements the semantics of C++ [temp.arg.nontype]. + /// If an error occurred, it returns ExprError(); otherwise, it + /// returns the converted template argument. \p ParamType is the + /// type of the non-type template parameter after it has been instantiated. ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *Arg, TemplateArgument &SugaredConverted, TemplateArgument &CanonicalConverted, CheckTemplateArgumentKind CTAK); + + /// Check a template argument against its corresponding + /// template template parameter. + /// + /// This routine implements the semantics of C++ [temp.arg.template]. + /// It returns true if an error occurred, and false otherwise. bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, TemplateArgumentLoc &Arg, bool IsDeduced); @@ -9338,6 +11757,10 @@ public: std::optional<SourceRange> ParamRange = {}); void NoteTemplateParameterLocation(const NamedDecl &Decl); + /// Given a non-type template argument that refers to a + /// declaration and the type of its corresponding non-type template + /// parameter, produce an expression that properly refers to that + /// declaration. ExprResult BuildExpressionFromDeclTemplateArgument( const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, NamedDecl *TemplateParam = nullptr); @@ -9429,6 +11852,29 @@ public: SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; } }; + /// Determine whether the given template parameter lists are + /// equivalent. + /// + /// \param New The new template parameter list, typically written in the + /// source code as part of a new template declaration. + /// + /// \param Old The old template parameter list, typically found via + /// name lookup of the template declared with this template parameter + /// list. + /// + /// \param Complain If true, this routine will produce a diagnostic if + /// the template parameter lists are not equivalent. + /// + /// \param Kind describes how we are to match the template parameter lists. + /// + /// \param TemplateArgLoc If this source location is valid, then we + /// are actually checking the template parameter list of a template + /// argument (New) against the template parameter list of its + /// corresponding template template parameter (Old). We produce + /// slightly different diagnostics in this scenario. + /// + /// \returns True if the template parameter lists are equal, false + /// otherwise. bool TemplateParameterListsAreEqual( const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New, const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, @@ -9443,6 +11889,10 @@ public: Kind, TemplateArgLoc); } + /// Check whether a template can be declared within this scope. + /// + /// If the template declaration is valid in this scope, returns + /// false. Otherwise, issues a diagnostic and returns true. bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); /// Called when the parser has parsed a C++ typename @@ -9492,15 +11942,46 @@ public: const IdentifierInfo &II, SourceLocation IILoc, bool DeducedTSTContext = true); + /// Rebuilds a type within the context of the current instantiation. + /// + /// The type \p T is part of the type of an out-of-line member definition of + /// a class template (or class template partial specialization) that was + /// parsed and constructed before we entered the scope of the class template + /// (or partial specialization thereof). This routine will rebuild that type + /// now that we have entered the declarator's scope, which may produce + /// different canonical types, e.g., + /// + /// \code + /// template<typename T> + /// struct X { + /// typedef T* pointer; + /// pointer data(); + /// }; + /// + /// template<typename T> + /// typename X<T>::pointer X<T>::data() { ... } + /// \endcode + /// + /// Here, the type "typename X<T>::pointer" will be created as a + /// DependentNameType, since we do not know that we can look into X<T> when we + /// parsed the type. This function will rebuild the type, performing the + /// lookup of "pointer" in X<T> and returning an ElaboratedType whose + /// canonical type is the same as the canonical type of T*, allowing the + /// return types of the out-of-line definition and the declaration to match. TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, SourceLocation Loc, DeclarationName Name); bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS); ExprResult RebuildExprInCurrentInstantiation(Expr *E); + + /// Rebuild the template parameters now that we know we're in a current + /// instantiation. bool RebuildTemplateParamsInCurrentInstantiation(TemplateParameterList *Params); + /// Produces a formatted string that describes the binding of + /// template parameters to template arguments. std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args); @@ -9514,6 +11995,9 @@ public: SourceLocation Less, SourceLocation Greater); + /// ActOnDependentIdExpression - Handle a dependent id-expression that + /// was just parsed. This is only possible with an explicit scope + /// specifier naming a dependent type. ExprResult ActOnDependentIdExpression( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, @@ -9662,8 +12146,28 @@ public: SuppressedDiagnosticsMap; SuppressedDiagnosticsMap SuppressedDiagnostics; + /// Compare types for equality with respect to possibly compatible + /// function types (noreturn adjustment, implicit calling conventions). If any + /// of parameter and argument is not a function, just perform type comparison. + /// + /// \param P the template parameter type. + /// + /// \param A the argument type. bool isSameOrCompatibleFunctionType(QualType Param, QualType Arg); + /// Allocate a TemplateArgumentLoc where all locations have + /// been initialized to the given location. + /// + /// \param Arg The template argument we are producing template argument + /// location information for. + /// + /// \param NTTPType For a declaration template argument, the type of + /// the non-type template parameter that corresponds to this template + /// argument. Can be null if no type sugar is available to add to the + /// type from the template argument. + /// + /// \param Loc The source location to use for the resulting template + /// argument. TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, @@ -9707,6 +12211,30 @@ public: SmallVectorImpl<DeducedTemplateArgument> &Deduced, bool NumberOfArgumentsMustMatch); + /// Substitute the explicitly-provided template arguments into the + /// given function template according to C++ [temp.arg.explicit]. + /// + /// \param FunctionTemplate the function template into which the explicit + /// template arguments will be substituted. + /// + /// \param ExplicitTemplateArgs the explicitly-specified template + /// arguments. + /// + /// \param Deduced the deduced template arguments, which will be populated + /// with the converted and checked explicit template arguments. + /// + /// \param ParamTypes will be populated with the instantiated function + /// parameters. + /// + /// \param FunctionType if non-NULL, the result type of the function template + /// will also be instantiated and the pointed-to value will be updated with + /// the instantiated function type. + /// + /// \param Info if substitution fails for any reason, this object will be + /// populated with more information about the failure. + /// + /// \returns TemplateDeductionResult::Success if substitution was successful, + /// or some failure condition. TemplateDeductionResult SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo &ExplicitTemplateArgs, @@ -9729,6 +12257,12 @@ public: QualType OriginalArgType; }; + /// Finish template argument deduction for a function template, + /// checking the deduced template arguments for completeness and forming + /// the function template specialization. + /// + /// \param OriginalCallArgs If non-NULL, the original call arguments against + /// which the deduced argument types should be compared. TemplateDeductionResult FinishTemplateArgumentDeduction( FunctionTemplateDecl *FunctionTemplate, SmallVectorImpl<DeducedTemplateArgument> &Deduced, @@ -9738,6 +12272,32 @@ public: bool PartialOverloading = false, llvm::function_ref<bool()> CheckNonDependent = [] { return false; }); + /// Perform template argument deduction from a function call + /// (C++ [temp.deduct.call]). + /// + /// \param FunctionTemplate the function template for which we are performing + /// template argument deduction. + /// + /// \param ExplicitTemplateArgs the explicit template arguments provided + /// for this call. + /// + /// \param Args the function call arguments + /// + /// \param Specialization if template argument deduction was successful, + /// this will be set to the function template specialization produced by + /// template argument deduction. + /// + /// \param Info the argument will be updated to provide additional information + /// about template argument deduction. + /// + /// \param CheckNonDependent A callback to invoke to check conversions for + /// non-dependent parameters, between deduction and substitution, per DR1391. + /// If this returns true, substitution will be skipped and we return + /// TemplateDeductionResult::NonDependentConversionFailure. The callback is + /// passed the parameter types (after substituting explicit template + /// arguments). + /// + /// \returns the result of template argument deduction. TemplateDeductionResult DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, @@ -9746,17 +12306,72 @@ public: QualType ObjectType, Expr::Classification ObjectClassification, llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent); + /// Deduce template arguments when taking the address of a function + /// template (C++ [temp.deduct.funcaddr]) or matching a specialization to + /// a template. + /// + /// \param FunctionTemplate the function template for which we are performing + /// template argument deduction. + /// + /// \param ExplicitTemplateArgs the explicitly-specified template + /// arguments. + /// + /// \param ArgFunctionType the function type that will be used as the + /// "argument" type (A) when performing template argument deduction from the + /// function template's function type. This type may be NULL, if there is no + /// argument type to compare against, in C++0x [temp.arg.explicit]p3. + /// + /// \param Specialization if template argument deduction was successful, + /// this will be set to the function template specialization produced by + /// template argument deduction. + /// + /// \param Info the argument will be updated to provide additional information + /// about template argument deduction. + /// + /// \param IsAddressOfFunction If \c true, we are deducing as part of taking + /// the address of a function template per [temp.deduct.funcaddr] and + /// [over.over]. If \c false, we are looking up a function template + /// specialization based on its signature, per [temp.deduct.decl]. + /// + /// \returns the result of template argument deduction. TemplateDeductionResult DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, bool IsAddressOfFunction = false); + /// Deduce template arguments for a templated conversion + /// function (C++ [temp.deduct.conv]) and, if successful, produce a + /// conversion function template specialization. TemplateDeductionResult DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, QualType ObjectType, Expr::Classification ObjectClassification, QualType ToType, CXXConversionDecl *&Specialization, sema::TemplateDeductionInfo &Info); + /// Deduce template arguments for a function template when there is + /// nothing to deduce against (C++0x [temp.arg.explicit]p3). + /// + /// \param FunctionTemplate the function template for which we are performing + /// template argument deduction. + /// + /// \param ExplicitTemplateArgs the explicitly-specified template + /// arguments. + /// + /// \param Specialization if template argument deduction was successful, + /// this will be set to the function template specialization produced by + /// template argument deduction. + /// + /// \param Info the argument will be updated to provide additional information + /// about template argument deduction. + /// + /// \param IsAddressOfFunction If \c true, we are deducing as part of taking + /// the address of a function template in a context where we do not have a + /// target type, per [over.over]. If \c false, we are looking up a function + /// template specialization based on its signature, which only happens when + /// deducing a function parameter type from an argument that is a template-id + /// naming a function template specialization. + /// + /// \returns the result of template argument deduction. TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, @@ -9783,6 +12398,25 @@ public: TypeSourceInfo *ReplaceAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, QualType Replacement); + /// Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6) + /// + /// Note that this is done even if the initializer is dependent. (This is + /// necessary to support partial ordering of templates using 'auto'.) + /// A dependent type will be produced when deducing from a dependent type. + /// + /// \param Type the type pattern using the auto type-specifier. + /// \param Init the initializer for the variable whose type is to be deduced. + /// \param Result if type deduction was successful, this will be set to the + /// deduced type. + /// \param Info the argument will be updated to provide additional information + /// about template argument deduction. + /// \param DependentDeduction Set if we should permit deduction in + /// dependent cases. This is necessary for template partial ordering + /// with 'auto' template parameters. The template parameter depth to be + /// used should be specified in the 'Info' parameter. + /// \param IgnoreConstraints Set if we should not fail if the deduced type + /// does not satisfy the type-constraint in the auto + /// type. TemplateDeductionResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *Initializer, QualType &Result, sema::TemplateDeductionInfo &Info, @@ -9796,6 +12430,16 @@ public: bool CheckIfFunctionSpecializationIsImmediate(FunctionDecl *FD, SourceLocation Loc); + /// Returns the more specialized class template partial specialization + /// according to the rules of partial ordering of class template partial + /// specializations (C++ [temp.class.order]). + /// + /// \param PS1 the first class template partial specialization + /// + /// \param PS2 the second class template partial specialization + /// + /// \returns the more specialized class template partial specialization. If + /// neither partial specialization is more specialized, returns NULL. ClassTemplatePartialSpecializationDecl * getMoreSpecializedPartialSpecialization( ClassTemplatePartialSpecializationDecl *PS1, @@ -9815,9 +12459,25 @@ public: TemplateParameterList *PParam, TemplateDecl *AArg, SourceLocation Loc, bool IsDeduced); + /// Mark which template parameters are used in a given expression. + /// + /// \param E the expression from which template parameters will be deduced. + /// + /// \param Used a bit vector whose elements will be set to \c true + /// to indicate when the corresponding template parameter will be + /// deduced. void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used); + /// Mark which template parameters can be deduced from a given + /// template argument list. + /// + /// \param TemplateArgs the template argument list from which template + /// parameters will be deduced. + /// + /// \param Used a bit vector whose elements will be set to \c true + /// to indicate when the corresponding template parameter will be + /// deduced. void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used); @@ -9826,16 +12486,74 @@ public: llvm::SmallBitVector &Deduced) { return MarkDeducedTemplateParameters(Context, FunctionTemplate, Deduced); } + + /// Marks all of the template parameters that will be deduced by a + /// call to the given function template. static void MarkDeducedTemplateParameters(ASTContext &Ctx, const FunctionTemplateDecl *FunctionTemplate, llvm::SmallBitVector &Deduced); + /// Returns the more specialized function template according + /// to the rules of function template partial ordering (C++ + /// [temp.func.order]). + /// + /// \param FT1 the first function template + /// + /// \param FT2 the second function template + /// + /// \param TPOC the context in which we are performing partial ordering of + /// function templates. + /// + /// \param NumCallArguments1 The number of arguments in the call to FT1, used + /// only when \c TPOC is \c TPOC_Call. Does not include the object argument + /// when calling a member function. + /// + /// \param RawObj1Ty The type of the object parameter of FT1 if a member + /// function only used if \c TPOC is \c TPOC_Call and FT1 is a Function + /// template from a member function + /// + /// \param RawObj2Ty The type of the object parameter of FT2 if a member + /// function only used if \c TPOC is \c TPOC_Call and FT2 is a Function + /// template from a member function + /// + /// \param Reversed If \c true, exactly one of FT1 and FT2 is an overload + /// candidate with a reversed parameter order. In this case, the corresponding + /// P/A pairs between FT1 and FT2 are reversed. + /// + /// \returns the more specialized function template. If neither + /// template is more specialized, returns NULL. FunctionTemplateDecl *getMoreSpecializedTemplate( FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc, TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1, QualType RawObj1Ty = {}, QualType RawObj2Ty = {}, bool Reversed = false); + /// Retrieve the most specialized of the given function template + /// specializations. + /// + /// \param SpecBegin the start iterator of the function template + /// specializations that we will be comparing. + /// + /// \param SpecEnd the end iterator of the function template + /// specializations, paired with \p SpecBegin. + /// + /// \param Loc the location where the ambiguity or no-specializations + /// diagnostic should occur. + /// + /// \param NoneDiag partial diagnostic used to diagnose cases where there are + /// no matching candidates. + /// + /// \param AmbigDiag partial diagnostic used to diagnose an ambiguity, if one + /// occurs. + /// + /// \param CandidateDiag partial diagnostic used for each function template + /// specialization that is a candidate in the ambiguous ordering. One + /// parameter in this diagnostic should be unbound, which will correspond to + /// the string describing the template arguments for the function template + /// specialization. + /// + /// \returns the most specialized function template specialization, if + /// found. Otherwise, returns SpecEnd. UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin, UnresolvedSetIterator SEnd, TemplateSpecCandidateSet &FailedCandidates, @@ -9844,6 +12562,15 @@ public: const PartialDiagnostic &CandidateDiag, bool Complain = true, QualType TargetType = QualType()); + /// Returns the more constrained function according to the rules of + /// partial ordering by constraints (C++ [temp.constr.order]). + /// + /// \param FD1 the first function + /// + /// \param FD2 the second function + /// + /// \returns the more constrained function. If neither function is + /// more constrained, returns NULL. FunctionDecl *getMoreConstrainedFunction(FunctionDecl *FD1, FunctionDecl *FD2); @@ -10281,6 +13008,33 @@ public: const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs); + /// Retrieve the template argument list(s) that should be used to + /// instantiate the definition of the given declaration. + /// + /// \param ND the declaration for which we are computing template + /// instantiation arguments. + /// + /// \param DC In the event we don't HAVE a declaration yet, we instead provide + /// the decl context where it will be created. In this case, the `Innermost` + /// should likely be provided. If ND is non-null, this is ignored. + /// + /// \param Innermost if non-NULL, specifies a template argument list for the + /// template declaration passed as ND. + /// + /// \param RelativeToPrimary true if we should get the template + /// arguments relative to the primary template, even when we're + /// dealing with a specialization. This is only relevant for function + /// template specializations. + /// + /// \param Pattern If non-NULL, indicates the pattern from which we will be + /// instantiating the definition of the given declaration, \p ND. This is + /// used to determine the proper set of template instantiation arguments for + /// friend function template specializations. + /// + /// \param ForConstraintInstantiation when collecting arguments, + /// ForConstraintInstantiation indicates we should continue looking when + /// encountering a lambda generic call operator, and continue looking for + /// arguments on an enclosing class template. MultiLevelTemplateArgumentList getTemplateInstantiationArgs( const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false, std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt, @@ -10441,6 +13195,8 @@ public: if (PragmaAttributeCurrentTargetDecl) PrintPragmaAttributeInstantiationPoint(); } + /// Prints the current instantiation stack through a series of + /// notes. void PrintInstantiationStack(); /// Determines whether we are currently in a context where @@ -10453,6 +13209,36 @@ public: /// diagnostics that will be suppressed. std::optional<sema::TemplateDeductionInfo *> isSFINAEContext() const; + /// Perform substitution on the type T with a given set of template + /// arguments. + /// + /// This routine substitutes the given template arguments into the + /// type T and produces the instantiated type. + /// + /// \param T the type into which the template arguments will be + /// substituted. If this type is not dependent, it will be returned + /// immediately. + /// + /// \param Args the template arguments that will be + /// substituted for the top-level template parameters within T. + /// + /// \param Loc the location in the source code where this substitution + /// is being performed. It will typically be the location of the + /// declarator (if we're instantiating the type of some declaration) + /// or the location of the type in the source code (if, e.g., we're + /// instantiating the type of a cast expression). + /// + /// \param Entity the name of the entity associated with a declaration + /// being instantiated (if any). May be empty to indicate that there + /// is no such entity (if, e.g., this is a type that occurs as part of + /// a cast expression) or that the entity has no name (e.g., an + /// unnamed function parameter). + /// + /// \param AllowDeducedTST Whether a DeducedTemplateSpecializationType is + /// acceptable as the top level type of the result. + /// + /// \returns If the instantiation succeeds, the instantiated + /// type. Otherwise, produces diagnostics and returns a NULL type. TypeSourceInfo *SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity, @@ -10466,6 +13252,10 @@ public: const MultiLevelTemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity); + /// A form of SubstType intended specifically for instantiating the + /// type of a FunctionDecl. Its purpose is solely to force the + /// instantiation of default-argument expressions and to avoid + /// instantiating an exception-specification. TypeSourceInfo *SubstFunctionDeclType( TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity, CXXRecordDecl *ThisContext, @@ -10481,12 +13271,18 @@ public: const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, std::optional<unsigned> NumExpansions, bool ExpectParameterPack, bool EvaluateConstraints = true); + + /// Substitute the given template arguments into the given set of + /// parameters, producing the set of parameter types that would be generated + /// from such a substitution. bool SubstParmTypes(SourceLocation Loc, ArrayRef<ParmVarDecl *> Params, const FunctionProtoType::ExtParameterInfo *ExtParamInfos, const MultiLevelTemplateArgumentList &TemplateArgs, SmallVectorImpl<QualType> &ParamTypes, SmallVectorImpl<ParmVarDecl *> *OutParams, ExtParameterInfoBuilder &ParamInfos); + + /// Substitute the given template arguments into the default argument. bool SubstDefaultArgument(SourceLocation Loc, ParmVarDecl *Param, const MultiLevelTemplateArgumentList &TemplateArgs, bool ForCallExpr = false); @@ -10538,19 +13334,76 @@ public: SubstInitializer(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs, bool CXXDirectInit); + /// Perform substitution on the base class specifiers of the + /// given class template specialization. + /// + /// Produces a diagnostic and returns true on error, returns false and + /// attaches the instantiated base classes to the class template + /// specialization if successful. bool SubstBaseSpecifiers(CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs); + /// Instantiate the definition of a class from a given pattern. + /// + /// \param PointOfInstantiation The point of instantiation within the + /// source code. + /// + /// \param Instantiation is the declaration whose definition is being + /// instantiated. This will be either a class template specialization + /// or a member class of a class template specialization. + /// + /// \param Pattern is the pattern from which the instantiation + /// occurs. This will be either the declaration of a class template or + /// the declaration of a member class of a class template. + /// + /// \param TemplateArgs The template arguments to be substituted into + /// the pattern. + /// + /// \param TSK the kind of implicit or explicit instantiation to perform. + /// + /// \param Complain whether to complain if the class cannot be instantiated + /// due to the lack of a definition. + /// + /// \returns true if an error occurred, false otherwise. bool InstantiateClass(SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateSpecializationKind TSK, bool Complain = true); + /// Instantiate the definition of an enum from a given pattern. + /// + /// \param PointOfInstantiation The point of instantiation within the + /// source code. + /// \param Instantiation is the declaration whose definition is being + /// instantiated. This will be a member enumeration of a class + /// temploid specialization, or a local enumeration within a + /// function temploid specialization. + /// \param Pattern The templated declaration from which the instantiation + /// occurs. + /// \param TemplateArgs The template arguments to be substituted into + /// the pattern. + /// \param TSK The kind of implicit or explicit instantiation to perform. + /// + /// \return \c true if an error occurred, \c false otherwise. bool InstantiateEnum(SourceLocation PointOfInstantiation, EnumDecl *Instantiation, EnumDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateSpecializationKind TSK); + /// Instantiate the definition of a field from the given pattern. + /// + /// \param PointOfInstantiation The point of instantiation within the + /// source code. + /// \param Instantiation is the declaration whose definition is being + /// instantiated. This will be a class of a class temploid + /// specialization, or a local enumeration within a function temploid + /// specialization. + /// \param Pattern The templated declaration from which the instantiation + /// occurs. + /// \param TemplateArgs The template arguments to be substituted into + /// the pattern. + /// + /// \return \c true if an error occurred, \c false otherwise. bool InstantiateInClassInitializer( SourceLocation PointOfInstantiation, FieldDecl *Instantiation, FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -10563,12 +13416,18 @@ public: ClassTemplateSpecializationDecl *ClassTemplateSpec, TemplateSpecializationKind TSK, bool Complain = true); + /// Instantiates the definitions of all of the member + /// of the given class, which is an instantiation of a class template + /// or a member class of a template. void InstantiateClassMembers(SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateSpecializationKind TSK); + /// Instantiate the definitions of all of the members of the + /// given class template specialization, which was named as part of an + /// explicit instantiation. void InstantiateClassTemplateSpecializationMembers( SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, @@ -10578,6 +13437,7 @@ public: NestedNameSpecifierLoc NNS, const MultiLevelTemplateArgumentList &TemplateArgs); + /// Do template substitution on declaration name info. DeclarationNameInfo SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -10748,6 +13608,13 @@ public: const Decl *Pattern, Decl *Inst, LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *OuterMostScope = nullptr); + + /// Update instantiation attributes after template was late parsed. + /// + /// Some attributes are evaluated based on the body of template. If it is + /// late parsed, such attributes cannot be evaluated when declaration is + /// instantiated. This function is used to update instantiation attributes + /// when template definition is ready. void updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst); void @@ -10756,17 +13623,45 @@ public: LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *OuterMostScope = nullptr); + /// In the MS ABI, we need to instantiate default arguments of dllexported + /// default constructors along with the constructor definition. This allows IR + /// gen to emit a constructor closure which calls the default constructor with + /// its default arguments. void InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor); bool InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param); void InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Function); + + /// Instantiate (or find existing instantiation of) a function template with a + /// given set of template arguments. + /// + /// Usually this should not be used, and template argument deduction should be + /// used in its place. FunctionDecl *InstantiateFunctionDeclaration( FunctionTemplateDecl *FTD, const TemplateArgumentList *Args, SourceLocation Loc, CodeSynthesisContext::SynthesisKind CSC = CodeSynthesisContext::ExplicitTemplateArgumentSubstitution); + + /// Instantiate the definition of the given function from its + /// template. + /// + /// \param PointOfInstantiation the point at which the instantiation was + /// required. Note that this is not precisely a "point of instantiation" + /// for the function, but it's close. + /// + /// \param Function the already-instantiated declaration of a + /// function template specialization or member function of a class template + /// specialization. + /// + /// \param Recursive if true, recursively instantiates any functions that + /// are required by this instantiation. + /// + /// \param DefinitionRequired if true, then we are performing an explicit + /// instantiation where the body of the function is required. Complain if + /// there is no such body. void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive = false, @@ -10780,9 +13675,16 @@ public: SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs = nullptr, LocalInstantiationScope *StartingScope = nullptr); + + /// Instantiates a variable template specialization by completing it + /// with appropriate type information and initializer. VarTemplateSpecializationDecl *CompleteVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, const MultiLevelTemplateArgumentList &TemplateArgs); + + /// BuildVariableInstantiation - Used after a new variable has been created. + /// Sets basic variable data and decides whether to postpone the + /// variable instantiation. void BuildVariableInstantiation(VarDecl *NewVar, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -10792,9 +13694,26 @@ public: bool InstantiatingVarTemplate = false, VarTemplateSpecializationDecl *PrevVTSD = nullptr); + /// Instantiate the initializer of a variable. void InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs); + + /// Instantiate the definition of the given variable from its + /// template. + /// + /// \param PointOfInstantiation the point at which the instantiation was + /// required. Note that this is not precisely a "point of instantiation" + /// for the variable, but it's close. + /// + /// \param Var the already-instantiated declaration of a templated variable. + /// + /// \param Recursive if true, recursively instantiates any functions that + /// are required by this instantiation. + /// + /// \param DefinitionRequired if true, then we are performing an explicit + /// instantiation where a definition of the variable is required. Complain + /// if there is no such definition. void InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive = false, bool DefinitionRequired = false, @@ -10804,10 +13723,42 @@ public: CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, const MultiLevelTemplateArgumentList &TemplateArgs); + /// Find the instantiation of the given declaration within the + /// current instantiation. + /// + /// This routine is intended to be used when \p D is a declaration + /// referenced from within a template, that needs to mapped into the + /// corresponding declaration within an instantiation. For example, + /// given: + /// + /// \code + /// template<typename T> + /// struct X { + /// enum Kind { + /// KnownValue = sizeof(T) + /// }; + /// + /// bool getKind() const { return KnownValue; } + /// }; + /// + /// template struct X<int>; + /// \endcode + /// + /// In the instantiation of X<int>::getKind(), we need to map the \p + /// EnumConstantDecl for \p KnownValue (which refers to + /// X<T>::<Kind>::KnownValue) to its instantiation + /// (X<int>::<Kind>::KnownValue). + /// \p FindInstantiatedDecl performs this mapping from within the + /// instantiation of X<int>. NamedDecl * FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext = false); + + /// Finds the instantiation of the given declaration context + /// within the current instantiation. + /// + /// \returns NULL if there was an error DeclContext * FindInstantiatedContext(SourceLocation Loc, DeclContext *DC, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -10820,6 +13771,8 @@ public: FunctionDecl *SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD, FunctionDecl *Spaceship); + /// Performs template instantiation for all implicit template + /// instantiations we have seen until this point. void PerformPendingInstantiations(bool LocalOnly = false); TemplateParameterList * @@ -11247,6 +14200,20 @@ public: /// avoid actually expanding the pack where possible. std::optional<unsigned> getFullyPackExpandedSize(TemplateArgument Arg); + /// Called when an expression computing the size of a parameter pack + /// is parsed. + /// + /// \code + /// template<typename ...Types> struct count { + /// static const unsigned value = sizeof...(Types); + /// }; + /// \endcode + /// + // + /// \param OpLoc The location of the "sizeof" keyword. + /// \param Name The name of the parameter pack whose size will be determined. + /// \param NameLoc The source location of the name of the parameter pack. + /// \param RParenLoc The location of the closing parentheses. ExprResult ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc, IdentifierInfo &Name, SourceLocation NameLoc, @@ -11576,14 +14543,62 @@ public: const DeclSpec *DS = nullptr); QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVRA, const DeclSpec *DS = nullptr); + + /// Build a pointer type. + /// + /// \param T The type to which we'll be building a pointer. + /// + /// \param Loc The location of the entity whose type involves this + /// pointer type or, if there is no such entity, the location of the + /// type that will have pointer type. + /// + /// \param Entity The name of the entity that involves the pointer + /// type, if known. + /// + /// \returns A suitable pointer type, if there are no + /// errors. Otherwise, returns a NULL type. QualType BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); + + /// Build a reference type. + /// + /// \param T The type to which we'll be building a reference. + /// + /// \param Loc The location of the entity whose type involves this + /// reference type or, if there is no such entity, the location of the + /// type that will have reference type. + /// + /// \param Entity The name of the entity that involves the reference + /// type, if known. + /// + /// \returns A suitable reference type, if there are no + /// errors. Otherwise, returns a NULL type. QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity); + + /// Build an array type. + /// + /// \param T The type of each element in the array. + /// + /// \param ASM C99 array size modifier (e.g., '*', 'static'). + /// + /// \param ArraySize Expression describing the size of the array. + /// + /// \param Brackets The range from the opening '[' to the closing ']'. + /// + /// \param Entity The name of the entity that involves the array + /// type, if known. + /// + /// \returns A suitable array type, if there are no errors. Otherwise, + /// returns a NULL type. QualType BuildArrayType(QualType T, ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, SourceRange Brackets, DeclarationName Entity); QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc); + + /// Build an ext-vector type. + /// + /// Run the required checks for the extended vector type. QualType BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc); QualType BuildMatrixType(QualType T, Expr *NumRows, Expr *NumColumns, @@ -11592,6 +14607,11 @@ public: QualType BuildCountAttributedArrayOrPointerType(QualType WrappedTy, Expr *CountExpr); + /// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an + /// expression is uninstantiated. If instantiated it will apply the + /// appropriate address space to the type. This function allows dependent + /// template variables to be used in conjunction with the address_space + /// attribute QualType BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, SourceLocation AttrLoc); @@ -11634,16 +14654,72 @@ public: SourceLocation Loc, DeclarationName Entity, const FunctionProtoType::ExtProtoInfo &EPI); + /// Build a member pointer type \c T Class::*. + /// + /// \param T the type to which the member pointer refers. + /// \param Class the class type into which the member pointer points. + /// \param Loc the location where this type begins + /// \param Entity the name of the entity that will have this member pointer + /// type + /// + /// \returns a member pointer type, if successful, or a NULL type if there was + /// an error. QualType BuildMemberPointerType(QualType T, QualType Class, SourceLocation Loc, DeclarationName Entity); + + /// Build a block pointer type. + /// + /// \param T The type to which we'll be building a block pointer. + /// + /// \param Loc The source location, used for diagnostics. + /// + /// \param Entity The name of the entity that involves the block pointer + /// type, if known. + /// + /// \returns A suitable block pointer type, if there are no + /// errors. Otherwise, returns a NULL type. QualType BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); + + /// Build a paren type including \p T. QualType BuildParenType(QualType T); QualType BuildAtomicType(QualType T, SourceLocation Loc); + + /// Build a Read-only Pipe type. + /// + /// \param T The type to which we'll be building a Pipe. + /// + /// \param Loc We do not use it for now. + /// + /// \returns A suitable pipe type, if there are no errors. Otherwise, returns + /// a NULL type. QualType BuildReadPipeType(QualType T, SourceLocation Loc); + + /// Build a Write-only Pipe type. + /// + /// \param T The type to which we'll be building a Pipe. + /// + /// \param Loc We do not use it for now. + /// + /// \returns A suitable pipe type, if there are no errors. Otherwise, returns + /// a NULL type. QualType BuildWritePipeType(QualType T, SourceLocation Loc); + + /// Build a bit-precise integer type. + /// + /// \param IsUnsigned Boolean representing the signedness of the type. + /// + /// \param BitWidth Size of this int type in bits, or an expression + /// representing that. + /// + /// \param Loc Location of the keyword. QualType BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc); + /// GetTypeForDeclarator - Convert the type for the specified + /// declarator to Type instances. + /// + /// The result of this call will never be null, but the associated + /// type may be a null type if there's an unrecoverable error. TypeSourceInfo *GetTypeForDeclarator(Declarator &D); TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy); @@ -11715,6 +14791,22 @@ public: QualType getCompletedType(Expr *E); void completeExprArrayBound(Expr *E); + + /// Ensure that the type of the given expression is complete. + /// + /// This routine checks whether the expression \p E has a complete type. If + /// the expression refers to an instantiable construct, that instantiation is + /// performed as needed to complete its type. Furthermore + /// Sema::RequireCompleteType is called for the expression's type (or in the + /// case of a reference type, the referred-to type). + /// + /// \param E The expression whose type is required to be complete. + /// \param Kind Selects which completeness rules should be applied. + /// \param Diagnoser The object that will emit a diagnostic if the type is + /// incomplete. + /// + /// \returns \c true if the type of \p E is incomplete and diagnosed, \c false + /// otherwise. bool RequireCompleteExprType(Expr *E, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser); bool RequireCompleteExprType(Expr *E, unsigned DiagID); @@ -11725,6 +14817,10 @@ public: return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser); } + /// Retrieve a version of the type 'T' that is elaborated by Keyword, + /// qualified by the nested-name-specifier contained in SS, and that is + /// (re)declared by OwnedTagDecl, which is nullptr if this is not a + /// (re)declaration. QualType getElaboratedType(ElaboratedTypeKeyword Keyword, const CXXScopeSpec &SS, QualType T, TagDecl *OwnedTagDecl = nullptr); @@ -11763,6 +14859,24 @@ public: QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind, SourceLocation Loc); + /// Ensure that the type T is a literal type. + /// + /// This routine checks whether the type @p T is a literal type. If @p T is an + /// incomplete type, an attempt is made to complete it. If @p T is a literal + /// type, or @p AllowIncompleteType is true and @p T is an incomplete type, + /// returns false. Otherwise, this routine issues the diagnostic @p PD (giving + /// it the type @p T), along with notes explaining why the type is not a + /// literal type, and returns true. + /// + /// @param Loc The location in the source that the non-literal type + /// diagnostic should refer to. + /// + /// @param T The type that this routine is examining for literalness. + /// + /// @param Diagnoser Emits a diagnostic if T is not a literal type. + /// + /// @returns @c true if @p T is not a literal type and a diagnostic was + /// emitted, @c false otherwise. bool RequireLiteralType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser); bool RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID); @@ -11778,6 +14892,26 @@ public: CompleteTypeKind Kind = CompleteTypeKind::Default) { return !RequireCompleteTypeImpl(Loc, T, Kind, nullptr); } + + /// Ensure that the type T is a complete type. + /// + /// This routine checks whether the type @p T is complete in any + /// context where a complete type is required. If @p T is a complete + /// type, returns false. If @p T is a class template specialization, + /// this routine then attempts to perform class template + /// instantiation. If instantiation fails, or if @p T is incomplete + /// and cannot be completed, issues the diagnostic @p diag (giving it + /// the type @p T) and returns true. + /// + /// @param Loc The location in the source that the incomplete type + /// diagnostic should refer to. + /// + /// @param T The type that this routine is examining for completeness. + /// + /// @param Kind Selects which completeness rules should be applied. + /// + /// @returns @c true if @p T is incomplete and a diagnostic was emitted, + /// @c false otherwise. bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser); bool RequireCompleteType(SourceLocation Loc, QualType T, @@ -11847,6 +14981,7 @@ public: } private: + /// The implementation of RequireCompleteType bool RequireCompleteTypeImpl(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser *Diagnoser); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 3f8f2f0..d622871 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -566,10 +566,6 @@ void Sema::runWithSufficientStackSpace(SourceLocation Loc, clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn); } -/// makeUnavailableInSystemHeader - There is an error in the current -/// context. If we're still in a system header, and we can plausibly -/// make the relevant declaration unavailable instead of erroring, do -/// so and return true. bool Sema::makeUnavailableInSystemHeader(SourceLocation loc, UnavailableAttr::ImplicitReason reason) { // If we're not in a function, it's an error. @@ -595,11 +591,6 @@ ASTMutationListener *Sema::getASTMutationListener() const { return getASTConsumer().GetASTMutationListener(); } -///Registers an external source. If an external source already exists, -/// creates a multiplex external source and appends to it. -/// -///\param[in] E - A non-null external sema source. -/// void Sema::addExternalSource(ExternalSemaSource *E) { assert(E && "Cannot use with NULL ptr"); @@ -614,7 +605,6 @@ void Sema::addExternalSource(ExternalSemaSource *E) { ExternalSource = new MultiplexExternalSemaSource(ExternalSource.get(), E); } -/// Print out statistics about the semantic analysis. void Sema::PrintStats() const { llvm::errs() << "\n*** Semantic Analysis Stats:\n"; llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n"; @@ -782,8 +772,6 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, CurFPFeatureOverrides()); } -/// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding -/// to the conversion from scalar type ScalarTy to the Boolean type. CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) { switch (ScalarTy->getScalarTypeKind()) { case Type::STK_Bool: return CK_NoOp; @@ -1100,9 +1088,6 @@ void Sema::emitAndClearUnusedLocalTypedefWarnings() { UnusedLocalTypedefNameCandidates.clear(); } -/// This is called before the very first declaration in the translation unit -/// is parsed. Note that the ASTContext may have already injected some -/// declarations. void Sema::ActOnStartOfTranslationUnit() { if (getLangOpts().CPlusPlusModules && getLangOpts().getCompilingModule() == LangOptions::CMK_HeaderUnit) @@ -1174,9 +1159,6 @@ void Sema::ActOnEndOfTranslationUnitFragment(TUFragmentKind Kind) { DelayedTypos.clear(); } -/// ActOnEndOfTranslationUnit - This is called at the very end of the -/// translation unit when EOF is reached and all but the top-level scope is -/// popped. void Sema::ActOnEndOfTranslationUnit() { assert(DelayedDiagnostics.getCurrentPool() == nullptr && "reached end of translation unit with a pool attached?"); @@ -2141,10 +2123,6 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { CheckType(FNPTy->getReturnType(), /*IsRetTy=*/true); } -/// Looks through the macro-expansion chain for the given -/// location, looking for a macro expansion with the given name. -/// If one is found, returns true and sets the location to that -/// expansion loc. bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) { SourceLocation loc = locref; if (!loc.isMacroID()) return false; @@ -2162,17 +2140,6 @@ bool Sema::findMacroSpelling(SourceLocation &locref, StringRef name) { return false; } -/// Determines the active Scope associated with the given declaration -/// context. -/// -/// This routine maps a declaration context to the active Scope object that -/// represents that declaration context in the parser. It is typically used -/// from "scope-less" code (e.g., template instantiation, lazy creation of -/// declarations) that injects a name for name-lookup purposes and, therefore, -/// must update the Scope. -/// -/// \returns The scope corresponding to the given declaraion context, or NULL -/// if no such scope is open. Scope *Sema::getScopeForContext(DeclContext *Ctx) { if (!Ctx) @@ -2303,13 +2270,6 @@ static void markEscapingByrefs(const FunctionScopeInfo &FSI, Sema &S) { } } -/// Pop a function (or block or lambda or captured region) scope from the stack. -/// -/// \param WP The warning policy to use for CFG-based warnings, or null if such -/// warnings should not be produced. -/// \param D The declaration corresponding to this function scope, if producing -/// CFG-based warnings. -/// \param BlockType The type of the block expression, if D is a BlockDecl. Sema::PoppedFunctionScopePtr Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP, const Decl *D, QualType BlockType) { @@ -2356,8 +2316,6 @@ void Sema::PopCompoundScope() { CurFunction->CompoundScopes.pop_back(); } -/// Determine whether any errors occurred within this function/method/ -/// block. bool Sema::hasAnyUnrecoverableErrorsInThisFunction() const { return getCurFunction()->hasUnrecoverableErrorOccurred(); } @@ -2508,17 +2466,6 @@ void ExternalSemaSource::ReadUndefinedButUsed( void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector< FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {} -/// Figure out if an expression could be turned into a call. -/// -/// Use this when trying to recover from an error where the programmer may have -/// written just the name of a function instead of actually calling it. -/// -/// \param E - The expression to examine. -/// \param ZeroArgCallReturnTy - If the expression can be turned into a call -/// with no arguments, this parameter is set to the type returned by such a -/// call; otherwise, it is set to an empty QualType. -/// \param OverloadSet - If the expression is an overloaded function -/// name, this parameter is populated with the decls of the various overloads. bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, UnresolvedSetImpl &OverloadSet) { ZeroArgCallReturnTy = QualType(); diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 979a64b..df6edb2 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -34,9 +34,6 @@ enum AccessResult { AR_dependent }; -/// SetMemberAccessSpecifier - Set the access specifier of a member. -/// Returns true on error (when the previous member decl access specifier -/// is different from the new member decl access specifier). bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, NamedDecl *PrevMemberDecl, AccessSpecifier LexicalAS) { @@ -1590,8 +1587,6 @@ Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, return CheckAccess(*this, E->getNameLoc(), Entity); } -/// Perform access-control checking on a previously-unresolved member -/// access which has now been resolved to a member. Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, DeclAccessPair Found) { if (!getLangOpts().AccessControl || @@ -1609,8 +1604,6 @@ Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, return CheckAccess(*this, E->getMemberLoc(), Entity); } -/// Is the given member accessible for the purposes of deciding whether to -/// define a special member function as deleted? bool Sema::isMemberAccessibleForDeletion(CXXRecordDecl *NamingClass, DeclAccessPair Found, QualType ObjectType, @@ -1658,7 +1651,6 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, return CheckAccess(*this, Loc, Entity); } -/// Checks access to a constructor. Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, CXXConstructorDecl *Constructor, DeclAccessPair Found, @@ -1705,7 +1697,6 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, return CheckConstructorAccess(UseLoc, Constructor, Found, Entity, PD); } -/// Checks access to a constructor. Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, CXXConstructorDecl *Constructor, DeclAccessPair Found, @@ -1747,7 +1738,6 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, return CheckAccess(*this, UseLoc, AccessEntity); } -/// Checks access to an overloaded operator new or delete. Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, SourceRange PlacementRange, CXXRecordDecl *NamingClass, @@ -1767,7 +1757,6 @@ Sema::AccessResult Sema::CheckAllocationAccess(SourceLocation OpLoc, return CheckAccess(*this, OpLoc, Entity); } -/// Checks access to a member. Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, CXXRecordDecl *NamingClass, DeclAccessPair Found) { @@ -1782,7 +1771,6 @@ Sema::AccessResult Sema::CheckMemberAccess(SourceLocation UseLoc, return CheckAccess(*this, UseLoc, Entity); } -/// Checks implicit access to a member in a structured binding. Sema::AccessResult Sema::CheckStructuredBindingMemberAccess(SourceLocation UseLoc, CXXRecordDecl *DecomposedClass, @@ -1815,8 +1803,6 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, return CheckAccess(*this, OpLoc, Entity); } -/// Checks access to an overloaded member operator, including -/// conversion operators. Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, Expr *ObjectExpr, Expr *ArgExpr, @@ -1839,7 +1825,6 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, return CheckMemberOperatorAccess(OpLoc, ObjectExpr, R, FoundDecl); } -/// Checks access to the target of a friend declaration. Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) { assert(isa<CXXMethodDecl>(target->getAsFunction())); @@ -1889,12 +1874,6 @@ Sema::AccessResult Sema::CheckAddressOfMemberAccess(Expr *OvlExpr, return CheckAccess(*this, Ovl->getNameLoc(), Entity); } -/// Checks access for a hierarchy conversion. -/// -/// \param ForceCheck true if this check should be performed even if access -/// control is disabled; some things rely on this for semantics -/// \param ForceUnprivileged true if this check should proceed as if the -/// context had no special privileges Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, @@ -1929,7 +1908,6 @@ Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, return CheckAccess(*this, AccessLoc, Entity); } -/// Checks access to all the declarations in the given result set. void Sema::CheckLookupAccess(const LookupResult &R) { assert(getLangOpts().AccessControl && "performing access check without access control"); @@ -1946,23 +1924,6 @@ void Sema::CheckLookupAccess(const LookupResult &R) { } } -/// Checks access to Target from the given class. The check will take access -/// specifiers into account, but no member access expressions and such. -/// -/// \param Target the declaration to check if it can be accessed -/// \param NamingClass the class in which the lookup was started. -/// \param BaseType type of the left side of member access expression. -/// \p BaseType and \p NamingClass are used for C++ access control. -/// Depending on the lookup case, they should be set to the following: -/// - lhs.target (member access without a qualifier): -/// \p BaseType and \p NamingClass are both the type of 'lhs'. -/// - lhs.X::target (member access with a qualifier): -/// BaseType is the type of 'lhs', NamingClass is 'X' -/// - X::target (qualified lookup without member access): -/// BaseType is null, NamingClass is 'X'. -/// - target (unqualified lookup). -/// BaseType is null, NamingClass is the parent class of 'target'. -/// \return true if the Target is accessible from the Class, false otherwise. bool Sema::IsSimplyAccessible(NamedDecl *Target, CXXRecordDecl *NamingClass, QualType BaseType) { // Perform the C++ accessibility checks first. diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index bb44531..aaabd98 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -1231,7 +1231,6 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) { D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc)); } -/// FreeVisContext - Deallocate and null out VisContext. void Sema::FreeVisContext() { delete static_cast<VisStack*>(VisContext); VisContext = nullptr; diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index da88b6c..5b2d652 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -43,13 +43,6 @@ static CXXRecordDecl *getCurrentInstantiationOf(QualType T, return nullptr; } -/// Compute the DeclContext that is associated with the given type. -/// -/// \param T the type for which we are attempting to find a DeclContext. -/// -/// \returns the declaration context represented by the type T, -/// or NULL if the declaration context cannot be computed (e.g., because it is -/// dependent and not the current instantiation). DeclContext *Sema::computeDeclContext(QualType T) { if (!T->isDependentType()) if (const TagType *Tag = T->getAs<TagType>()) @@ -58,19 +51,6 @@ DeclContext *Sema::computeDeclContext(QualType T) { return ::getCurrentInstantiationOf(T, CurContext); } -/// Compute the DeclContext that is associated with the given -/// scope specifier. -/// -/// \param SS the C++ scope specifier as it appears in the source -/// -/// \param EnteringContext when true, we will be entering the context of -/// this scope specifier, so we can retrieve the declaration context of a -/// class template or class template partial specialization even if it is -/// not the current instantiation. -/// -/// \returns the declaration context represented by the scope specifier @p SS, -/// or NULL if the declaration context cannot be computed (e.g., because it is -/// dependent and not the current instantiation). DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, bool EnteringContext) { if (!SS.isSet() || SS.isInvalid()) @@ -190,11 +170,6 @@ bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { return SS.getScopeRep()->isDependent(); } -/// If the given nested name specifier refers to the current -/// instantiation, return the declaration that corresponds to that -/// current instantiation (C++0x [temp.dep.type]p1). -/// -/// \param NNS a dependent nested name specifier. CXXRecordDecl *Sema::getCurrentInstantiationOf(NestedNameSpecifier *NNS) { assert(getLangOpts().CPlusPlus && "Only callable in C++"); assert(NNS->isDependent() && "Only dependent nested-name-specifier allowed"); @@ -341,11 +316,6 @@ bool Sema::ActOnSuperScopeSpecifier(SourceLocation SuperLoc, return false; } -/// Determines whether the given declaration is an valid acceptable -/// result for name lookup of a nested-name-specifier. -/// \param SD Declaration checked for nested-name-specifier. -/// \param IsExtension If not null and the declaration is accepted as an -/// extension, the pointed variable is assigned true. bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD, bool *IsExtension) { if (!SD) @@ -386,10 +356,6 @@ bool Sema::isAcceptableNestedNameSpecifier(const NamedDecl *SD, return false; } -/// If the given nested-name-specifier begins with a bare identifier -/// (e.g., Base::), perform name lookup for that identifier as a -/// nested-name-specifier within the given scope, and return the result of that -/// name lookup. NamedDecl *Sema::FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS) { if (!S || !NNS) return nullptr; @@ -439,37 +405,6 @@ public: } -/// Build a new nested-name-specifier for "identifier::", as described -/// by ActOnCXXNestedNameSpecifier. -/// -/// \param S Scope in which the nested-name-specifier occurs. -/// \param IdInfo Parser information about an identifier in the -/// nested-name-spec. -/// \param EnteringContext If true, enter the context specified by the -/// nested-name-specifier. -/// \param SS Optional nested name specifier preceding the identifier. -/// \param ScopeLookupResult Provides the result of name lookup within the -/// scope of the nested-name-specifier that was computed at template -/// definition time. -/// \param ErrorRecoveryLookup Specifies if the method is called to improve -/// error recovery and what kind of recovery is performed. -/// \param IsCorrectedToColon If not null, suggestion of replace '::' -> ':' -/// are allowed. The bool value pointed by this parameter is set to -/// 'true' if the identifier is treated as if it was followed by ':', -/// not '::'. -/// \param OnlyNamespace If true, only considers namespaces in lookup. -/// -/// This routine differs only slightly from ActOnCXXNestedNameSpecifier, in -/// that it contains an extra parameter \p ScopeLookupResult, which provides -/// the result of name lookup within the scope of the nested-name-specifier -/// that was computed at template definition time. -/// -/// If ErrorRecoveryLookup is true, then this call is used to improve error -/// recovery. This means that it should not emit diagnostics, it should -/// just return true on failure. It also means it should only return a valid -/// scope if it *knows* that the result is correct. It should not return in a -/// dependent context, for example. Nor will it extend \p SS with the scope -/// specifier. bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, bool EnteringContext, CXXScopeSpec &SS, NamedDecl *ScopeLookupResult, @@ -898,12 +833,6 @@ bool Sema::ActOnCXXNestedNameSpecifierIndexedPack(CXXScopeSpec &SS, return false; } -/// IsInvalidUnlessNestedName - This method is used for error recovery -/// purposes to determine whether the specified identifier is only valid as -/// a nested name specifier, for example a namespace name. It is -/// conservatively correct to always return false from this method. -/// -/// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. bool Sema::IsInvalidUnlessNestedName(Scope *S, CXXScopeSpec &SS, NestedNameSpecInfo &IdInfo, bool EnteringContext) { @@ -1088,12 +1017,6 @@ bool Sema::ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } -/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global -/// scope or nested-name-specifier) is parsed, part of a declarator-id. -/// After this method is called, according to [C++ 3.4.3p3], names should be -/// looked up in the declarator-id's scope, until the declarator is parsed and -/// ActOnCXXExitDeclaratorScope is called. -/// The 'SS' should be a non-empty valid CXXScopeSpec. bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); @@ -1116,11 +1039,6 @@ bool Sema::ActOnCXXEnterDeclaratorScope(Scope *S, CXXScopeSpec &SS) { return false; } -/// ActOnCXXExitDeclaratorScope - Called when a declarator that previously -/// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same -/// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. -/// Used to indicate that names should revert to being looked up in the -/// defining scope. void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(SS.isSet() && "Parser passed invalid CXXScopeSpec."); if (SS.isInvalid()) diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index f03dcf0..eca8363 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -270,8 +270,6 @@ static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, bool CStyle, unsigned &msg, CastKind &Kind); -/// ActOnCXXNamedCast - Parse -/// {dynamic,static,reinterpret,const,addrspace}_cast's. ExprResult Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, SourceLocation LAngleBracketLoc, Declarator &D, diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index cc3615d..45b9bbb 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -131,9 +131,6 @@ static constexpr unsigned short combineFAPK(Sema::FormatArgumentPassingKind A, return (A << 8) | B; } -/// Checks that a call expression's argument count is at least the desired -/// number. This is useful when doing custom type-checking on a variadic -/// function. Returns true on error. bool Sema::checkArgCountAtLeast(CallExpr *Call, unsigned MinArgCount) { unsigned ArgCount = Call->getNumArgs(); if (ArgCount >= MinArgCount) @@ -144,9 +141,6 @@ bool Sema::checkArgCountAtLeast(CallExpr *Call, unsigned MinArgCount) { << /*is non object*/ 0 << Call->getSourceRange(); } -/// Checks that a call expression's argument count is at most the desired -/// number. This is useful when doing custom type-checking on a variadic -/// function. Returns true on error. bool Sema::checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount) { unsigned ArgCount = Call->getNumArgs(); if (ArgCount <= MaxArgCount) @@ -156,17 +150,12 @@ bool Sema::checkArgCountAtMost(CallExpr *Call, unsigned MaxArgCount) { << /*is non object*/ 0 << Call->getSourceRange(); } -/// Checks that a call expression's argument count is in the desired range. This -/// is useful when doing custom type-checking on a variadic function. Returns -/// true on error. bool Sema::checkArgCountRange(CallExpr *Call, unsigned MinArgCount, unsigned MaxArgCount) { return checkArgCountAtLeast(Call, MinArgCount) || checkArgCountAtMost(Call, MaxArgCount); } -/// Checks that a call expression's argument count is the desired number. -/// This is useful when doing custom type-checking. Returns true on error. bool Sema::checkArgCount(CallExpr *Call, unsigned DesiredArgCount) { unsigned ArgCount = Call->getNumArgs(); if (ArgCount == DesiredArgCount) @@ -2929,10 +2918,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return TheCallResult; } -/// Returns true if the argument consists of one contiguous run of 1s with any -/// number of 0s on either side. The 1s are allowed to wrap from LSB to MSB, so -/// 0x000FFF0, 0x0000FFFF, 0xFF0000FF, 0x0 are all runs. 0x0F0F0000 is not, -/// since all 1s are not contiguous. bool Sema::ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum) { llvm::APSInt Result; // We can't check the value of a dependent argument. @@ -2953,10 +2938,6 @@ bool Sema::ValueIsRunOfOnes(CallExpr *TheCall, unsigned ArgNum) { << ArgNum << Arg->getSourceRange(); } -/// Given a FunctionDecl's FormatAttr, attempts to populate the FomatStringInfo -/// parameter with the FormatAttr's correct format_idx and firstDataArg. -/// Returns true when the format fits the function and the FormatStringInfo has -/// been populated. bool Sema::getFormatStringInfo(const FormatAttr *Format, bool IsCXXMember, bool IsVariadic, FormatStringInfo *FSI) { if (Format->getFirstArg() == 0) @@ -3128,10 +3109,6 @@ static void CheckNonNullArguments(Sema &S, } } -/// Warn if a pointer or reference argument passed to a function points to an -/// object that is less aligned than the parameter. This can happen when -/// creating a typedef with a lower alignment than the original type and then -/// calling functions defined in terms of the original type. void Sema::CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl, StringRef ParamName, QualType ArgTy, QualType ParamTy) { @@ -3167,9 +3144,6 @@ void Sema::CheckArgAlignment(SourceLocation Loc, NamedDecl *FDecl, << ParamName << (FDecl != nullptr) << FDecl; } -/// Handles the checks for format strings, non-POD arguments to vararg -/// functions, NULL arguments passed to non-NULL parameters, diagnose_if -/// attributes and AArch64 SME attributes. void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, const Expr *ThisArg, ArrayRef<const Expr *> Args, bool IsMemberFunction, SourceLocation Loc, @@ -3361,8 +3335,6 @@ void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) { } } -/// CheckConstructorCall - Check a constructor call for correctness and safety -/// properties not enforced by the C type system. void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, ArrayRef<const Expr *> Args, const FunctionProtoType *Proto, @@ -3379,8 +3351,6 @@ void Sema::CheckConstructorCall(FunctionDecl *FDecl, QualType ThisType, Loc, SourceRange(), CallType); } -/// CheckFunctionCall - Check a direct function call for various correctness -/// and safety properties not strictly enforced by the C type system. bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall, const FunctionProtoType *Proto) { bool IsMemberOperatorCall = isa<CXXOperatorCallExpr>(TheCall) && @@ -3496,8 +3466,6 @@ bool Sema::CheckPointerCall(NamedDecl *NDecl, CallExpr *TheCall, return false; } -/// Checks function calls when a FunctionDecl or a NamedDecl is not available, -/// such as function pointers returned from functions. bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) { VariadicCallType CallType = getVariadicCallType(/*FDecl=*/nullptr, Proto, TheCall->getCallee()); @@ -4149,13 +4117,6 @@ static bool checkBuiltinArgument(Sema &S, CallExpr *E, unsigned ArgIndex) { return false; } -/// We have a call to a function like __sync_fetch_and_add, which is an -/// overloaded function based on the pointer type of its first argument. -/// The main BuildCallExpr routines have already promoted the types of -/// arguments because all of these calls are prototyped as void(...). -/// -/// This function goes through and does final semantic checking for these -/// builtins, as well as generating any warnings. ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) { CallExpr *TheCall = static_cast<CallExpr *>(TheCallResult.get()); Expr *Callee = TheCall->getCallee(); @@ -4527,12 +4488,6 @@ ExprResult Sema::BuiltinAtomicOverloaded(ExprResult TheCallResult) { return TheCallResult; } -/// BuiltinNontemporalOverloaded - We have a call to -/// __builtin_nontemporal_store or __builtin_nontemporal_load, which is an -/// overloaded function based on the pointer type of its last argument. -/// -/// This function goes through and does final semantic checking for these -/// builtins. ExprResult Sema::BuiltinNontemporalOverloaded(ExprResult TheCallResult) { CallExpr *TheCall = (CallExpr *)TheCallResult.get(); DeclRefExpr *DRE = @@ -4699,9 +4654,6 @@ static bool checkVAStartIsInVariadicFunction(Sema &S, Expr *Fn, return false; } -/// Check the arguments to '__builtin_va_start' or '__builtin_ms_va_start' -/// for validity. Emit an error and return true on failure; return false -/// on success. bool Sema::BuiltinVAStart(unsigned BuiltinID, CallExpr *TheCall) { Expr *Fn = TheCall->getCallee(); @@ -4839,8 +4791,6 @@ bool Sema::BuiltinVAStartARMMicrosoft(CallExpr *Call) { return false; } -/// BuiltinUnorderedCompare - Handle functions like __builtin_isgreater and -/// friends. This is declared to take (...), so we have to check everything. bool Sema::BuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) { if (checkArgCount(TheCall, 2)) return true; @@ -4881,9 +4831,6 @@ bool Sema::BuiltinUnorderedCompare(CallExpr *TheCall, unsigned BuiltinID) { return false; } -/// BuiltinSemaBuiltinFPClassification - Handle functions like -/// __builtin_isnan and friends. This is declared to take (...), so we have -/// to check everything. bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, unsigned BuiltinID) { if (checkArgCount(TheCall, NumArgs)) @@ -4969,7 +4916,6 @@ bool Sema::BuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs, return false; } -/// Perform semantic analysis for a call to __builtin_complex. bool Sema::BuiltinComplex(CallExpr *TheCall) { if (checkArgCount(TheCall, 2)) return true; @@ -5114,7 +5060,6 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { TheCall->getRParenLoc()); } -/// ConvertVectorExpr - Handle __builtin_convertvector ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { @@ -5145,9 +5090,6 @@ ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, BuiltinLoc, RParenLoc); } -/// BuiltinPrefetch - Handle __builtin_prefetch. -// This is declared to take (const void*, ...) and can take two -// optional constant int args. bool Sema::BuiltinPrefetch(CallExpr *TheCall) { unsigned NumArgs = TheCall->getNumArgs(); @@ -5166,7 +5108,6 @@ bool Sema::BuiltinPrefetch(CallExpr *TheCall) { return false; } -/// BuiltinArithmeticFence - Handle __arithmetic_fence. bool Sema::BuiltinArithmeticFence(CallExpr *TheCall) { if (!Context.getTargetInfo().checkArithmeticFenceSupported()) return Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported) @@ -5189,9 +5130,6 @@ bool Sema::BuiltinArithmeticFence(CallExpr *TheCall) { return false; } -/// BuiltinAssume - Handle __assume (MS Extension). -// __assume does not evaluate its arguments, and should warn if its argument -// has side effects. bool Sema::BuiltinAssume(CallExpr *TheCall) { Expr *Arg = TheCall->getArg(0); if (Arg->isInstantiationDependent()) return false; @@ -5204,9 +5142,6 @@ bool Sema::BuiltinAssume(CallExpr *TheCall) { return false; } -/// Handle __builtin_alloca_with_align. This is declared -/// as (size_t, size_t) where the second size_t must be a power of 2 greater -/// than 8. bool Sema::BuiltinAllocaWithAlign(CallExpr *TheCall) { // The alignment must be a constant integer. Expr *Arg = TheCall->getArg(1); @@ -5238,8 +5173,6 @@ bool Sema::BuiltinAllocaWithAlign(CallExpr *TheCall) { return false; } -/// Handle __builtin_assume_aligned. This is declared -/// as (const void*, size_t, ...) and can take one optional constant int arg. bool Sema::BuiltinAssumeAligned(CallExpr *TheCall) { if (checkArgCountRange(TheCall, 2, 3)) return true; @@ -5364,8 +5297,6 @@ bool Sema::BuiltinOSLogFormat(CallExpr *TheCall) { return false; } -/// BuiltinConstantArg - Handle a check if argument ArgNum of CallExpr -/// TheCall is a constant expression. bool Sema::BuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result) { Expr *Arg = TheCall->getArg(ArgNum); @@ -5382,8 +5313,6 @@ bool Sema::BuiltinConstantArg(CallExpr *TheCall, int ArgNum, return false; } -/// BuiltinConstantArgRange - Handle a check if argument ArgNum of CallExpr -/// TheCall is a constant expression in the range [Low, High]. bool Sema::BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, int High, bool RangeIsError) { if (isConstantEvaluatedContext()) @@ -5415,8 +5344,6 @@ bool Sema::BuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, return false; } -/// BuiltinConstantArgMultiple - Handle a check if argument ArgNum of CallExpr -/// TheCall is a constant expression is a multiple of Num.. bool Sema::BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Num) { llvm::APSInt Result; @@ -5437,8 +5364,6 @@ bool Sema::BuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, return false; } -/// BuiltinConstantArgPower2 - Check if argument ArgNum of TheCall is a -/// constant expression representing a power of 2. bool Sema::BuiltinConstantArgPower2(CallExpr *TheCall, int ArgNum) { llvm::APSInt Result; @@ -5482,9 +5407,6 @@ static bool IsShiftedByte(llvm::APSInt Value) { } } -/// BuiltinConstantArgShiftedByte - Check if argument ArgNum of TheCall is -/// a constant expression representing an arbitrary byte value shifted left by -/// a multiple of 8 bits. bool Sema::BuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum, unsigned ArgBits) { llvm::APSInt Result; @@ -5509,11 +5431,6 @@ bool Sema::BuiltinConstantArgShiftedByte(CallExpr *TheCall, int ArgNum, << Arg->getSourceRange(); } -/// BuiltinConstantArgShiftedByteOr0xFF - Check if argument ArgNum of -/// TheCall is a constant expression representing either a shifted byte value, -/// or a value of the form 0x??FF (i.e. a member of the arithmetic progression -/// 0x00FF, 0x01FF, ..., 0xFFFF). This strange range check is needed for some -/// Arm MVE intrinsics. bool Sema::BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, unsigned ArgBits) { llvm::APSInt Result; @@ -5541,9 +5458,6 @@ bool Sema::BuiltinConstantArgShiftedByteOrXXFF(CallExpr *TheCall, int ArgNum, << Arg->getSourceRange(); } -/// BuiltinLongjmp - Handle __builtin_longjmp(void *env[5], int val). -/// This checks that the target supports __builtin_longjmp and -/// that val is a constant 1. bool Sema::BuiltinLongjmp(CallExpr *TheCall) { if (!Context.getTargetInfo().hasSjLjLowering()) return Diag(TheCall->getBeginLoc(), diag::err_builtin_longjmp_unsupported) @@ -5563,8 +5477,6 @@ bool Sema::BuiltinLongjmp(CallExpr *TheCall) { return false; } -/// BuiltinSetjmp - Handle __builtin_setjmp(void *env[5]). -/// This checks that the target supports __builtin_setjmp. bool Sema::BuiltinSetjmp(CallExpr *TheCall) { if (!Context.getTargetInfo().hasSjLjLowering()) return Diag(TheCall->getBeginLoc(), diag::err_builtin_setjmp_unsupported) @@ -6125,9 +6037,6 @@ Sema::FormatStringType Sema::GetFormatStringType(const FormatAttr *Format) { .Default(FST_Unknown); } -/// CheckFormatArguments - Check calls to printf and scanf (and similar -/// functions) for correct use of format strings. -/// Returns true if a format string has been fully checked. bool Sema::CheckFormatArguments(const FormatAttr *Format, ArrayRef<const Expr *> Args, bool IsCXXMember, VariadicCallType CallType, SourceLocation Loc, @@ -8305,7 +8214,6 @@ void Sema::CheckInfNaNFunction(const CallExpr *Call, << 0 << 0 << Call->getSourceRange(); } -// Warn when using the wrong abs() function. void Sema::CheckAbsoluteValueFunction(const CallExpr *Call, const FunctionDecl *FDecl) { if (Call->getNumArgs() != 1) @@ -8714,13 +8622,6 @@ static void CheckMemaccessSize(Sema &S, unsigned BId, const CallExpr *Call) { } } -/// Check for dangerous or invalid arguments to memset(). -/// -/// This issues warnings on known problematic, dangerous or unspecified -/// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp' -/// function calls. -/// -/// \param Call The call expression to diagnose. void Sema::CheckMemaccessArguments(const CallExpr *Call, unsigned BId, IdentifierInfo *FnName) { @@ -8947,8 +8848,6 @@ static bool isConstantSizeArrayWithMoreThanOneElement(QualType Ty, return true; } -// Warn if the user has made the 'size' argument to strlcpy or strlcat -// be the size of the source, instead of the destination. void Sema::CheckStrlcpycatArguments(const CallExpr *Call, IdentifierInfo *FnName) { @@ -9034,9 +8933,6 @@ static const Expr *getStrlenExprArg(const Expr *E) { return nullptr; } -// Warn on anti-patterns as the 'size' argument to strncat. -// The correct size argument should look like following: -// strncat(dst, src, sizeof(dst) - strlen(dest) - 1); void Sema::CheckStrncatArguments(const CallExpr *CE, IdentifierInfo *FnName) { // Don't crash if the user has the wrong number of arguments. @@ -9195,7 +9091,6 @@ void CheckFreeArgumentsCast(Sema &S, const std::string &CalleeName, } } // namespace -/// Alerts the user that they are attempting to free a non-malloc'd object. void Sema::CheckFreeArguments(const CallExpr *E) { const std::string CalleeName = cast<FunctionDecl>(E->getCalleeDecl())->getQualifiedNameAsString(); @@ -9273,8 +9168,6 @@ Sema::CheckReturnValExpr(Expr *RetValExp, QualType lhsType, PPC().CheckPPCMMAType(RetValExp->getType(), ReturnLoc); } -/// Check for comparisons of floating-point values using == and !=. Issue a -/// warning if the comparison is not likely to do what the programmer intended. void Sema::CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS, BinaryOperatorKind Opcode) { if (!BinaryOperator::isEqualityOp(Opcode)) @@ -11614,12 +11507,6 @@ static bool IsInAnyMacroBody(const SourceManager &SM, SourceLocation Loc) { return false; } -/// Diagnose pointers that are always non-null. -/// \param E the expression containing the pointer -/// \param NullKind NPCK_NotNull if E is a cast to bool, otherwise, E is -/// compared to a null pointer -/// \param IsEqual True when the comparison is equal to a null pointer -/// \param Range Extra SourceRange to highlight in the diagnostic void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, Expr::NullPointerConstantKind NullKind, bool IsEqual, SourceRange Range) { @@ -11819,13 +11706,6 @@ void Sema::DiagnoseAlwaysNonNullPointer(Expr *E, << FixItHint::CreateInsertion(getLocForEndOfToken(E->getEndLoc()), "()"); } -/// Diagnoses "dangerous" implicit conversions within the given -/// expression (which is a full expression). Implements -Wconversion -/// and -Wsign-compare. -/// -/// \param CC the "context" location of the implicit conversion, i.e. -/// the most location of the syntactic entity requiring the implicit -/// conversion void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { // Don't diagnose in unevaluated contexts. if (isUnevaluatedContext()) @@ -11844,14 +11724,10 @@ void Sema::CheckImplicitConversions(Expr *E, SourceLocation CC) { AnalyzeImplicitConversions(*this, E, CC); } -/// CheckBoolLikeConversion - Check conversion of given expression to boolean. -/// Input argument E is a logical expression. void Sema::CheckBoolLikeConversion(Expr *E, SourceLocation CC) { ::CheckBoolLikeConversion(*this, E, CC); } -/// Diagnose when expression is an integer constant expression and its evaluation -/// results in integer overflow void Sema::CheckForIntOverflow (const Expr *E) { // Use a work list to deal with nested struct initializers. SmallVector<const Expr *, 2> Exprs(1, E); @@ -12816,11 +12692,6 @@ static void diagnoseArrayStarInParamType(Sema &S, QualType PType, S.Diag(Loc, diag::err_array_star_in_function_definition); } -/// CheckParmsForFunctionDef - Check that the parameters of the given -/// function are appropriate for the definition of a function. This -/// takes care of any checks that cannot be performed on the -/// declaration itself, e.g., that the types of each of the function -/// parameters are complete. bool Sema::CheckParmsForFunctionDef(ArrayRef<ParmVarDecl *> Parameters, bool CheckParameterNames) { bool HasInvalidParm = false; @@ -13152,8 +13023,6 @@ static CharUnits getPresumedAlignmentOfPointer(const Expr *E, Sema &S) { return S.Context.getTypeAlignInChars(E->getType()->getPointeeType()); } -/// CheckCastAlign - Implements -Wcast-align, which warns when a -/// pointer cast increases the alignment requirements. void Sema::CheckCastAlign(Expr *Op, QualType T, SourceRange TRange) { // This is actually a lot of work to potentially be doing on every // cast; don't do it if we're ignoring -Wcast_align (as is the default). @@ -13700,7 +13569,6 @@ void Sema::DiagnoseEmptyLoopBody(const Stmt *S, //===--- CHECK: Warn on self move with std::move. -------------------------===// -/// DiagnoseSelfMove - Emits a warning if a value is moved to itself. void Sema::DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation OpLoc) { if (Diags.isIgnored(diag::warn_sizeof_pointer_expr_memaccess, OpLoc)) @@ -14812,10 +14680,6 @@ ExprResult Sema::BuiltinMatrixColumnMajorStore(CallExpr *TheCall, return CallResult; } -/// \brief Enforce the bounds of a TCB -/// CheckTCBEnforcement - Enforces that every function in a named TCB only -/// directly calls other functions in the same TCB as marked by the enforce_tcb -/// and enforce_tcb_leaf attributes. void Sema::CheckTCBEnforcement(const SourceLocation CallExprLoc, const NamedDecl *Callee) { // This warning does not make sense in code that has no runtime behavior. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 3f0027b..da2e167 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -284,14 +284,6 @@ static ParsedType buildNamedType(Sema &S, const CXXScopeSpec *SS, QualType T, return S.CreateParsedType(ElTy, Builder.getTypeSourceInfo(S.Context, ElTy)); } -/// If the identifier refers to a type name within this scope, -/// return the declaration of that type. -/// -/// This routine performs ordinary name lookup of the identifier II -/// within the given scope, with optional C++ scope specifier SS, to -/// determine whether the name refers to a type. If so, returns an -/// opaque pointer (actually a QualType) corresponding to that -/// type. Otherwise, returns NULL. ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS, bool isClassName, bool HasTrailingDot, ParsedType ObjectTypePtr, @@ -644,11 +636,6 @@ ParsedType Sema::ActOnMSVCUnknownTypeName(const IdentifierInfo &II, return CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); } -/// isTagName() - This method is called *for error recovery purposes only* -/// to determine if the specified name is a valid tag name ("struct foo"). If -/// so, this returns the TST for the tag corresponding to it (TST_enum, -/// TST_union, TST_struct, TST_interface, TST_class). This is used to diagnose -/// cases in C where the user forgot to specify the tag. DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { // Do a tag name lookup in this scope. LookupResult R(*this, &II, SourceLocation(), LookupTagName); @@ -673,20 +660,6 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) { return DeclSpec::TST_unspecified; } -/// isMicrosoftMissingTypename - In Microsoft mode, within class scope, -/// if a CXXScopeSpec's type is equal to the type of one of the base classes -/// then downgrade the missing typename error to a warning. -/// This is needed for MSVC compatibility; Example: -/// @code -/// template<class T> class A { -/// public: -/// typedef int TYPE; -/// }; -/// template<class T> class B : public A<T> { -/// public: -/// A<T>::TYPE a; // no typename required because A<T> is a base class. -/// }; -/// @endcode bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S) { if (CurContext->isRecord()) { if (SS->getScopeRep()->getKind() == NestedNameSpecifier::Super) @@ -1362,9 +1335,6 @@ void Sema::ActOnTagFinishSkippedDefinition(SkippedDefinitionContext Context) { CurContext = static_cast<decltype(CurContext)>(Context); } -/// EnterDeclaratorContext - Used when we must lookup names in the context -/// of a declarator's nested name specifier. -/// void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) { // C++0x [basic.lookup.unqual]p13: // A name used in the definition of a static data member of class @@ -1522,7 +1492,6 @@ static bool AllowOverloadingOfFunction(const LookupResult &Previous, return false; } -/// Add this decl to the scope shadowed decl chains. void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) { // Move up the scope chain until we find the nearest enclosing // non-transparent context. The declaration will be introduced into this @@ -1605,8 +1574,6 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *, DeclContext*, ASTContext&); -/// Filters out lookup results that don't fall within the given scope -/// as determined by isDeclInScope. void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, bool ConsiderLinkage, bool AllowInlineNamespace) { @@ -1626,8 +1593,6 @@ void Sema::FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, F.done(); } -/// We've determined that \p New is a redeclaration of \p Old. Check that they -/// have compatible owning modules. bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) { // [module.interface]p7: // A declaration is attached to a module as follows: @@ -1687,9 +1652,6 @@ bool Sema::CheckRedeclarationModuleOwnership(NamedDecl *New, NamedDecl *Old) { return false; } -// [module.interface]p6: -// A redeclaration of an entity X is implicitly exported if X was introduced by -// an exported declaration; otherwise it shall not be exported. bool Sema::CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old) { // [module.interface]p1: // An export-declaration shall inhabit a namespace scope. @@ -1727,8 +1689,6 @@ bool Sema::CheckRedeclarationExported(NamedDecl *New, NamedDecl *Old) { return true; } -// A wrapper function for checking the semantic restrictions of -// a redeclaration within a module. bool Sema::CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old) { if (CheckRedeclarationModuleOwnership(New, Old)) return true; @@ -1739,22 +1699,6 @@ bool Sema::CheckRedeclarationInModule(NamedDecl *New, NamedDecl *Old) { return false; } -// Check the redefinition in C++20 Modules. -// -// [basic.def.odr]p14: -// For any definable item D with definitions in multiple translation units, -// - if D is a non-inline non-templated function or variable, or -// - if the definitions in different translation units do not satisfy the -// following requirements, -// the program is ill-formed; a diagnostic is required only if the definable -// item is attached to a named module and a prior definition is reachable at -// the point where a later definition occurs. -// - Each such definition shall not be attached to a named module -// ([module.unit]). -// - Each such definition shall consist of the same sequence of tokens, ... -// ... -// -// Return true if the redefinition is not allowed. Return false otherwise. bool Sema::IsRedefinitionInModule(const NamedDecl *New, const NamedDecl *Old) const { assert(getASTContext().isSameEntity(New, Old) && @@ -1851,18 +1795,6 @@ static bool IsDisallowedCopyOrAssign(const CXXMethodDecl *D) { return D->isCopyAssignmentOperator(); } -// We need this to handle -// -// typedef struct { -// void *foo() { return 0; } -// } A; -// -// When we see foo we don't know if after the typedef we will get 'A' or '*A' -// for example. If 'A', foo will have external linkage. If we have '*A', -// foo will have no linkage. Since we can't know until we get to the end -// of the typedef, this function finds out if D might have non-external linkage. -// Callers should verify at the end of the TU if it D has external linkage or -// not. bool Sema::mightHaveNonExternalLinkage(const DeclaratorDecl *D) { const DeclContext *DC = D->getDeclContext(); while (!DC->isTranslationUnit()) { @@ -2127,8 +2059,6 @@ void Sema::DiagnoseUnusedDecl(const NamedDecl *D) { D, [this](SourceLocation Loc, PartialDiagnostic PD) { Diag(Loc, PD); }); } -/// DiagnoseUnusedDecl - Emit warnings about declarations that are not used -/// unless they are marked attr(unused). void Sema::DiagnoseUnusedDecl(const NamedDecl *D, DiagReceiverTy DiagReceiver) { if (!ShouldDiagnoseUnusedDecl(getLangOpts(), D)) return; @@ -2318,29 +2248,6 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { } } -/// getNonFieldDeclScope - Retrieves the innermost scope, starting -/// from S, where a non-field would be declared. This routine copes -/// with the difference between C and C++ scoping rules in structs and -/// unions. For example, the following code is well-formed in C but -/// ill-formed in C++: -/// @code -/// struct S6 { -/// enum { BAR } e; -/// }; -/// -/// void test_S6() { -/// struct S6 a; -/// a.e = BAR; -/// } -/// @endcode -/// For the declaration of BAR, this routine will return a different -/// scope. The scope S will be the scope of the unnamed enumeration -/// within S6. In C++, this routine will return the scope associated -/// with S6, because the enumeration's scope is a transparent -/// context but structures can contain non-field names. In C, this -/// routine will return the translation unit scope, since the -/// enumeration's scope is a transparent context and structures cannot -/// contain non-field names. Scope *Sema::getNonFieldDeclScope(Scope *S) { while (((S->getFlags() & Scope::DeclScope) == 0) || (S->getEntity() && S->getEntity()->isTransparentContext()) || @@ -2403,10 +2310,6 @@ FunctionDecl *Sema::CreateBuiltin(IdentifierInfo *II, QualType Type, return New; } -/// LazilyCreateBuiltin - The specified Builtin-ID was first used at -/// file scope. lazily create a decl for it. ForRedeclaration is true -/// if we're creating this built-in in anticipation of redeclaring the -/// built-in. NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S, bool ForRedeclaration, SourceLocation Loc) { @@ -2545,11 +2448,6 @@ bool Sema::isIncompatibleTypedef(const TypeDecl *Old, TypedefNameDecl *New) { return false; } -/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the -/// same name and scope as a previous declaration 'Old'. Figure out -/// how to resolve this situation, merging decls or emitting -/// diagnostics as appropriate. If there was an error, set New to be invalid. -/// void Sema::MergeTypedefNameDecl(Scope *S, TypedefNameDecl *New, LookupResult &OldDecls) { // If the new decl is known invalid already, don't bother doing any @@ -3160,7 +3058,6 @@ static void diagnoseMissingConstinit(Sema &S, const VarDecl *InitDecl, } } -/// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, AvailabilityMergeKind AMK) { if (UsedAttr *OldAttr = Old->getMostRecentDecl()->getAttr<UsedAttr>()) { @@ -3619,17 +3516,6 @@ static void adjustDeclContextForDeclaratorDecl(DeclaratorDecl *NewD, FixSemaDC(VD->getDescribedVarTemplate()); } -/// MergeFunctionDecl - We just parsed a function 'New' from -/// declarator D which has the same name and scope as a previous -/// declaration 'Old'. Figure out how to resolve this situation, -/// merging decls or emitting diagnostics as appropriate. -/// -/// In C++, New and Old must be declarations that are not -/// overloaded. Use IsOverload to determine whether New and Old are -/// overloaded, and to select the Old declaration that New should be -/// merged with. -/// -/// Returns true if there was an error, false otherwise. bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, bool MergeTypeWithOld, bool NewDeclIsDefn) { // Verify the old decl was also a function. @@ -4361,15 +4247,6 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD, Scope *S, return true; } -/// Completes the merge of two function declarations that are -/// known to be compatible. -/// -/// This routine handles the merging of attributes and other -/// properties of function declarations from the old declaration to -/// the new declaration, once we know that New is in fact a -/// redeclaration of Old. -/// -/// \returns false bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, Scope *S, bool MergeTypeWithOld) { // Merge the attributes @@ -4445,13 +4322,6 @@ static void diagnoseVarDeclTypeMismatch(Sema &S, VarDecl *New, VarDecl* Old) { New->setInvalidDecl(); } -/// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and -/// scope as a previous declaration 'Old'. Figure out how to merge their types, -/// emitting diagnostics as appropriate. -/// -/// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back -/// to here in AddInitializerToDecl. We can't check them before the initializer -/// is attached. void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old, bool MergeTypeWithOld) { if (New->isInvalidDecl() || Old->isInvalidDecl() || New->getType()->containsErrors() || Old->getType()->containsErrors()) @@ -4568,14 +4438,6 @@ static bool mergeTypeWithPrevious(Sema &S, VarDecl *NewVD, VarDecl *OldVD, } } -/// MergeVarDecl - We just parsed a variable 'New' which has the same name -/// and scope as a previous declaration 'Old'. Figure out how to resolve this -/// situation, merging decls or emitting diagnostics as appropriate. -/// -/// Tentative definition rules (C99 6.9.2p2) are checked by -/// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative -/// definitions here, since the initializer hasn't been attached. -/// void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // If the new decl is already invalid, don't do any other checking. if (New->isInvalidDecl()) @@ -4868,8 +4730,6 @@ void Sema::notePreviousDefinition(const NamedDecl *Old, SourceLocation New) { Diag(Old->getLocation(), diag::note_previous_definition); } -/// We've just determined that \p Old and \p New both appear to be definitions -/// of the same variable. Either diagnose or fix the problem. bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) { if (!hasVisibleDefinition(Old) && (New->getFormalLinkage() == Linkage::Internal || New->isInline() || @@ -4893,8 +4753,6 @@ bool Sema::checkVarDeclRedefinition(VarDecl *Old, VarDecl *New) { } } -/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with -/// no declarator (e.g. "struct foo;") is parsed. Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, const ParsedAttributesView &DeclAttrs, @@ -5116,9 +4974,7 @@ static unsigned GetDiagnosticTypeSpecifierID(const DeclSpec &DS) { llvm_unreachable("unexpected type specifier"); } } -/// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with -/// no declarator (e.g. "struct foo;") is parsed. It also accepts template -/// parameters to cope with template friend declarations. + Decl *Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, const ParsedAttributesView &DeclAttrs, @@ -5416,10 +5272,6 @@ void Sema::ActOnDefinedDeclarationSpecifier(Decl *D) { DiagPlaceholderFieldDeclDefinitions(RD); } -/// Emit diagnostic warnings for placeholder members. -/// We can only do that after the class is fully constructed, -/// as anonymous union/structs can insert placeholders -/// in their parent scope (which might be a Record). void Sema::DiagPlaceholderFieldDeclDefinitions(RecordDecl *Record) { if (!getLangOpts().CPlusPlus) return; @@ -5573,10 +5425,6 @@ static void checkDuplicateDefaultInit(Sema &S, CXXRecordDecl *Parent, checkDuplicateDefaultInit(S, Parent, findDefaultInitializer(AnonUnion)); } -/// BuildAnonymousStructOrUnion - Handle the declaration of an -/// anonymous structure or union. Anonymous unions are a C++ feature -/// (C++ [class.union]) and a C11 feature; anonymous structures -/// are a C11 feature and GNU C++ extension. Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, AccessSpecifier AS, RecordDecl *Record, @@ -5853,19 +5701,6 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, return Anon; } -/// BuildMicrosoftCAnonymousStruct - Handle the declaration of an -/// Microsoft C anonymous structure. -/// Ref: http://msdn.microsoft.com/en-us/library/z2cx9y4f.aspx -/// Example: -/// -/// struct A { int a; }; -/// struct B { struct A; int b; }; -/// -/// void foo() { -/// B var; -/// var.a = 3; -/// } -/// Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, RecordDecl *Record) { assert(Record && "expected a record!"); @@ -5908,13 +5743,10 @@ Decl *Sema::BuildMicrosoftCAnonymousStruct(Scope *S, DeclSpec &DS, return Anon; } -/// GetNameForDeclarator - Determine the full declaration name for the -/// given Declarator. DeclarationNameInfo Sema::GetNameForDeclarator(Declarator &D) { return GetNameFromUnqualifiedId(D.getName()); } -/// Retrieves the declaration name from a parsed unqualified-id. DeclarationNameInfo Sema::GetNameFromUnqualifiedId(const UnqualifiedId &Name) { DeclarationNameInfo NameInfo; @@ -6204,13 +6036,6 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { return Dcl; } -/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: -/// If T is the name of a class, then each of the following shall have a -/// name different from T: -/// - every static data member of class T; -/// - every member function of class T -/// - every member of class T that is itself a type; -/// \returns true if the declaration name violates these rules. bool Sema::DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo NameInfo) { DeclarationName Name = NameInfo.getName(); @@ -6226,24 +6051,6 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, return false; } -/// Diagnose a declaration whose declarator-id has the given -/// nested-name-specifier. -/// -/// \param SS The nested-name-specifier of the declarator-id. -/// -/// \param DC The declaration context to which the nested-name-specifier -/// resolves. -/// -/// \param Name The name of the entity being declared. -/// -/// \param Loc The location of the name of the entity being declared. -/// -/// \param IsMemberSpecialization Whether we are declaring a member -/// specialization. -/// -/// \param TemplateId The template-id, if any. -/// -/// \returns true if we cannot safely recover from this error, false otherwise. bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, SourceLocation Loc, @@ -6727,8 +6534,6 @@ TryToFixInvalidVariablyModifiedTypeSourceInfo(TypeSourceInfo *TInfo, return FixedTInfo; } -/// Attempt to fold a variable-sized type to a constant-sized type, returning -/// true if we were successful. bool Sema::tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, QualType &T, SourceLocation Loc, unsigned FailedFoldDiagID) { @@ -6752,10 +6557,6 @@ bool Sema::tryToFixVariablyModifiedVarType(TypeSourceInfo *&TInfo, return false; } -/// Register the given locally-scoped extern "C" declaration so -/// that it can be found later for redeclarations. We include any extern "C" -/// declaration that is not visible in the translation unit here, not just -/// function-scope declarations. void Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) { if (!getLangOpts().CPlusPlus && @@ -6773,8 +6574,6 @@ NamedDecl *Sema::findLocallyScopedExternCDecl(DeclarationName Name) { return Result.empty() ? nullptr : *Result.begin(); } -/// Diagnose function specifiers on a declaration of an identifier that -/// does not identify a function. void Sema::DiagnoseFunctionSpecifiers(const DeclSpec &DS) { // FIXME: We should probably indicate the identifier in question to avoid // confusion for constructs like "virtual int a(), b;" @@ -6875,9 +6674,6 @@ Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) { } } -/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which -/// declares a typedef-name, either using the 'typedef' type specifier or via -/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. NamedDecl* Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, LookupResult &Previous, bool &Redeclaration) { @@ -7364,8 +7160,6 @@ static bool hasParsedAttr(Scope *S, const Declarator &PD, PD.getDeclarationAttributes().hasAttribute(Kind); } -/// Adjust the \c DeclContext for a function or variable that might be a -/// function-local external declaration. bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) { if (!DC->isFunctionOrMethod()) return false; @@ -8316,8 +8110,6 @@ static bool shouldWarnIfShadowedDecl(const DiagnosticsEngine &Diags, return !Diags.isIgnored(diag::warn_decl_shadow, R.getNameLoc()); } -/// Return the declaration shadowed by the given variable \p D, or null -/// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, const LookupResult &R) { if (!shouldWarnIfShadowedDecl(Diags, R)) @@ -8332,8 +8124,6 @@ NamedDecl *Sema::getShadowedDeclaration(const VarDecl *D, : nullptr; } -/// Return the declaration shadowed by the given typedef \p D, or null -/// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D, const LookupResult &R) { // Don't warn if typedef declaration is part of a class @@ -8347,8 +8137,6 @@ NamedDecl *Sema::getShadowedDeclaration(const TypedefNameDecl *D, return isa<TypedefNameDecl>(ShadowedDecl) ? ShadowedDecl : nullptr; } -/// Return the declaration shadowed by the given variable \p D, or null -/// if it doesn't shadow any declaration or shadowing warnings are disabled. NamedDecl *Sema::getShadowedDeclaration(const BindingDecl *D, const LookupResult &R) { if (!shouldWarnIfShadowedDecl(Diags, R)) @@ -8359,15 +8147,6 @@ NamedDecl *Sema::getShadowedDeclaration(const BindingDecl *D, : nullptr; } -/// Diagnose variable or built-in function shadowing. Implements -/// -Wshadow. -/// -/// This method is called whenever a VarDecl is added to a "useful" -/// scope. -/// -/// \param ShadowedDecl the declaration that is shadowed by the given variable -/// \param R the lookup of the name -/// void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, const LookupResult &R) { DeclContext *NewDC = D->getDeclContext(); @@ -8484,8 +8263,6 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl, Diag(ShadowedDecl->getLocation(), diag::note_previous_declaration); } -/// Diagnose shadowing for variables shadowed in the lambda record \p LambdaRD -/// when these variables are captured by the lambda. void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) { for (const auto &Shadow : LSI->ShadowingDecls) { const NamedDecl *ShadowedDecl = Shadow.ShadowedDecl; @@ -8513,7 +8290,6 @@ void Sema::DiagnoseShadowingLambdaDecls(const LambdaScopeInfo *LSI) { } } -/// Check -Wshadow without the advantage of a previous lookup. void Sema::CheckShadow(Scope *S, VarDecl *D) { if (Diags.isIgnored(diag::warn_decl_shadow, D->getLocation())) return; @@ -9001,18 +8777,6 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) { } } -/// Perform semantic checking on a newly-created variable -/// declaration. -/// -/// This routine performs all of the type-checking required for a -/// variable declaration once it has been built. It is used both to -/// check variables after they have been parsed and their declarators -/// have been translated into a declaration, and to check variables -/// that have been instantiated from a template. -/// -/// Sets NewVD->isInvalidDecl() if an error was encountered. -/// -/// Returns true if the variable declaration is a redeclaration. bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { CheckVariableDeclarationType(NewVD); @@ -9033,8 +8797,6 @@ bool Sema::CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous) { return false; } -/// AddOverriddenMethods - See if a method overrides any in the base classes, -/// and if so, check that it's a valid override and remember it. bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { llvm::SmallPtrSet<const CXXMethodDecl*, 4> Overridden; @@ -11095,15 +10857,6 @@ static Attr *getImplicitCodeSegAttrFromClass(Sema &S, const FunctionDecl *FD) { return nullptr; } -/// Returns an implicit CodeSegAttr if a __declspec(code_seg) is found on a -/// containing class. Otherwise it will return implicit SectionAttr if the -/// function is a definition and there is an active value on CodeSegStack -/// (from the current #pragma code-seg value). -/// -/// \param FD Function being declared. -/// \param IsDefinition Whether it is a definition or just a declaration. -/// \returns A CodeSegAttr or SectionAttr to apply to the function or -/// nullptr if no attribute should be added. Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition) { if (Attr *A = getImplicitCodeSegAttrFromClass(*this, FD)) @@ -11116,14 +10869,6 @@ Attr *Sema::getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, return nullptr; } -/// Determines if we can perform a correct type check for \p D as a -/// redeclaration of \p PrevDecl. If not, we can generally still perform a -/// best-effort check. -/// -/// \param NewD The new declaration. -/// \param OldD The old declaration. -/// \param NewT The portion of the type of the new declaration to check. -/// \param OldT The portion of the type of the old declaration to check. bool Sema::canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD, QualType NewT, QualType OldT) { if (!NewD->getLexicalDeclContext()->isDependentContext()) @@ -11148,15 +10893,6 @@ bool Sema::canFullyTypeCheckRedeclaration(ValueDecl *NewD, ValueDecl *OldD, return true; } -/// Checks if the new declaration declared in dependent context must be -/// put in the same redeclaration chain as the specified declaration. -/// -/// \param D Declaration that is checked. -/// \param PrevDecl Previous declaration found with proper lookup method for the -/// same declaration name. -/// \returns True if D must be added to the redeclaration chain which PrevDecl -/// belongs to. -/// bool Sema::shouldLinkDependentDeclWithPrevious(Decl *D, Decl *PrevDecl) { if (!D->getLexicalDeclContext()->isDependentContext()) return true; @@ -12032,23 +11768,6 @@ static void CheckConstPureAttributesUsage(Sema &S, FunctionDecl *NewFD) { } } -/// Perform semantic checking of a new function declaration. -/// -/// Performs semantic analysis of the new function declaration -/// NewFD. This routine performs all semantic checking that does not -/// require the actual declarator involved in the declaration, and is -/// used both for the declaration of functions as they are parsed -/// (called via ActOnDeclarator) and for the declaration of functions -/// that have been instantiated via C++ template instantiation (called -/// via InstantiateDecl). -/// -/// \param IsMemberSpecialization whether this new function declaration is -/// a member specialization (that replaces any definition provided by the -/// previous declaration). -/// -/// This sets NewFD->isInvalidDecl() to true if there was an error. -/// -/// \returns true if the function declaration is a redeclaration. bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, LookupResult &Previous, bool IsMemberSpecialization, @@ -13502,9 +13221,6 @@ void Sema::checkNonTrivialCUnion(QualType QT, SourceLocation Loc, .visit(QT, nullptr, false); } -/// AddInitializerToDecl - Adds the initializer Init to the -/// declaration dcl. If DirectInit is true, this is C++ direct -/// initialization rather than copy initialization. void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // If there is no declaration, there was an error parsing it. Just ignore // the initializer. @@ -14022,10 +13738,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { CheckCompleteVariableDeclaration(VDecl); } -/// ActOnInitializerError - Given that there was an error parsing an -/// initializer for the given declaration, try to at least re-establish -/// invariants such as whether a variable's type is either dependent or -/// complete. void Sema::ActOnInitializerError(Decl *D) { // Our main concern here is re-establishing invariants like "a // variable's type is either dependent or complete". @@ -14743,8 +14455,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { CheckCompleteDecompositionDeclaration(DD); } -/// Check if VD needs to be dllexport/dllimport due to being in a -/// dllexport/import function. void Sema::CheckStaticLocalForDllExport(VarDecl *VD) { assert(VD->isStaticLocal()); @@ -14802,8 +14512,6 @@ void Sema::CheckThreadLocalForLargeAlignment(VarDecl *VD) { } } -/// FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform -/// any semantic actions necessary after any initializer has been attached. void Sema::FinalizeDeclaration(Decl *ThisDecl) { // Note that we are no longer parsing the initializer for this declaration. ParsingInitForAutoVars.erase(ThisDecl); @@ -15033,8 +14741,6 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, return BuildDeclaratorGroup(Decls); } -/// BuildDeclaratorGroup - convert a list of declarations into a declaration -/// group, performing any necessary semantic checking. Sema::DeclGroupPtrTy Sema::BuildDeclaratorGroup(MutableArrayRef<Decl *> Group) { // C++14 [dcl.spec.auto]p7: (DR1347) @@ -15111,8 +14817,6 @@ void Sema::ActOnDocumentableDecls(ArrayRef<Decl *> Group) { Context.attachCommentsToJustParsedDecls(Group, &getPreprocessor()); } -/// Common checks for a parameter-declaration that should apply to both function -/// parameters and non-type template parameters. void Sema::CheckFunctionOrTemplateParamDeclarator(Scope *S, Declarator &D) { // Check that there are no default arguments inside the type of this // parameter. @@ -15172,8 +14876,6 @@ static void CheckExplicitObjectParameter(Sema &S, ParmVarDecl *P, LSI->ExplicitObjectParameter = P; } -/// ActOnParamDeclarator - Called from Parser::ParseFunctionDeclarator() -/// to introduce parameters into function prototype scope. Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, SourceLocation ExplicitThisLoc) { const DeclSpec &DS = D.getDeclSpec(); @@ -15282,8 +14984,6 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D, return New; } -/// Synthesizes a variable for a parameter arising from a -/// typedef. ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T) { @@ -15922,18 +15622,6 @@ void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) { } } -/// Given the set of return statements within a function body, -/// compute the variables that are subject to the named return value -/// optimization. -/// -/// Each of the variables that is subject to the named return value -/// optimization will be marked as NRVO variables in the AST, and any -/// return statement that has a marked NRVO variable as its NRVO candidate can -/// use the named return value optimization. -/// -/// This function applies a very simplistic algorithm for NRVO: if every return -/// statement in the scope of a variable has the same NRVO candidate, that -/// candidate is an NRVO variable. void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { ReturnStmt **Returns = Scope->Returns.data(); @@ -16526,8 +16214,6 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, checkThisInStaticMemberFunctionAttributes(Method); } -/// ImplicitlyDefineFunction - An undeclared identifier was used in a function -/// call, forming a call to an implicitly defined function (per C99 6.5.1p2). NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II, Scope *S) { // It is not valid to implicitly define a function in C23. @@ -16660,12 +16346,6 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, return FD; } -/// If this function is a C++ replaceable global allocation function -/// (C++2a [basic.stc.dynamic.allocation], C++2a [new.delete]), -/// adds any function attributes that we know a priori based on the standard. -/// -/// We need to check for duplicate attributes both here and where user-written -/// attributes are applied to declarations. void Sema::AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction( FunctionDecl *FD) { if (FD->isInvalidDecl()) @@ -16735,15 +16415,6 @@ void Sema::AddKnownFunctionAttributesForReplaceableGlobalAllocationFunction( // have new-extended alignment and is of the requested size. } -/// Adds any function attributes that we know a priori based on -/// the declaration of this function. -/// -/// These attributes can apply both to implicitly-declared builtins -/// (like __builtin___printf_chk) or to library-declared functions -/// like NSLog or printf. -/// -/// We need to check for duplicate attributes both here and where user-written -/// attributes are applied to declarations. void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { if (FD->isInvalidDecl()) return; @@ -16994,7 +16665,6 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, return NewTD; } -/// Check that this is a valid underlying type for an enum declaration. bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); QualType T = TI->getType(); @@ -17012,8 +16682,6 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { << T << T->isBitIntType(); } -/// Check whether this is a valid redeclaration of a previous enumeration. -/// \return true if the redeclaration was invalid. bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy, bool IsFixed, const EnumDecl *Prev) { @@ -17098,10 +16766,6 @@ Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl, llvm_unreachable("invalid TTK"); } -/// Determine whether a tag with a given kind is acceptable -/// as a redeclaration of the given tag declaration. -/// -/// \returns true if the new tag kind is acceptable, false otherwise. bool Sema::isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag, bool isDefinition, SourceLocation NewTagLoc, @@ -17285,16 +16949,6 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, return false; } -/// This is invoked when we see 'struct foo' or 'struct {'. In the -/// former case, Name will be non-null. In the later case, Name will be null. -/// TagSpec indicates what kind of tag this is. TUK indicates whether this is a -/// reference/declaration/definition of a tag. -/// -/// \param IsTypeSpecifier \c true if this is a type-specifier (or -/// trailing-type-specifier) other than one in an alias-declaration. -/// -/// \param SkipBody If non-null, will be set to indicate if the caller should -/// skip the definition of this tag and treat it as if it were a declaration. DeclResult Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -18541,8 +18195,6 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc, return BitWidth; } -/// ActOnField - Each field of a C struct/union is passed into this in order -/// to create a FieldDecl object for it. Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, Declarator &D, Expr *BitfieldWidth) { FieldDecl *Res = HandleField(S, cast_if_present<RecordDecl>(TagD), DeclStart, @@ -18551,8 +18203,6 @@ Decl *Sema::ActOnField(Scope *S, Decl *TagD, SourceLocation DeclStart, return Res; } -/// HandleField - Analyze a field of a C struct or a C++ data member. -/// FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, SourceLocation DeclStart, Declarator &D, Expr *BitWidth, @@ -18648,16 +18298,6 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, return NewFD; } -/// Build a new FieldDecl and check its well-formedness. -/// -/// This routine builds a new FieldDecl given the fields name, type, -/// record, etc. \p PrevDecl should refer to any previous declaration -/// with the same name and in the same scope as the field to be -/// created. -/// -/// \returns a new FieldDecl. -/// -/// \todo The Declarator argument is a hack. It will be removed once FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, RecordDecl *Record, SourceLocation Loc, @@ -18911,10 +18551,6 @@ bool Sema::CheckNontrivialField(FieldDecl *FD) { return false; } -/// ActOnLastBitfield - This routine handles synthesized bitfields rules for -/// class and class extensions. For every class \@interface and class -/// extension \@interface, if the last ivar is a bitfield of any type, -/// then add an implicit `char :0` ivar to the end of that interface. void Sema::ActOnLastBitfield(SourceLocation DeclLoc, SmallVectorImpl<Decl *> &AllIvarDecls) { if (LangOpts.ObjCRuntime.isFragile() || AllIvarDecls.empty()) @@ -20589,8 +20225,6 @@ bool Sema::shouldIgnoreInHostDeviceCheck(FunctionDecl *Callee) { CUDA().IdentifyTarget(Callee) == CUDAFunctionTarget::Global; } -// Report a failure to merge function effects between declarations due to a -// conflict. void Sema::diagnoseFunctionEffectMergeConflicts( const FunctionEffectSet::Conflicts &Errs, SourceLocation NewLoc, SourceLocation OldLoc) { @@ -20601,7 +20235,6 @@ void Sema::diagnoseFunctionEffectMergeConflicts( } } -// Warn and return true if adding an effect to a set would create a conflict. bool Sema::diagnoseConflictingFunctionEffect( const FunctionEffectsRef &FX, const FunctionEffectWithCondition &NewEC, SourceLocation NewAttrLoc) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index b8842e9..6edf1fa 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -111,9 +111,6 @@ static bool checkPositiveIntArgument(Sema &S, const AttrInfo &AI, const Expr *Ex return true; } -/// Check if the argument \p E is a ASCII string literal. If not emit an error -/// and return false, otherwise set \p Str to the value of the string literal -/// and return true. bool Sema::checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation) { @@ -131,10 +128,6 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, return true; } -/// Check if the argument \p ArgNum of \p Attr is a ASCII string literal. -/// If not emit an error and return false. If the argument is an identifier it -/// will emit an error with a fixit hint and treat it as if it was a string -/// literal. bool Sema::checkStringLiteralArgumentAttr(const ParsedAttr &AL, unsigned ArgNum, StringRef &Str, SourceLocation *ArgLocation) { @@ -2843,15 +2836,6 @@ SectionAttr *Sema::mergeSectionAttr(Decl *D, const AttributeCommonInfo &CI, return ::new (Context) SectionAttr(Context, CI, Name); } -/// Used to implement to perform semantic checking on -/// attribute((section("foo"))) specifiers. -/// -/// In this case, "foo" is passed in to be checked. If the section -/// specifier is invalid, return an Error that indicates the problem. -/// -/// This is a simple quality of implementation feature to catch errors -/// and give good diagnostics in cases when the assembler or code generator -/// would otherwise reject the section specifier. llvm::Error Sema::isValidSectionSpecifier(StringRef SecName) { if (!Context.getTargetInfo().getTriple().isOSDarwin()) return llvm::Error::success(); @@ -2964,8 +2948,6 @@ static void handleCodeSegAttr(Sema &S, Decl *D, const ParsedAttr &AL) { D->addAttr(CSA); } -// Check for things we'd like to warn about. Multiversioning issues are -// handled later in the process, once we know how many exist. bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { enum FirstParam { Unsupported, Duplicate, Unknown }; enum SecondParam { None, CPU, Tune }; @@ -3027,7 +3009,6 @@ bool Sema::checkTargetAttr(SourceLocation LiteralLoc, StringRef AttrStr) { return false; } -// Check Target Version attrs bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D, StringRef &AttrStr, bool &isDefault) { enum FirstParam { Unsupported }; @@ -5066,8 +5047,6 @@ bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, return false; } -/// Checks a regparm attribute, returning true if it is ill-formed and -/// otherwise setting numParams to the appropriate value. bool Sema::CheckRegparmAttr(const ParsedAttr &AL, unsigned &numParams) { if (AL.isInvalid()) return true; @@ -7253,8 +7232,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, } } -/// ProcessDeclAttributeList - Apply all the decl attributes in the specified -/// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList( Scope *S, Decl *D, const ParsedAttributesView &AttrList, const ProcessDeclAttributeOptions &Options) { @@ -7328,8 +7305,6 @@ void Sema::ProcessDeclAttributeList( } } -// Helper for delayed processing TransparentUnion or BPFPreserveAccessIndexAttr -// attribute. void Sema::ProcessDeclAttributeDelayed(Decl *D, const ParsedAttributesView &AttrList) { for (const ParsedAttr &AL : AttrList) @@ -7344,8 +7319,6 @@ void Sema::ProcessDeclAttributeDelayed(Decl *D, BPF().handlePreserveAIRecord(cast<RecordDecl>(D)); } -// Annotation attributes are the only attributes allowed after an access -// specifier. bool Sema::ProcessAccessDeclAttributeList( AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { for (const ParsedAttr &AL : AttrList) { @@ -7380,9 +7353,6 @@ static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { } } -/// checkUnusedDeclAttributes - Given a declarator which is not being -/// used to build a declaration, complain about any decl attributes -/// which might be lying around on it. void Sema::checkUnusedDeclAttributes(Declarator &D) { ::checkUnusedDeclAttributes(*this, D.getDeclarationAttributes()); ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes()); @@ -7391,8 +7361,6 @@ void Sema::checkUnusedDeclAttributes(Declarator &D) { ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); } -/// DeclClonePragmaWeak - clone existing decl (maybe definition), -/// \#pragma weak needs a non-definition decl and source may not have one. NamedDecl *Sema::DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II, SourceLocation Loc) { assert(isa<FunctionDecl>(ND) || isa<VarDecl>(ND)); @@ -7437,8 +7405,6 @@ NamedDecl *Sema::DeclClonePragmaWeak(NamedDecl *ND, const IdentifierInfo *II, return NewD; } -/// DeclApplyPragmaWeak - A declaration (maybe definition) needs \#pragma weak -/// applied to it, possibly with an alias. void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, const WeakInfo &W) { if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) IdentifierInfo *NDId = ND->getIdentifier(); @@ -7657,9 +7623,6 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { } while ((pool = pool->getParent())); } -/// Given a set of delayed diagnostics, re-emit them as if they had -/// been delayed in the current context instead of in the given pool. -/// Essentially, this just moves them to the current pool. void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) { DelayedDiagnosticPool *curPool = DelayedDiagnostics.getCurrentPool(); assert(curPool && "re-emitting in undelayed context not supported"); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ffa6bca..59487bf 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -326,9 +326,6 @@ void Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, } } -/// ActOnParamDefaultArgument - Check whether the default argument -/// provided for a function parameter is well-formed. If so, attach it -/// to the parameter declaration. void Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, Expr *DefaultArg) { @@ -374,10 +371,6 @@ Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, SetParamDefaultArgument(Param, DefaultArg, EqualLoc); } -/// ActOnParamUnparsedDefaultArgument - We've seen a default -/// argument for a function parameter, but we can't parse it yet -/// because we're inside a class definition. Note that this default -/// argument will be parsed later. void Sema::ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc, SourceLocation ArgLoc) { @@ -389,8 +382,6 @@ void Sema::ActOnParamUnparsedDefaultArgument(Decl *param, UnparsedDefaultArgLocs[Param] = ArgLoc; } -/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of -/// the default argument for the parameter param failed. void Sema::ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc, Expr *DefaultArg) { if (!param) @@ -410,11 +401,6 @@ void Sema::ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc, Param->setDefaultArg(RE.get()); } -/// CheckExtraCXXDefaultArguments - Check for any extra default -/// arguments in the declarator, which is not a function declaration -/// or definition and therefore is not permitted to have default -/// arguments. This routine should be invoked for every declarator -/// that is not a function declaration or definition. void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { // C++ [dcl.fct.default]p3 // A default argument expression shall be specified only in the @@ -466,10 +452,6 @@ static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) { }); } -/// MergeCXXFunctionDecl - Merge two declarations of the same C++ -/// function, once we already know that they have the same -/// type. Subroutine of MergeFunctionDecl. Returns true if there was an -/// error, false otherwise. bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, Scope *S) { bool Invalid = false; @@ -1607,11 +1589,6 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { DD->setInvalidDecl(); } -/// Merge the exception specifications of two variable declarations. -/// -/// This is called when there's a redeclaration of a VarDecl. The function -/// checks if the redeclaration might have an exception specification and -/// validates compatibility and merges the specs if necessary. void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { // Shortcut if exceptions are disabled. if (!getLangOpts().CXXExceptions) @@ -1808,12 +1785,6 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, Sema::CheckConstexprKind Kind); static bool CheckConstexprMissingReturn(Sema &SemaRef, const FunctionDecl *Dcl); -// Check whether a function declaration satisfies the requirements of a -// constexpr function definition or a constexpr constructor definition. If so, -// return true. If not, produce appropriate diagnostics (unless asked not to by -// Kind) and return false. -// -// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, CheckConstexprKind Kind) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); @@ -2617,14 +2588,6 @@ void Sema::DiagnoseImmediateEscalatingReason(FunctionDecl *FD) { Visitor.TraverseDecl(FD); } -/// Get the class that is directly named by the current context. This is the -/// class for which an unqualified-id in this scope could name a constructor -/// or destructor. -/// -/// If the scope specifier denotes a class, this will be that class. -/// If the scope specifier is empty, this will be the class whose -/// member-specification we are currently within. Otherwise, there -/// is no such class. CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) { assert(getLangOpts().CPlusPlus && "No class names in C!"); @@ -2639,19 +2602,12 @@ CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) { return dyn_cast_or_null<CXXRecordDecl>(CurContext); } -/// isCurrentClassName - Determine whether the identifier II is the -/// name of the class type currently being defined. In the case of -/// nested classes, this will only return true if II is the name of -/// the innermost class. bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS) { CXXRecordDecl *CurDecl = getCurrentClass(S, SS); return CurDecl && &II == CurDecl->getIdentifier(); } -/// Determine whether the identifier II is a typo for the name of -/// the class type currently being defined. If so, update it to the identifier -/// that should have been used. bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { assert(getLangOpts().CPlusPlus && "No class names in C!"); @@ -2675,10 +2631,6 @@ bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { return false; } -/// Check the validity of a C++ base class specifier. -/// -/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics -/// and returns NULL otherwise. CXXBaseSpecifier *Sema::CheckBaseSpecifier(CXXRecordDecl *Class, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, @@ -2798,11 +2750,6 @@ CXXBaseSpecifier *Sema::CheckBaseSpecifier(CXXRecordDecl *Class, Access, TInfo, EllipsisLoc); } -/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is -/// one entry in the base class list of a class specifier, for -/// example: -/// class foo : public bar, virtual private baz { -/// 'public bar' and 'virtual private baz' are each base-specifiers. BaseResult Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, const ParsedAttributesView &Attributes, bool Virtual, AccessSpecifier Access, @@ -2882,8 +2829,6 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, } } -/// Performs the actual work of attaching the given base class -/// specifiers to a C++ class. bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, MutableArrayRef<CXXBaseSpecifier *> Bases) { if (Bases.empty()) @@ -2989,9 +2934,6 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, return Invalid; } -/// ActOnBaseSpecifiers - Attach the given base specifiers to the -/// class, after checking whether there are any duplicate base -/// classes. void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, MutableArrayRef<CXXBaseSpecifier *> Bases) { if (!ClassDecl || Bases.empty()) @@ -3001,8 +2943,6 @@ void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases); } -/// Determine whether the type \p Derived is a C++ class that is -/// derived from the type \p Base. bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { if (!getLangOpts().CPlusPlus) return false; @@ -3028,8 +2968,6 @@ bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { return DerivedRD->isDerivedFrom(BaseRD); } -/// Determine whether the type \p Derived is a C++ class that is -/// derived from the type \p Base. bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, CXXBasePaths &Paths) { if (!getLangOpts().CPlusPlus) @@ -3074,18 +3012,7 @@ void Sema::BuildBasePathArray(const CXXBasePaths &Paths, assert(Paths.isRecordingPaths() && "Must record paths!"); return ::BuildBasePathArray(Paths.front(), BasePathArray); } -/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base -/// conversion (where Derived and Base are class types) is -/// well-formed, meaning that the conversion is unambiguous (and -/// that all of the base classes are accessible). Returns true -/// and emits a diagnostic if the code is ill-formed, returns false -/// otherwise. Loc is the location where this routine should point to -/// if there is an error, and Range is the source range to highlight -/// if there is an error. -/// -/// If either InaccessibleBaseID or AmbiguousBaseConvID are 0, then the -/// diagnostic for the respective type of error will be suppressed, but the -/// check for ill-formed code will still be performed. + bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, unsigned InaccessibleBaseID, @@ -3179,19 +3106,6 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, BasePath, IgnoreAccess); } - -/// Builds a string representing ambiguous paths from a -/// specific derived class to different subobjects of the same base -/// class. -/// -/// This function builds a string that can be used in error messages -/// to show the different paths that one can take through the -/// inheritance hierarchy to go from the derived class to different -/// subobjects of a base class. The result looks something like this: -/// @code -/// struct D -> struct B -> struct A -/// struct D -> struct C -> struct A -/// @endcode std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { std::string PathDisplayStr; std::set<unsigned> DisplayedPaths; @@ -3215,7 +3129,6 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { // C++ class member Handling //===----------------------------------------------------------------------===// -/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, const ParsedAttributesView &Attrs) { @@ -3226,7 +3139,6 @@ bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, return ProcessAccessDeclAttributeList(ASDecl, Attrs); } -/// CheckOverrideControl - Check C++11 override control semantics. void Sema::CheckOverrideControl(NamedDecl *D) { if (D->isInvalidDecl()) return; @@ -3330,9 +3242,6 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent) { } } -/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member -/// function overrides a virtual member function marked 'final', according to -/// C++11 [class.virtual]p4. bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old) { FinalAttr *FA = Old->getAttr<FinalAttr>(); @@ -3356,7 +3265,6 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { return false; } -// Check if there is a field shadowing. void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, DeclarationName FieldName, const CXXRecordDecl *RD, @@ -3407,11 +3315,6 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, } } -/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member -/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the -/// bitfield width if there is one, 'InitExpr' specifies the initializer if -/// one has been parsed, and 'InitStyle' is set if an in-class initializer is -/// present (but parsing it has been deferred). NamedDecl * Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, @@ -4123,9 +4026,6 @@ namespace { } } // namespace -/// Enter a new C++ default initializer scope. After calling this, the -/// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if -/// parsing or instantiating the initializer failed. void Sema::ActOnStartCXXInClassMemberInitializer() { // Create a synthetic function scope to represent the call to the constructor // that notionally surrounds a use of this initializer. @@ -4180,9 +4080,6 @@ ExprResult Sema::ConvertMemberDefaultInitExpression(FieldDecl *FD, return Seq.Perform(*this, Entity, Kind, InitExpr); } -/// This is invoked after parsing an in-class initializer for a -/// non-static C++ class member, and after instantiating an in-class initializer -/// in a class template. Such actions are deferred until the class is complete. void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, SourceLocation InitLoc, Expr *InitExpr) { @@ -4269,7 +4166,6 @@ static bool FindBaseInitializer(Sema &SemaRef, return DirectBaseSpec || VirtualBaseSpec; } -/// Handle a C++ member initializer using braced-init-list syntax. MemInitResult Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, @@ -4285,7 +4181,6 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, EllipsisLoc); } -/// Handle a C++ member initializer using parentheses syntax. MemInitResult Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, @@ -4384,7 +4279,6 @@ ValueDecl *Sema::tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl, return tryLookupUnambiguousFieldDecl(ClassDecl, MemberOrBase); } -/// Handle a C++ member initializer. MemInitResult Sema::BuildMemInitializer(Decl *ConstructorD, Scope *S, @@ -5734,7 +5628,6 @@ bool CheckRedundantUnionInit(Sema &S, } } // namespace -/// ActOnMemInitializers - Handle the member initializers for a constructor. void Sema::ActOnMemInitializers(Decl *ConstructorDecl, SourceLocation ColonLoc, ArrayRef<CXXCtorInitializer*> MemInits, @@ -6485,7 +6378,6 @@ void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) { } } -/// Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -6659,8 +6551,6 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { DelayedDllExportClasses.push_back(Class); } -/// Perform propagation of DLL attributes from a derived class to a -/// templated base class for MS compatibility. void Sema::propagateDLLAttrToBaseClassTemplate( CXXRecordDecl *Class, Attr *ClassAttr, ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) { @@ -6719,13 +6609,6 @@ void Sema::propagateDLLAttrToBaseClassTemplate( } } -/// Determine the kind of defaulting that would be done for a given function. -/// -/// If the function is both a default constructor and a copy / move constructor -/// (due to having a default argument for the first parameter), this picks -/// CXXSpecialMemberKind::DefaultConstructor. -/// -/// FIXME: Check that case is properly handled by all callers. Sema::DefaultedFunctionKind Sema::getDefaultedFunctionKind(const FunctionDecl *FD) { if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) { @@ -6947,13 +6830,6 @@ ReportOverrides(Sema &S, unsigned DiagID, const CXXMethodDecl *MD, return IssuedDiagnostic; } -/// Perform semantic checks on a class definition that has been -/// completing, introducing implicitly-declared members, checking for -/// abstract types, etc. -/// -/// \param S The scope in which the class was parsed. Null if we didn't just -/// parse a class definition. -/// \param Record The completed class. void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { if (!Record) return; @@ -10124,8 +10000,6 @@ static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, return true; } -/// Diagnose why the specified class does not have a trivial special member of -/// the given kind. void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMemberKind CSM) { QualType Ty = Context.getRecordType(RD); @@ -10137,9 +10011,6 @@ void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, /*Diagnose*/true); } -/// Determine whether a defaulted or deleted special member function is trivial, -/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, -/// C++11 [class.copy]p25, and C++11 [class.dtor]p5. bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM, TrivialABIHandling TAH, bool Diagnose) { assert(!MD->isUserProvided() && CSM != CXXSpecialMemberKind::Invalid && @@ -10370,8 +10241,6 @@ static void AddMostOverridenMethods(const CXXMethodDecl *MD, AddMostOverridenMethods(O, Methods); } -/// Check if a method overloads virtual methods in a base class without -/// overriding any. void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) { if (!MD->getDeclName().isIdentifier()) @@ -10411,8 +10280,6 @@ void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD, } } -/// Diagnose methods which overload virtual methods in a base class -/// without overriding any. void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) { if (MD->isInvalidDecl()) return; @@ -10600,11 +10467,6 @@ static void findImplicitlyDeclaredEqualityComparisons( } } -/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared -/// special functions, such as the default constructor, copy -/// constructor, or destructor, to the given C++ class (C++ -/// [special]p1). This routine can only be executed just before the -/// definition of the class is complete. void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // Don't add implicit special members to templated classes. // FIXME: This means unqualified lookups for 'operator=' within a class @@ -10781,9 +10643,6 @@ void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) { PopDeclContext(); } -/// This is used to implement the constant expression evaluation part of the -/// attribute enable_if extension. There is nothing in standard C++ which would -/// require reentering parameters. void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) { if (!Param) return; @@ -10793,14 +10652,6 @@ void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) { IdResolver.AddDecl(Param); } -/// ActOnStartDelayedCXXMethodDeclaration - We have completed -/// parsing a top-level (non-nested) C++ class, and we are now -/// parsing those parts of the given Method declaration that could -/// not be parsed earlier (C++ [class.mem]p2), such as default -/// arguments. This action should enter the scope of the given -/// Method declaration as if we had just parsed the qualified method -/// name. However, it should not bring the parameters into scope; -/// that will be performed by ActOnDelayedCXXMethodParameter. void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { } @@ -10820,12 +10671,6 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { IdResolver.AddDecl(Param); } -/// ActOnFinishDelayedCXXMethodDeclaration - We have finished -/// processing the delayed method declaration for Method. The method -/// declaration is now considered finished. There may be a separate -/// ActOnStartOfFunctionDef action later (not necessarily -/// immediately!) for this method, if it was also defined inside the -/// class body. void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { if (!MethodD) return; @@ -10867,12 +10712,6 @@ static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) { } } -/// CheckConstructorDeclarator - Called by ActOnDeclarator to check -/// the well-formedness of the constructor declarator @p D with type @p -/// R. If there are any errors in the declarator, this routine will -/// emit diagnostics and set the invalid bit to true. In any case, the type -/// will be updated to reflect a well-formed type for the constructor and -/// returned. QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, StorageClass &SC) { bool isVirtual = D.getDeclSpec().isVirtualSpecified(); @@ -10933,9 +10772,6 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); } -/// CheckConstructor - Checks a fully-formed constructor for -/// well-formedness, issuing any diagnostics required. Returns true if -/// the constructor declarator is invalid. void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { CXXRecordDecl *ClassDecl = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext()); @@ -10968,9 +10804,6 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { } } -/// CheckDestructor - Checks a fully-formed destructor definition for -/// well-formedness, issuing any diagnostics required. Returns true -/// on error. bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { CXXRecordDecl *RD = Destructor->getParent(); @@ -11020,12 +10853,6 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { return false; } -/// CheckDestructorDeclarator - Called by ActOnDeclarator to check -/// the well-formednes of the destructor declarator @p D with type @p -/// R. If there are any errors in the declarator, this routine will -/// emit diagnostics and set the declarator to invalid. Even if this happens, -/// will be updated to reflect a well-formed type for the destructor and -/// returned. QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, StorageClass& SC) { // C++ [class.dtor]p1: @@ -11142,12 +10969,6 @@ static void extendRight(SourceRange &R, SourceRange After) { R.setEnd(After.getEnd()); } -/// CheckConversionDeclarator - Called by ActOnDeclarator to check the -/// well-formednes of the conversion function declarator @p D with -/// type @p R. If there are any errors in the declarator, this routine -/// will emit diagnostics and return true. Otherwise, it will return -/// false. Either way, the type @p R will be updated to reflect a -/// well-formed type for the conversion operator. void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, StorageClass& SC) { // C++ [class.conv.fct]p1: @@ -11321,10 +11142,6 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, << SourceRange(DS.getExplicitSpecRange()); } -/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete -/// the declaration of the given C++ conversion function. This routine -/// is responsible for recording the conversion function in the C++ -/// class, if possible. Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { assert(Conversion && "Expected to receive a conversion function declaration"); @@ -11496,10 +11313,6 @@ struct BadSpecifierDiagnoser { }; } -/// Check the validity of a declarator that we parsed for a deduction-guide. -/// These aren't actually declarators in the grammar, so we need to check that -/// the user didn't specify any pieces that are not part of the deduction-guide -/// grammar. Return true on invalid deduction-guide. bool Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, StorageClass &SC) { TemplateName GuidedTemplate = D.getName().TemplateName.get().get(); @@ -11823,8 +11636,6 @@ static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { return dyn_cast_or_null<NamespaceDecl>(D); } -/// ActOnFinishNamespaceDef - This callback is called after a namespace is -/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl); assert(Namespc && "Invalid parameter, expected NamespaceDecl"); @@ -11988,8 +11799,6 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind, return Info->getType(); } -/// Retrieve the special "std" namespace, which may require us to -/// implicitly define the namespace. NamespaceDecl *Sema::getOrCreateStdNamespace() { if (!StdNamespace) { // The "std" namespace has not yet been defined, so build one implicitly. @@ -12473,9 +12282,6 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) { return false; } - -/// Determines whether to create a using shadow decl for a particular -/// decl, given the set of decls existing prior to this using lookup. bool Sema::CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Orig, const LookupResult &Previous, UsingShadowDecl *&PrevShadow) { @@ -12658,7 +12464,6 @@ static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl *Base) { llvm_unreachable("not a direct base class"); } -/// Builds a shadow declaration corresponding to a 'using' declaration. UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD, NamedDecl *Orig, UsingShadowDecl *PrevDecl) { @@ -12702,33 +12507,6 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD, return Shadow; } -/// Hides a using shadow declaration. This is required by the current -/// using-decl implementation when a resolvable using declaration in a -/// class is followed by a declaration which would hide or override -/// one or more of the using decl's targets; for example: -/// -/// struct Base { void foo(int); }; -/// struct Derived : Base { -/// using Base::foo; -/// void foo(int); -/// }; -/// -/// The governing language is C++03 [namespace.udecl]p12: -/// -/// When a using-declaration brings names from a base class into a -/// derived class scope, member functions in the derived class -/// override and/or hide member functions with the same name and -/// parameter types in a base class (rather than conflicting). -/// -/// There are two ways to implement this: -/// (1) optimistically create shadow decls when they're not hidden -/// by existing declarations, or -/// (2) don't create any shadow decls (or at least don't make them -/// visible) until we've fully parsed/instantiated the class. -/// The problem with (1) is that we might have to retroactively remove -/// a shadow decl, which requires several O(n) operations because the -/// decl structures are (very reasonably) not designed for removal. -/// (2) avoids this but is very fiddly and phase-dependent. void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { if (Shadow->getDeclName().getNameKind() == DeclarationName::CXXConversionFunctionName) @@ -12850,11 +12628,6 @@ private: }; } // end anonymous namespace -/// Remove decls we can't actually see from a lookup being used to declare -/// shadow using decls. -/// -/// \param S - The scope of the potential shadow decl -/// \param Previous - The lookup of a potential shadow decl's name. void Sema::FilterUsingLookup(Scope *S, LookupResult &Previous) { // It is really dumb that we have to do this. LookupResult::Filter F = Previous.makeFilter(); @@ -12873,11 +12646,6 @@ void Sema::FilterUsingLookup(Scope *S, LookupResult &Previous) { F.done(); } -/// Builds a using declaration. -/// -/// \param IsInstantiation - Whether this call arises from an -/// instantiation of an unresolved using declaration. We treat -/// the lookup differently for these declarations. NamedDecl *Sema::BuildUsingDeclaration( Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, @@ -13204,7 +12972,6 @@ NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom, return UPD; } -/// Additional checks for a using declaration referring to a constructor name. bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { assert(!UD->hasTypename() && "expecting a constructor name"); @@ -13232,9 +12999,6 @@ bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { return false; } -/// Checks that the given using declaration is not an invalid -/// redeclaration. Note that this is checking only for the using decl -/// itself, not for any ill-formedness among the UsingShadowDecls. bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, bool HasTypenameKeyword, const CXXScopeSpec &SS, @@ -13310,13 +13074,6 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, return false; } -/// Checks that the given nested-name qualifier used in a using decl -/// in the current context is appropriately related to the current -/// scope. If an error is found, diagnoses it and returns true. -/// R is nullptr, if the caller has not (yet) done a lookup, otherwise it's the -/// result of that lookup. UD is likewise nullptr, except when we have an -/// already-populated UsingDecl whose shadow decls contain the same information -/// (i.e. we're instantiating a UsingDecl with non-dependent scope). bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, bool HasTypename, const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, @@ -14425,8 +14182,6 @@ void Sema::CheckCompleteDestructorVariant(SourceLocation CurrentLocation, MarkVirtualBaseDestructorsReferenced(Destructor->getLocation(), ClassDecl); } -/// Perform any semantic analysis which needs to be delayed until all -/// pending class member declarations have been parsed. void Sema::ActOnFinishCXXMemberDecls() { // If the context is an invalid C++ class, just suppress these checks. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) { @@ -16250,11 +16005,6 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { Diag(VD->getLocation(), diag::warn_global_destructor); } -/// Given a constructor and the set of arguments provided for the -/// constructor, convert the arguments and add any required default arguments -/// to form a proper call to this constructor. -/// -/// \returns true if an error occurred, false otherwise. bool Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, QualType DeclInitType, MultiExprArg ArgsPtr, SourceLocation Loc, @@ -16464,9 +16214,6 @@ CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { return false; } -/// CheckOverloadedOperatorDeclaration - Check whether the declaration -/// of this overloaded operator is well-formed. If so, returns false; -/// otherwise, emits appropriate diagnostics and returns true. bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { assert(FnDecl && FnDecl->isOverloadedOperator() && "Expected an overloaded operator declaration"); @@ -16691,9 +16438,6 @@ checkLiteralOperatorTemplateParameterList(Sema &SemaRef, return true; } -/// CheckLiteralOperatorDeclaration - Check whether the declaration -/// of this literal operator function is well-formed. If so, returns -/// false; otherwise, emits appropriate diagnostics and returns true. bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { if (isa<CXXMethodDecl>(FnDecl)) { Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) @@ -16864,12 +16608,6 @@ bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { return false; } -/// ActOnStartLinkageSpecification - Parsed the beginning of a C++ -/// linkage specification, including the language and (if present) -/// the '{'. ExternLoc is the location of the 'extern', Lang is the -/// language string literal. LBraceLoc, if valid, provides the location of -/// the '{' brace. Otherwise, this linkage specification does not -/// have any braces. Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, Expr *LangStr, SourceLocation LBraceLoc) { @@ -16913,10 +16651,6 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, return D; } -/// ActOnFinishLinkageSpecification - Complete the definition of -/// the C++ linkage specification LinkageSpec. If RBraceLoc is -/// valid, it's the position of the closing '}' brace in a linkage -/// specification that uses braces. Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, Decl *LinkageSpec, SourceLocation RBraceLoc) { @@ -16949,9 +16683,6 @@ Decl *Sema::ActOnEmptyDeclaration(Scope *S, return ED; } -/// Perform semantic analysis for the variable declaration that -/// occurs within a C++ catch clause, returning the newly-created -/// variable. VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, SourceLocation StartLoc, SourceLocation Loc, @@ -17086,8 +16817,6 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, return ExDecl; } -/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch -/// handler. Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { TypeSourceInfo *TInfo = GetTypeForDeclarator(D); bool Invalid = D.isInvalidType(); @@ -17331,8 +17060,6 @@ static bool UsefulToPrintExpr(const Expr *E) { return true; } -/// Try to print more useful information about a failed static_assert -/// with expression \E void Sema::DiagnoseStaticAssertDetails(const Expr *E) { if (const auto *Op = dyn_cast<BinaryOperator>(E); Op && Op->getOpcode() != BO_LOr) { @@ -17598,8 +17325,6 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, return Decl; } -/// Handle a friend tag declaration where the scope specifier was -/// templated. DeclResult Sema::ActOnTemplatedFriendTag( Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, @@ -17716,23 +17441,6 @@ DeclResult Sema::ActOnTemplatedFriendTag( return Friend; } -/// Handle a friend type declaration. This works in tandem with -/// ActOnTag. -/// -/// Notes on friend class templates: -/// -/// We generally treat friend class declarations as if they were -/// declaring a class. So, for example, the elaborated type specifier -/// in a friend declaration is required to obey the restrictions of a -/// class-head (i.e. no typedefs in the scope chain), template -/// parameters are required to match up with simple template-ids, &c. -/// However, unlike when declaring a template specialization, it's -/// okay to refer to a template specialization without an empty -/// template parameter declaration, e.g. -/// friend class A<T>::B<unsigned>; -/// We permit this as a special case; if there are any template -/// parameters present at all, require proper matching, i.e. -/// template <> template \<class T> friend class A<int>::B; Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TempParams) { SourceLocation Loc = DS.getBeginLoc(); @@ -18539,11 +18247,6 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, return false; } -/// Mark the given method pure. -/// -/// \param Method the method to be marked pure. -/// -/// \param InitRange the source range that covers the "0" initializer. bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { SourceLocation EndLoc = InitRange.getEnd(); if (EndLoc.isValid()) @@ -18590,7 +18293,6 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { ExpressionEvaluationContext::PotentiallyEvaluated, D); } -/// Invoked after we are finished parsing an initializer for the declaration D. void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { assert(D); @@ -18623,9 +18325,6 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { PopExpressionEvaluationContext(); } -/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a -/// C++ if/switch/while/for statement. -/// e.g: "if (int x = f()) {...}" DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { // C++ 6.4p2: // The declarator shall not specify a function or an array. diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index d226e3b..35a85ef 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -112,12 +112,6 @@ ExprResult Sema::ActOnNoexceptSpec(Expr *NoexceptExpr, return Converted; } -/// CheckSpecifiedExceptionType - Check if the given type is valid in an -/// exception specification. Incomplete types, or pointers to incomplete types -/// other than void are not allowed. -/// -/// \param[in,out] T The exception type. This will be decayed to a pointer type -/// when the input is an array or a function type. bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { // C++11 [except.spec]p2: // A type cv T, "array of T", or "function returning T" denoted @@ -189,9 +183,6 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { return false; } -/// CheckDistantExceptionSpec - Check if the given type is a pointer or pointer -/// to member to a function with an exception specification. This means that -/// it is invalid to add another level of indirection. bool Sema::CheckDistantExceptionSpec(QualType T) { // C++17 removes this rule in favor of putting exception specifications into // the type system. @@ -491,10 +482,6 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { return ReturnValueOnError; } -/// CheckEquivalentExceptionSpec - Check if the two types have equivalent -/// exception specifications. Exception specifications are equivalent if -/// they allow exactly the same set of exception types. It does not matter how -/// that is achieved. See C++ [except.spec]p2. bool Sema::CheckEquivalentExceptionSpec( const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc) { @@ -767,9 +754,6 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) { llvm_unreachable("unexpected access check result"); } -/// CheckExceptionSpecSubset - Check whether the second function type's -/// exception specification is a subset (or equivalent) of the first function -/// type. This is used by override and pointer assignment checks. bool Sema::CheckExceptionSpecSubset( const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, const PartialDiagnostic &NoThrowDiagID, @@ -890,11 +874,6 @@ CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID, SFunc, SourceLoc); } -/// CheckParamExceptionSpec - Check if the parameter and return types of the -/// two functions have equivalent exception specs. This is part of the -/// assignment and override compatibility check. We do not check the parameters -/// of parameter function pointers recursively, as no sane programmer would -/// even be able to write such a function type. bool Sema::CheckParamExceptionSpec( const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID, const FunctionProtoType *Target, bool SkipTargetFirstParameter, diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 66a8de6..59facdf 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -69,8 +69,6 @@ using namespace clang; using namespace sema; -/// Determine whether the use of this declaration is valid, without -/// emitting diagnostics. bool Sema::CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid) { // See if this is an auto-typed variable whose initializer we are parsing. if (ParsingInitForAutoVars.count(D)) @@ -119,7 +117,6 @@ static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { } } -/// Emit a note explaining that this function is deleted. void Sema::NoteDeletedFunction(FunctionDecl *Decl) { assert(Decl && Decl->isDeleted()); @@ -215,18 +212,6 @@ void Sema::MaybeSuggestAddingStaticToDecl(const FunctionDecl *Cur) { } } -/// Determine whether the use of this declaration is valid, and -/// emit any corresponding diagnostics. -/// -/// This routine diagnoses various problems with referencing -/// declarations that can occur when using a declaration. For example, -/// it might warn if a deprecated or unavailable declaration is being -/// used, or produce an error (and return true) if a C++0x deleted -/// function is being used. -/// -/// \returns true if there was an error (this declaration cannot be -/// referenced), false otherwise. -/// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass, bool ObjCPropertyAccess, @@ -419,10 +404,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, return false; } -/// DiagnoseSentinelCalls - This routine checks whether a call or -/// message-send is to a declaration with the sentinel attribute, and -/// if so, it checks that the requirements of the sentinel are -/// satisfied. void Sema::DiagnoseSentinelCalls(const NamedDecl *D, SourceLocation Loc, ArrayRef<Expr *> Args) { const SentinelAttr *Attr = D->getAttr<SentinelAttr>(); @@ -773,8 +754,6 @@ ExprResult Sema::DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose) { return Res; } -/// CallExprUnaryConversions - a special case of an unary conversion -/// performed on a function designator of a call expression. ExprResult Sema::CallExprUnaryConversions(Expr *E) { QualType Ty = E->getType(); ExprResult Res = E; @@ -942,9 +921,6 @@ ExprResult Sema::DefaultArgumentPromotion(Expr *E) { return E; } -/// Determine the degree of POD-ness for an expression. -/// Incomplete types are considered POD, since this check can be performed -/// when we're in an unevaluated context. Sema::VarArgKind Sema::isValidVarArgType(const QualType &Ty) { if (Ty->isIncompleteType()) { // C++11 [expr.call]p7: @@ -1045,8 +1021,6 @@ void Sema::checkVariadicArgument(const Expr *E, VariadicCallType CT) { } } -/// DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but -/// will create a trap if the resulting type is not a POD type. ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, FunctionDecl *FDecl) { if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) { @@ -2052,12 +2026,6 @@ Sema::ExpandFunctionLocalPredefinedMacros(ArrayRef<Token> Toks) { return ExpandedToks; } -/// ActOnStringLiteral - The specified tokens were lexed as pasted string -/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string -/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from -/// multiple tokens. However, the common case is that StringToks points to one -/// string. -/// ExprResult Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) { assert(!StringToks.empty() && "Must have at least one string!"); @@ -2283,8 +2251,6 @@ NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) { return NOUR_None; } -/// BuildDeclRefExpr - Build an expression that references a -/// declaration that does not require a closure capture. DeclRefExpr * Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, const DeclarationNameInfo &NameInfo, @@ -2342,15 +2308,6 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, return E; } -/// Decomposes the given name into a DeclarationNameInfo, its location, and -/// possibly a list of template arguments. -/// -/// If this produces template arguments, it is permitted to call -/// DecomposeTemplateName. -/// -/// This actually loses a lot of source location information for -/// non-standard name kinds; we should consider preserving that in -/// some way. void Sema::DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, @@ -2407,14 +2364,6 @@ static void emitEmptyLookupTypoDiagnostic( SemaRef.PDiag(NoteID)); } -/// Diagnose a lookup that found results in an enclosing class during error -/// recovery. This usually indicates that the results were found in a dependent -/// base class that could not be searched as part of a template definition. -/// Always issues a diagnostic (though this may be only a warning in MS -/// compatibility mode). -/// -/// Return \c true if the error is unrecoverable, or \c false if the caller -/// should attempt to recover using these lookup results. bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { // During a default argument instantiation the CurContext points // to a CXXMethodDecl; but we can't apply a this-> fixit inside a @@ -2474,9 +2423,6 @@ bool Sema::DiagnoseDependentMemberLookup(const LookupResult &R) { return false; } -/// Diagnose an empty lookup. -/// -/// \return false if new lookup candidates were found bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, CorrectionCandidateCallback &CCC, TemplateArgumentListInfo *ExplicitTemplateArgs, @@ -2914,10 +2860,6 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, return BuildDeclarationNameExpr(SS, R, ADL); } -/// BuildQualifiedDeclarationNameExpr - Build a C++ qualified -/// declaration name, generally during template instantiation. -/// There's a large number of things which don't need to be done along -/// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { @@ -2990,26 +2932,6 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( return BuildDeclarationNameExpr(SS, R, /*ADL=*/false); } -/// Cast a base object to a member's actual type. -/// -/// There are two relevant checks: -/// -/// C++ [class.access.base]p7: -/// -/// If a class member access operator [...] is used to access a non-static -/// data member or non-static member function, the reference is ill-formed if -/// the left operand [...] cannot be implicitly converted to a pointer to the -/// naming class of the right operand. -/// -/// C++ [expr.ref]p7: -/// -/// If E2 is a non-static data member or a non-static member function, the -/// program is ill-formed if the class of which E2 is directly a member is an -/// ambiguous base (11.8) of the naming class (11.9.3) of E2. -/// -/// Note that the latter check does not consider access; the access of the -/// "real" base class is checked as appropriate when checking the access of the -/// member name. ExprResult Sema::PerformObjectMemberConversion(Expr *From, NestedNameSpecifier *Qualifier, @@ -3268,7 +3190,6 @@ static void diagnoseUncapturableValueReferenceOrBinding(Sema &S, SourceLocation loc, ValueDecl *var); -/// Complete semantic analysis for a reference to the given declaration. ExprResult Sema::BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, @@ -4253,13 +4174,6 @@ static void warnOnSizeofOnArrayDecay(Sema &S, SourceLocation Loc, QualType T, << ICE->getSubExpr()->getType(); } -/// Check the constraints on expression operands to unary type expression -/// and type traits. -/// -/// Completes any types necessary and validates the constraints on the operand -/// expression. The logic mostly mirrors the type-based overload, but may modify -/// the expression as it completes the type for that expression through template -/// instantiation, etc. bool Sema::CheckUnaryExprOrTypeTraitOperand(Expr *E, UnaryExprOrTypeTrait ExprKind) { QualType ExprTy = E->getType(); @@ -4551,21 +4465,6 @@ static void captureVariablyModifiedType(ASTContext &Context, QualType T, } while (!T.isNull() && T->isVariablyModifiedType()); } -/// Check the constraints on operands to unary expression and type -/// traits. -/// -/// This will complete any types necessary, and validate the various constraints -/// on those operands. -/// -/// The UsualUnaryConversions() function is *not* called by this routine. -/// C99 6.3.2.1p[2-4] all state: -/// Except when it is the operand of the sizeof operator ... -/// -/// C++ [expr.sizeof]p4 -/// The lvalue-to-rvalue, array-to-pointer, and function-to-pointer -/// standard conversions are not applied to the operand of sizeof. -/// -/// This policy is followed for all of the unary trait expressions. bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, SourceLocation OpLoc, SourceRange ExprRange, @@ -4652,7 +4551,6 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType, return false; } -/// Build a sizeof or alignof expression given a type operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, @@ -4678,8 +4576,6 @@ ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd()); } -/// Build a sizeof or alignof expression given an expression -/// operand. ExprResult Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind) { @@ -4723,9 +4619,6 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, ExprKind, E, Context.getSizeType(), OpLoc, E->getSourceRange().getEnd()); } -/// ActOnUnaryExprOrTypeTraitExpr - Handle @c sizeof(type) and @c sizeof @c -/// expr and the same for @c alignof and @c __alignof -/// Note that the ArgRange is invalid if isType is false. ExprResult Sema::ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, UnaryExprOrTypeTrait ExprKind, bool IsType, @@ -4752,13 +4645,6 @@ bool Sema::CheckAlignasTypeArgument(StringRef KWName, TypeSourceInfo *TInfo, UETT_AlignOf, KWName); } -/// ActOnAlignasTypeArgument - Handle @c alignas(type-id) and @c -/// _Alignas(type-name) . -/// [dcl.align] An alignment-specifier of the form -/// alignas(type-id) has the same effect as alignas(alignof(type-id)). -/// -/// [N1570 6.7.5] _Alignas(type-name) is equivalent to -/// _Alignas(_Alignof(type-name)). bool Sema::ActOnAlignasTypeArgument(StringRef KWName, ParsedType Ty, SourceLocation OpLoc, SourceRange R) { TypeSourceInfo *TInfo; @@ -5818,12 +5704,6 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) { return false; } -/// ConvertArgumentsForCall - Converts the arguments specified in -/// Args/NumArgs to the parameter types of the function FDecl with -/// function prototype Proto. Call is the call expression itself, and -/// Fn is the function expression. For a C++ member function, this -/// routine does not attempt to convert the object argument. Returns -/// true if the call is ill-formed. bool Sema::ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl, @@ -6078,14 +5958,6 @@ static void DiagnoseCalleeStaticArrayParam(Sema &S, ParmVarDecl *PVD) { << ATL.getLocalSourceRange(); } -/// CheckStaticArrayArgument - If the given argument corresponds to a static -/// array parameter, check that it is non-null, and that if it is formed by -/// array-to-pointer decay, the underlying array is sufficiently large. -/// -/// C99 6.7.5.3p7: If the keyword static also appears within the [ and ] of the -/// array type derivation, then for each call to the function, the value of the -/// corresponding actual argument shall provide access to the first element of -/// an array with at least as many elements as specified by the size expression. void Sema::CheckStaticArrayArgument(SourceLocation CallLoc, ParmVarDecl *Param, @@ -6486,9 +6358,6 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, return Call; } -/// BuildCallExpr - Handle a call to Fn with the specified array of arguments. -/// This provides the location of the left/right parens and a list of comma -/// locations. ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig, bool IsExecConfig, @@ -6689,8 +6558,6 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, ExecConfig, IsExecConfig); } -/// BuildBuiltinCallExpr - Create a call to a builtin function specified by Id -// with the specified CallArgs Expr *Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs) { StringRef Name = Context.BuiltinInfo.getName(Id); @@ -6712,10 +6579,6 @@ Expr *Sema::BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, return Call.get(); } -/// Parse a __builtin_astype expression. -/// -/// __builtin_astype( value, dst type ) -/// ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { @@ -6723,7 +6586,6 @@ ExprResult Sema::ActOnAsTypeExpr(Expr *E, ParsedType ParsedDestTy, return BuildAsTypeExpr(E, DstTy, BuiltinLoc, RParenLoc); } -/// Create a new AsTypeExpr node (bitcast) from the arguments. ExprResult Sema::BuildAsTypeExpr(Expr *E, QualType DestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { @@ -6738,11 +6600,6 @@ ExprResult Sema::BuildAsTypeExpr(Expr *E, QualType DestTy, return new (Context) AsTypeExpr(E, DestTy, VK, OK, BuiltinLoc, RParenLoc); } -/// ActOnConvertVectorExpr - create a new convert-vector expression from the -/// provided arguments. -/// -/// __builtin_convertvector( value, dst type ) -/// ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, SourceLocation BuiltinLoc, SourceLocation RParenLoc) { @@ -6751,12 +6608,6 @@ ExprResult Sema::ActOnConvertVectorExpr(Expr *E, ParsedType ParsedDestTy, return ConvertVectorExpr(E, TInfo, BuiltinLoc, RParenLoc); } -/// BuildResolvedCallExpr - Build a call to a resolved expression, -/// i.e. an expression not of \p OverloadTy. The expression should -/// unary-convert to an expression of function-pointer or -/// block-pointer type. -/// -/// \param NDecl the declaration being called, if available ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, SourceLocation LParenLoc, ArrayRef<Expr *> Args, @@ -7307,7 +7158,6 @@ Sema::BuildInitList(SourceLocation LBraceLoc, MultiExprArg InitArgList, return E; } -/// Do an explicit extend of the given block pointer if we're in ARC. void Sema::maybeExtendBlockObject(ExprResult &E) { assert(E.get()->getType()->isBlockPointerType()); assert(E.get()->isPRValue()); @@ -7321,8 +7171,6 @@ void Sema::maybeExtendBlockObject(ExprResult &E) { Cleanup.setExprNeedsCleanups(true); } -/// Prepares for a scalar cast, performing all the necessary stages -/// except the final cast and returning the kind required. CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { // Both Src and Dest are scalar types, i.e. arithmetic or pointer. // Also, callers should have filtered out the invalid cases with @@ -7549,12 +7397,6 @@ static bool breakDownVectorType(QualType type, uint64_t &len, return true; } -/// Are the two types SVE-bitcast-compatible types? I.e. is bitcasting from the -/// first SVE type (e.g. an SVE VLAT) to the second type (e.g. an SVE VLST) -/// allowed? -/// -/// This will also return false if the two given types do not make sense from -/// the perspective of SVE bitcasts. bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) { assert(srcTy->isVectorType() || destTy->isVectorType()); @@ -7570,8 +7412,6 @@ bool Sema::isValidSveBitcast(QualType srcTy, QualType destTy) { ValidScalableConversion(destTy, srcTy); } -/// Are the two types matrix types and do they have the same dimensions i.e. -/// do they have the same number of rows and the same number of columns? bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) { if (!destTy->isMatrixType() || !srcTy->isMatrixType()) return false; @@ -7602,7 +7442,6 @@ bool Sema::areVectorTypesSameSize(QualType SrcTy, QualType DestTy) { return (SrcLen * SrcEltSize == DestLen * DestEltSize); } -// This returns true if at least one of the types is an altivec vector. bool Sema::anyAltivecTypes(QualType SrcTy, QualType DestTy) { assert((DestTy->isVectorType() || SrcTy->isVectorType()) && "expected at least one type to be a vector here"); @@ -7626,13 +7465,6 @@ bool Sema::anyAltivecTypes(QualType SrcTy, QualType DestTy) { return (IsSrcTyAltivec || IsDestTyAltivec); } -/// Are the two types lax-compatible vector types? That is, given -/// that one of them is a vector, do they have equal storage sizes, -/// where the storage size is the number of elements times the element -/// size? -/// -/// This will also return false if either of the types is neither a -/// vector nor a real type. bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { assert(destTy->isVectorType() || srcTy->isVectorType()); @@ -7647,8 +7479,6 @@ bool Sema::areLaxCompatibleVectorTypes(QualType srcTy, QualType destTy) { return areVectorTypesSameSize(srcTy, destTy); } -/// Is this a legal conversion between two types, one of which is -/// known to be a vector type? bool Sema::isLaxVectorConversion(QualType srcTy, QualType destTy) { assert(destTy->isVectorType() || srcTy->isVectorType()); @@ -7941,8 +7771,6 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, return BuildCompoundLiteralExpr(LParenLoc, TInfo, RParenLoc, initE); } -/// This is not an AltiVec-style cast or or C++ direct-initialization, so turn -/// the ParenListExpr into a sequence of comma binary operators. ExprResult Sema::MaybeConvertParenListExprToParenExpr(Scope *S, Expr *OrigExpr) { ParenListExpr *E = dyn_cast<ParenListExpr>(OrigExpr); @@ -7966,9 +7794,6 @@ ExprResult Sema::ActOnParenListExpr(SourceLocation L, return ParenListExpr::Create(Context, L, Val, R); } -/// Emit a specialized diagnostic when one expression is a null pointer -/// constant and the other is not a pointer. Returns true if a diagnostic is -/// emitted. bool Sema::DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation QuestionLoc) { const Expr *NullExpr = LHSExpr; @@ -8831,8 +8656,6 @@ static QualType computeConditionalNullability(QualType ResTy, bool IsBin, return Ctx.getAttributedType(NewAttr, ResTy, ResTy); } -/// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null -/// in the case of a the GNU conditional expr extension. ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, @@ -8936,7 +8759,6 @@ ExprResult Sema::ActOnConditionalOp(SourceLocation QuestionLoc, ColonLoc, result, VK, OK); } -// Check that the SME attributes for PSTATE.ZA and PSTATE.SM are compatible. bool Sema::IsInvalidSMECallConversion(QualType FromType, QualType ToType) { unsigned FromAttributes = 0, ToAttributes = 0; if (const auto *FromFn = @@ -9915,9 +9737,6 @@ QualType Sema::InvalidOperands(SourceLocation Loc, ExprResult &LHS, return QualType(); } -// Diagnose cases where a scalar was implicitly converted to a vector and -// diagnose the underlying types. Otherwise, diagnose the error -// as invalid vector logical operands for non-C++ cases. QualType Sema::InvalidLogicalVectorOperands(SourceLocation Loc, ExprResult &LHS, ExprResult &RHS) { QualType LHSType = LHS.get()->IgnoreImpCasts()->getType(); @@ -12644,11 +12463,6 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS, return InvalidOperands(Loc, LHS, RHS); } -// Return a signed ext_vector_type that is of identical size and number of -// elements. For floating point vectors, return an integer type of identical -// size and number of elements. In the non ext_vector_type case, search from -// the largest type to the smallest type to avoid cases where long long == long, -// where long gets picked over long long. QualType Sema::GetSignedVectorType(QualType V) { const VectorType *VTy = V->castAs<VectorType>(); unsigned TypeSize = Context.getTypeSize(VTy->getElementType()); @@ -12704,10 +12518,6 @@ QualType Sema::GetSignedSizelessVectorType(QualType V) { return Context.getScalableVectorType(IntTy, VecSize.getKnownMinValue()); } -/// CheckVectorCompareOperands - vector comparisons are a clang extension that -/// operates on extended vector types. Instead of producing an IntTy result, -/// like a scalar comparison, a vector comparison produces a vector of integer -/// types. QualType Sema::CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc) { @@ -13826,9 +13636,6 @@ static bool IgnoreCommaOperand(const Expr *E, const ASTContext &Context) { return false; } -// Look for instances where it is likely the comma operator is confused with -// another operator. There is an explicit list of acceptable expressions for -// the left hand side of the comma operator, otherwise emit a warning. void Sema::DiagnoseCommaOperator(const Expr *LHS, SourceLocation Loc) { // No warnings in macros if (Loc.isMacroID()) @@ -14108,13 +13915,6 @@ bool Sema::CheckUseOfCXXMethodAsAddressOfOperand(SourceLocation OpLoc, << FixItHint::CreateInsertion(DRE->getSourceRange().getBegin(), Qual); } -/// CheckAddressOfOperand - The operand of & must be either a function -/// designator or an lvalue designating an object. If it is an lvalue, the -/// object cannot be declared with storage class register or be a bit field. -/// Note: The usual conversions are *not* applied to the operand of the & -/// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue. -/// In C++, the operand might be an overloaded function name, in which case -/// we allow the '&' but retain the overloaded-function type. QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { if (const BuiltinType *PTy = OrigOp.get()->getType()->getAsPlaceholderType()){ if (PTy->getKind() == BuiltinType::Overload) { @@ -14733,9 +14533,6 @@ static bool needsConversionOfHalfVec(bool OpRequiresConversion, ASTContext &Ctx, return HasVectorOfHalfType(E0) && (!E1 || HasVectorOfHalfType(E1)); } -/// CreateBuiltinBinOp - Creates a new built-in binary operation with -/// operator @p Opc at location @c TokLoc. This routine only supports -/// built-in operations; ActOnBinOp handles overloaded operators. ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr) { @@ -15208,7 +15005,6 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr); } -// Binary Operators. 'Tok' is the token for the operator. ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr) { @@ -15667,9 +15463,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, return UO; } -/// Determine whether the given expression is a qualified member -/// access expression, of a form that could be turned into a pointer to member -/// with the address-of operator. bool Sema::isQualifiedMemberAccess(Expr *E) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { if (!DRE->getQualifier()) @@ -15751,14 +15544,12 @@ ExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, return CreateBuiltinUnaryOp(OpLoc, Opc, Input, IsAfterAmp); } -// Unary Operators. 'Tok' is the token for the operator. ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input, bool IsAfterAmp) { return BuildUnaryOp(S, OpLoc, ConvertTokenKindToUnaryOpcode(Op), Input, IsAfterAmp); } -/// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, LabelDecl *TheDecl) { TheDecl->markUsed(Context); @@ -16085,7 +15876,6 @@ ExprResult Sema::ActOnChooseExpr(SourceLocation BuiltinLoc, // Clang Extensions. //===----------------------------------------------------------------------===// -/// ActOnBlockStart - This callback is invoked when a block literal is started. void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) { BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); @@ -16234,8 +16024,6 @@ void Sema::ActOnBlockArguments(SourceLocation CaretLoc, Declarator &ParamInfo, } } -/// ActOnBlockError - If there is an error parsing a block, this callback -/// is invoked to pop the information about the block from the action impl. void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { // Leave the expression-evaluation context. DiscardCleanupsInEvaluationContext(); @@ -16246,8 +16034,6 @@ void Sema::ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) { PopFunctionScopeInfo(); } -/// ActOnBlockStmtExpr - This is called when the body of a block statement -/// literal was successfully completed. ^(int x){...} ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Stmt *Body, Scope *CurScope) { // If blocks are disabled, emit an error. @@ -17382,10 +17168,6 @@ void Sema::WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec) { Rec.PossibleDerefs.clear(); } -/// Check whether E, which is either a discarded-value expression or an -/// unevaluated operand, is a simple-assignment to a volatlie-qualified lvalue, -/// and if so, remove it from the list of volatile-qualified assignments that -/// we are going to warn are deprecated. void Sema::CheckUnusedVolatileAssignment(Expr *E) { if (!E->getType().isVolatileQualified() || !getLangOpts().CPlusPlus20) return; @@ -17985,8 +17767,6 @@ static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) { return CCD && CCD->getInheritedConstructor(); } -/// Mark a function referenced, and check whether it is odr-used -/// (C++ [basic.def.odr]p2, C99 6.9p3) void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse) { assert(Func && "No function?"); @@ -19788,9 +19568,6 @@ static void DoMarkBindingDeclReferenced(Sema &SemaRef, SourceLocation Loc, } } -/// Mark a variable referenced, and check whether it is odr-used -/// (C++ [basic.def.odr]p2, C99 6.9p3). Note that this should not be -/// used directly for normal expressions referring to VarDecl. void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) { DoMarkVarDeclReferenced(*this, Loc, Var, nullptr, RefsMinusAssignments); } @@ -19891,10 +19668,6 @@ MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E, SemaRef.MarkAnyDeclReferenced(Loc, DM, MightBeOdrUse); } -/// Perform reference-marking and odr-use handling for a DeclRefExpr. -/// -/// Note, this may change the dependence of the DeclRefExpr, and so needs to be -/// handled with care if the DeclRefExpr is not newly-created. void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { // TODO: update this with DR# once a defect report is filed. // C++11 defect. The address of a pure member should not be an ODR use, even @@ -19917,7 +19690,6 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) { RefsMinusAssignments); } -/// Perform reference-marking and odr-use handling for a MemberExpr. void Sema::MarkMemberReferenced(MemberExpr *E) { // C++11 [basic.def.odr]p2: // A non-overloaded function whose name appears as a potentially-evaluated @@ -19937,7 +19709,6 @@ void Sema::MarkMemberReferenced(MemberExpr *E) { RefsMinusAssignments); } -/// Perform reference-marking and odr-use handling for a FunctionParmPackExpr. void Sema::MarkFunctionParmPackReferenced(FunctionParmPackExpr *E) { for (VarDecl *VD : *E) MarkExprReferenced(*this, E->getParameterPackLocation(), VD, E, true, @@ -20055,12 +19826,6 @@ public: }; } // namespace -/// Mark any declarations that appear within this expression or any -/// potentially-evaluated subexpressions as "referenced". -/// -/// \param SkipLocalVariables If true, don't mark local variables as -/// 'referenced'. -/// \param StopAt Subexpressions that we shouldn't recurse into. void Sema::MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables, ArrayRef<const Expr*> StopAt) { @@ -20247,8 +20012,6 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { << FixItHint::CreateReplacement(Loc, "=="); } -/// Redundant parentheses over an equality comparison can indicate -/// that the user intended an assignment used as condition. void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) { // Don't warn if the parens came from a macro. SourceLocation parenLoc = ParenE->getBeginLoc(); @@ -20770,8 +20533,6 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { return E; } -/// Check a cast of an unknown-any type. We intentionally only -/// trigger this for C-style casts. ExprResult Sema::checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, Expr *CastExpr, CastKind &CastKind, ExprValueKind &VK, CXXCastPath &Path) { @@ -20862,8 +20623,6 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) { return ExprError(); } -/// Check for operands with placeholder types and complain if found. -/// Returns ExprError() if there was an error and no recovery was possible. ExprResult Sema::CheckPlaceholderExpr(Expr *E) { if (!Context.isDependenceAllowed()) { // C cannot handle TypoExpr nodes on either side of a binop because it diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f3af8de..69074f9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -55,10 +55,6 @@ using namespace clang; using namespace sema; -/// Handle the result of the special case name lookup for inheriting -/// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as -/// constructor names in member using declarations, even if 'X' is not the -/// name of the corresponding type. ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, SourceLocation NameLoc, const IdentifierInfo &Name) { @@ -544,7 +540,6 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, llvm_unreachable("unknown nested name specifier kind"); } -/// Build a C++ typeid expression with a type operand. ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, TypeSourceInfo *Operand, @@ -572,7 +567,6 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceRange(TypeidLoc, RParenLoc)); } -/// Build a C++ typeid expression with an expression operand. ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation TypeidLoc, Expr *E, @@ -747,7 +741,6 @@ getUuidAttrOfType(Sema &SemaRef, QualType QT, } } -/// Build a Microsoft __uuidof expression with a type operand. ExprResult Sema::BuildCXXUuidof(QualType Type, SourceLocation TypeidLoc, TypeSourceInfo *Operand, @@ -767,7 +760,6 @@ ExprResult Sema::BuildCXXUuidof(QualType Type, CXXUuidofExpr(Type, Operand, Guid, SourceRange(TypeidLoc, RParenLoc)); } -/// Build a Microsoft __uuidof expression with an expression operand. ExprResult Sema::BuildCXXUuidof(QualType Type, SourceLocation TypeidLoc, Expr *E, SourceLocation RParenLoc) { MSGuidDecl *Guid = nullptr; @@ -815,7 +807,6 @@ Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc, return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc); } -/// ActOnCXXBoolLiteral - Parse {true,false} literals. ExprResult Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { assert((Kind == tok::kw_true || Kind == tok::kw_false) && @@ -824,13 +815,11 @@ Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { CXXBoolLiteralExpr(Kind == tok::kw_true, Context.BoolTy, OpLoc); } -/// ActOnCXXNullPtrLiteral - Parse 'nullptr'. ExprResult Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { return new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc); } -/// ActOnCXXThrow - Parse throw expressions. ExprResult Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) { bool IsThrownVarInScope = false; @@ -987,7 +976,6 @@ static void getUnambiguousPublicSubobjects( } } -/// CheckCXXThrowOperand - Validate the operand of a throw. bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, QualType ExceptionObjectTy, Expr *E) { // If the type of the exception would be an incomplete type or a pointer @@ -1515,10 +1503,6 @@ bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) { return Class && Class->isBeingDefined(); } -/// Parse construction of a specified type. -/// Can be interpreted either as function-style casting ("int(x)") -/// or class type construction ("ClassType(x,y,z)") -/// or creation of a value-initialized type ("int()"). ExprResult Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, SourceLocation LParenOrBraceLoc, @@ -1920,22 +1904,6 @@ static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, return Best && Best.HasSizeT; } -/// Parsed a C++ 'new' expression (C++ 5.3.4). -/// -/// E.g.: -/// @code new (memory) int[size][4] @endcode -/// or -/// @code ::new Foo(23, "hello") @endcode -/// -/// \param StartLoc The first location of the expression. -/// \param UseGlobal True if 'new' was prefixed with '::'. -/// \param PlacementLParen Opening paren of the placement arguments. -/// \param PlacementArgs Placement new arguments. -/// \param PlacementRParen Closing paren of the placement arguments. -/// \param TypeIdParens If the type is in parens, the source range. -/// \param D The type to be allocated, as well as array dimensions. -/// \param Initializer The initializing expression or initializer-list, or null -/// if there is none. ExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, @@ -2545,8 +2513,6 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, DirectInitRange); } -/// Checks that a type is suitable as the allocated type -/// in a new-expression. bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R) { // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an @@ -3040,29 +3006,6 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, return false; } -/// DeclareGlobalNewDelete - Declare the global forms of operator new and -/// delete. These are: -/// @code -/// // C++03: -/// void* operator new(std::size_t) throw(std::bad_alloc); -/// void* operator new[](std::size_t) throw(std::bad_alloc); -/// void operator delete(void *) throw(); -/// void operator delete[](void *) throw(); -/// // C++11: -/// void* operator new(std::size_t); -/// void* operator new[](std::size_t); -/// void operator delete(void *) noexcept; -/// void operator delete[](void *) noexcept; -/// // C++1y: -/// void* operator new(std::size_t); -/// void* operator new[](std::size_t); -/// void operator delete(void *) noexcept; -/// void operator delete[](void *) noexcept; -/// void operator delete(void *, std::size_t) noexcept; -/// void operator delete[](void *, std::size_t) noexcept; -/// @endcode -/// Note that the placement and nothrow forms of new are *not* implicitly -/// declared. Their use requires including \<new\>. void Sema::DeclareGlobalNewDelete() { if (GlobalNewDeleteDeclared) return; @@ -3676,10 +3619,6 @@ void Sema::AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, } } -/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: -/// @code ::delete ptr; @endcode -/// or -/// @code delete [] ptr; @endcode ExprResult Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, bool ArrayForm, Expr *ExE) { @@ -4085,8 +4024,6 @@ Sema::ConditionResult Sema::ActOnConditionVariable(Decl *ConditionVar, CK == ConditionKind::ConstexprIf); } -/// Check the use of the given variable as a C++ condition in an if, -/// while, do-while, or switch statement. ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, SourceLocation StmtLoc, ConditionKind CK) { @@ -4124,7 +4061,6 @@ ExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar, llvm_unreachable("unexpected condition kind"); } -/// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid. ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) { // C++11 6.4p4: // The value of a condition that is an initialized declaration in a statement @@ -4152,10 +4088,6 @@ ExprResult Sema::CheckCXXBooleanCondition(Expr *CondExpr, bool IsConstexpr) { return E; } -/// Helper function to determine whether this is the (deprecated) C++ -/// conversion from a string literal to a pointer to non-const char or -/// non-const wchar_t (for narrow and wide string literals, -/// respectively). bool Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { // Look inside the implicit cast, if it exists. @@ -4257,11 +4189,6 @@ static ExprResult BuildCXXCastArgument(Sema &S, } } -/// PerformImplicitConversion - Perform an implicit conversion of the -/// expression From to the type ToType using the pre-computed implicit -/// conversion sequence ICS. Returns the converted -/// expression. Action is the kind of conversion we're performing, -/// used in the error message. ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, @@ -4361,11 +4288,6 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return From; } -/// PerformImplicitConversion - Perform an implicit conversion of the -/// expression From to the type ToType by following the standard -/// conversion sequence SCS. Returns the converted -/// expression. Flavor is the context in which we're performing this -/// conversion, for use in error messages. ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, const StandardConversionSequence& SCS, @@ -6815,26 +6737,6 @@ QualType Sema::CheckSizelessVectorConditionalTypes(ExprResult &Cond, return ResultType; } -/// Check the operands of ?: under C++ semantics. -/// -/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y -/// extension. In this case, LHS == Cond. (But they're not aliases.) -/// -/// This function also implements GCC's vector extension and the -/// OpenCL/ext_vector_type extension for conditionals. The vector extensions -/// permit the use of a?b:c where the type of a is that of a integer vector with -/// the same number of elements and size as the vectors of b and c. If one of -/// either b or c is a scalar it is implicitly converted to match the type of -/// the vector. Otherwise the expression is ill-formed. If both b and c are -/// scalars, then b and c are checked and converted to the type of a if -/// possible. -/// -/// The expressions are evaluated differently for GCC's and OpenCL's extensions. -/// For the GCC extension, the ?: operator is evaluated as -/// (a[0] != 0 ? b[0] : c[0], .. , a[n] != 0 ? b[n] : c[n]). -/// For the OpenCL extensions, the ?: operator is evaluated as -/// (most-significant-bit-set(a[0]) ? b[0] : c[0], .. , -/// most-significant-bit-set(a[n]) ? b[n] : c[n]). QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS, ExprValueKind &VK, ExprObjectKind &OK, @@ -7135,17 +7037,6 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, return QualType(); } -/// Find a merged pointer type and convert the two expressions to it. -/// -/// This finds the composite pointer type for \p E1 and \p E2 according to -/// C++2a [expr.type]p3. It converts both expressions to this type and returns -/// it. It does not emit diagnostics (FIXME: that's not true if \p ConvertArgs -/// is \c true). -/// -/// \param Loc The location of the operator requiring these two expressions to -/// be converted to the composite pointer type. -/// -/// \param ConvertArgs If \c false, do not convert E1 and E2 to the target type. QualType Sema::FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool ConvertArgs) { @@ -7732,10 +7623,6 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { return MaybeCreateExprWithCleanups(E); } -/// Process the expression contained within a decltype. For such expressions, -/// certain semantic checks on temporaries are delayed until this point, and -/// are omitted for the 'topmost' call in the decltype expression. If the -/// topmost call bound a temporary, strip that temporary off the expression. ExprResult Sema::ActOnDecltypeExpression(Expr *E) { assert(ExprEvalContexts.back().ExprContext == ExpressionEvaluationContextRecord::EK_Decltype && diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 3ae1af2..b7ea247 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -302,7 +302,6 @@ bool Sema::isPotentialImplicitMemberAccess(const CXXScopeSpec &SS, return isa<FieldDecl, IndirectFieldDecl, MSPropertyDecl>(R.getFoundDecl()); } -/// Builds an expression which might be an implicit member expression. ExprResult Sema::BuildPossibleImplicitMemberExpr( const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, const TemplateArgumentListInfo *TemplateArgs, const Scope *S) { @@ -613,18 +612,6 @@ static void DiagnoseQualifiedMemberReference(Sema &SemaRef, << SS.getRange() << rep << BaseType; } -// Check whether the declarations we found through a nested-name -// specifier in a member expression are actually members of the base -// type. The restriction here is: -// -// C++ [expr.ref]p2: -// ... In these cases, the id-expression shall name a -// member of the class or of one of its base classes. -// -// So it's perfectly legitimate for the nested-name specifier to name -// an unrelated class, and for us to find an overload set including -// decls from classes which are not superclasses, as long as the decl -// we actually pick through overload resolution is from a superclass. bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, const CXXScopeSpec &SS, @@ -1276,7 +1263,6 @@ static bool isPointerToRecordType(QualType T) { return false; } -/// Perform conversions on the LHS of a member access expression. ExprResult Sema::PerformMemberExprBaseConversion(Expr *Base, bool IsArrow) { if (IsArrow && !Base->getType()->isFunctionType()) @@ -1757,16 +1743,6 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, return ExprError(); } -/// The main callback when the parser finds something like -/// expression . [nested-name-specifier] identifier -/// expression -> [nested-name-specifier] identifier -/// where 'identifier' encompasses a fairly broad spectrum of -/// possibilities, including destructor and operator references. -/// -/// \param OpKind either tok::arrow or tok::period -/// \param ObjCImpDecl the current Objective-C \@implementation -/// decl; this is an ugly hack around the fact that Objective-C -/// \@implementations aren't properly put in the context chain ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, @@ -1928,10 +1904,6 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow, /*HadMultipleCandidates=*/false, MemberNameInfo, MemberType, VK, OK); } -/// Builds an implicit member access expression. The current context -/// is known to be an instance method, and the given unqualified lookup -/// set is known to contain only instance members, at least one of which -/// is from an appropriate type. ExprResult Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 26c65b3..64e43de 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3429,8 +3429,6 @@ void InitListChecker::UpdateStructuredListElement(InitListExpr *StructuredList, ++StructuredIndex; } -/// Determine whether we can perform aggregate initialization for the purposes -/// of overload resolution. bool Sema::CanPerformAggregateInitializationForOverloadResolution( const InitializedEntity &Entity, InitListExpr *From) { QualType Type = Entity.getType(); diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 9a3fabc..a4acf3b 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -914,8 +914,6 @@ static void InsertOCLBuiltinDeclarationsFromTable(Sema &S, LookupResult &LR, LR.resolveKind(); } -/// Lookup a builtin function, when name lookup would otherwise -/// fail. bool Sema::LookupBuiltin(LookupResult &R) { Sema::LookupNameKind NameKind = R.getLookupKind(); @@ -1594,7 +1592,6 @@ llvm::DenseSet<Module*> &Sema::getLookupModules() { return LookupModulesCache; } -/// Determine if we could use all the declarations in the module. bool Sema::isUsableModule(const Module *M) { assert(M && "We shouldn't check nullness for module here"); // Return quickly if we cached the result. @@ -2175,34 +2172,6 @@ bool LookupResult::isAvailableForLookup(Sema &SemaRef, NamedDecl *ND) { return false; } -/// Perform unqualified name lookup starting from a given -/// scope. -/// -/// Unqualified name lookup (C++ [basic.lookup.unqual], C99 6.2.1) is -/// used to find names within the current scope. For example, 'x' in -/// @code -/// int x; -/// int f() { -/// return x; // unqualified name look finds 'x' in the global scope -/// } -/// @endcode -/// -/// Different lookup criteria can find different names. For example, a -/// particular scope can have both a struct and a function of the same -/// name, and each can be found by certain lookup criteria. For more -/// information about lookup criteria, see the documentation for the -/// class LookupCriteria. -/// -/// @param S The scope from which unqualified name lookup will -/// begin. If the lookup criteria permits, name lookup may also search -/// in the parent scopes. -/// -/// @param [in,out] R Specifies the lookup to perform (e.g., the name to -/// look up and the lookup kind), and is updated with the results of lookup -/// including zero or more declarations and possibly additional information -/// used to diagnose ambiguities. -/// -/// @returns \c true if lookup succeeded and false otherwise. bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation, bool ForceNoCPlusPlus) { DeclarationName Name = R.getLookupName(); @@ -2420,28 +2389,6 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, return Found; } -/// Perform qualified name lookup into a given context. -/// -/// Qualified name lookup (C++ [basic.lookup.qual]) is used to find -/// names when the context of those names is explicit specified, e.g., -/// "std::vector" or "x->member", or as part of unqualified name lookup. -/// -/// Different lookup criteria can find different names. For example, a -/// particular scope can have both a struct and a function of the same -/// name, and each can be found by certain lookup criteria. For more -/// information about lookup criteria, see the documentation for the -/// class LookupCriteria. -/// -/// \param R captures both the lookup criteria and any lookup results found. -/// -/// \param LookupCtx The context in which qualified name lookup will -/// search. If the lookup criteria permits, name lookup may also search -/// in the parent contexts or (for C++ classes) base classes. -/// -/// \param InUnqualifiedLookup true if this is qualified name lookup that -/// occurs as part of unqualified name lookup. -/// -/// \returns true if lookup succeeded, false if it failed. bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup) { assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context"); @@ -2716,21 +2663,6 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, return true; } -/// Performs qualified name lookup or special type of lookup for -/// "__super::" scope specifier. -/// -/// This routine is a convenience overload meant to be called from contexts -/// that need to perform a qualified name lookup with an optional C++ scope -/// specifier that might require special kind of lookup. -/// -/// \param R captures both the lookup criteria and any lookup results found. -/// -/// \param LookupCtx The context in which qualified name lookup will -/// search. -/// -/// \param SS An optional C++ scope-specifier. -/// -/// \returns true if lookup succeeded, false if it failed. bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, CXXScopeSpec &SS) { auto *NNS = SS.getScopeRep(); @@ -2741,25 +2673,6 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, return LookupQualifiedName(R, LookupCtx); } -/// Performs name lookup for a name that was parsed in the -/// source code, and may contain a C++ scope specifier. -/// -/// This routine is a convenience routine meant to be called from -/// contexts that receive a name and an optional C++ scope specifier -/// (e.g., "N::M::x"). It will then perform either qualified or -/// unqualified name lookup (with LookupQualifiedName or LookupName, -/// respectively) on the given name and return those results. It will -/// perform a special type of lookup for "__super::" scope specifier. -/// -/// @param S The scope from which unqualified name lookup will -/// begin. -/// -/// @param SS An optional C++ scope-specifier, e.g., "::N::M". -/// -/// @param EnteringContext Indicates whether we are going to enter the -/// context of the scope-specifier SS (if present). -/// -/// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation, bool EnteringContext) { @@ -2814,15 +2727,6 @@ bool Sema::LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, return false; } -/// Perform qualified name lookup into all base classes of the given -/// class. -/// -/// \param R captures both the lookup criteria and any lookup results found. -/// -/// \param Class The context in which qualified name lookup will -/// search. Name lookup will search in all base classes merging the results. -/// -/// @returns True if any decls were found (but possibly ambiguous) bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) { // The access-control rules we use here are essentially the rules for // doing a lookup in Class that just magically skipped the direct @@ -2852,10 +2756,6 @@ bool Sema::LookupInSuper(LookupResult &R, CXXRecordDecl *Class) { return !R.empty(); } -/// Produce a diagnostic describing the ambiguity that resulted -/// from name lookup. -/// -/// \param Result The result of the ambiguous lookup to be diagnosed. void Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { assert(Result.isAmbiguous() && "Lookup result must be ambiguous"); @@ -3318,13 +3218,6 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { } } -/// Find the associated classes and namespaces for -/// argument-dependent lookup for a call with the given set of -/// arguments. -/// -/// This routine computes the sets of associated classes and associated -/// namespaces searched by argument-dependent lookup -/// (C++ [basic.lookup.argdep]) for a given set of arguments. void Sema::FindAssociatedClassesAndNamespaces( SourceLocation InstantiationLoc, ArrayRef<Expr *> Args, AssociatedNamespaceSet &AssociatedNamespaces, @@ -3617,7 +3510,6 @@ Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMemberKind SM, return *Result; } -/// Look up the default constructor for the given class. CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { SpecialMemberOverloadResult Result = LookupSpecialMember(Class, CXXSpecialMemberKind::DefaultConstructor, @@ -3626,7 +3518,6 @@ CXXConstructorDecl *Sema::LookupDefaultConstructor(CXXRecordDecl *Class) { return cast_or_null<CXXConstructorDecl>(Result.getMethod()); } -/// Look up the copying constructor for the given class. CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, unsigned Quals) { assert(!(Quals & ~(Qualifiers::Const | Qualifiers::Volatile)) && @@ -3638,7 +3529,6 @@ CXXConstructorDecl *Sema::LookupCopyingConstructor(CXXRecordDecl *Class, return cast_or_null<CXXConstructorDecl>(Result.getMethod()); } -/// Look up the moving constructor for the given class. CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class, unsigned Quals) { SpecialMemberOverloadResult Result = LookupSpecialMember( @@ -3648,7 +3538,6 @@ CXXConstructorDecl *Sema::LookupMovingConstructor(CXXRecordDecl *Class, return cast_or_null<CXXConstructorDecl>(Result.getMethod()); } -/// Look up the constructors for the given class. DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { // If the implicit constructors have not yet been declared, do so now. if (CanDeclareSpecialMemberFunction(Class)) { @@ -3667,7 +3556,6 @@ DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { return Class->lookup(Name); } -/// Look up the copying assignment operator for the given class. CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class, unsigned Quals, bool RValueThis, unsigned ThisQuals) { @@ -3683,7 +3571,6 @@ CXXMethodDecl *Sema::LookupCopyingAssignment(CXXRecordDecl *Class, return Result.getMethod(); } -/// Look up the moving assignment operator for the given class. CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, unsigned Quals, bool RValueThis, @@ -3698,12 +3585,6 @@ CXXMethodDecl *Sema::LookupMovingAssignment(CXXRecordDecl *Class, return Result.getMethod(); } -/// Look for the destructor of the given class. -/// -/// During semantic analysis, this routine should be used in lieu of -/// CXXRecordDecl::getDestructor(). -/// -/// \returns The destructor for this class. CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { return cast_or_null<CXXDestructorDecl>( LookupSpecialMember(Class, CXXSpecialMemberKind::Destructor, false, false, @@ -3711,12 +3592,6 @@ CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { .getMethod()); } -/// LookupLiteralOperator - Determine which literal operator should be used for -/// a user-defined literal, per C++11 [lex.ext]. -/// -/// Normal overload resolution is not used to select which literal operator to -/// call for a user-defined literal. Look up the provided literal operator name, -/// and filter the results to the appropriate set for the given argument types. Sema::LiteralOperatorLookupResult Sema::LookupLiteralOperator(Scope *S, LookupResult &R, ArrayRef<QualType> ArgTys, bool AllowRaw, @@ -4484,10 +4359,6 @@ void Sema::LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, H.lookupVisibleDecls(*this, Ctx, Kind, IncludeGlobalScope); } -/// LookupOrCreateLabel - Do a name lookup of a label with the specified name. -/// If GnuLabelLoc is a valid source location, then this is a definition -/// of an __label__ label name, otherwise it is a normal label definition -/// or use. LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, SourceLocation GnuLabelLoc) { // Do a lookup to see if we have a label with this name already. @@ -5384,37 +5255,6 @@ std::unique_ptr<TypoCorrectionConsumer> Sema::makeTypoCorrectionConsumer( return Consumer; } -/// Try to "correct" a typo in the source code by finding -/// visible declarations whose names are similar to the name that was -/// present in the source code. -/// -/// \param TypoName the \c DeclarationNameInfo structure that contains -/// the name that was present in the source code along with its location. -/// -/// \param LookupKind the name-lookup criteria used to search for the name. -/// -/// \param S the scope in which name lookup occurs. -/// -/// \param SS the nested-name-specifier that precedes the name we're -/// looking for, if present. -/// -/// \param CCC A CorrectionCandidateCallback object that provides further -/// validation of typo correction candidates. It also provides flags for -/// determining the set of keywords permitted. -/// -/// \param MemberContext if non-NULL, the context in which to look for -/// a member access expression. -/// -/// \param EnteringContext whether we're entering the context described by -/// the nested-name-specifier SS. -/// -/// \param OPT when non-NULL, the search for visible declarations will -/// also walk the protocols in the qualified interfaces of \p OPT. -/// -/// \returns a \c TypoCorrection containing the corrected name if the typo -/// along with information such as the \c NamedDecl where the corrected name -/// was declared, and any additional \c NestedNameSpecifier needed to access -/// it (C++ only). The \c TypoCorrection is empty if there is no correction. TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, @@ -5512,44 +5352,6 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName, return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure && !SecondBestTC); } -/// Try to "correct" a typo in the source code by finding -/// visible declarations whose names are similar to the name that was -/// present in the source code. -/// -/// \param TypoName the \c DeclarationNameInfo structure that contains -/// the name that was present in the source code along with its location. -/// -/// \param LookupKind the name-lookup criteria used to search for the name. -/// -/// \param S the scope in which name lookup occurs. -/// -/// \param SS the nested-name-specifier that precedes the name we're -/// looking for, if present. -/// -/// \param CCC A CorrectionCandidateCallback object that provides further -/// validation of typo correction candidates. It also provides flags for -/// determining the set of keywords permitted. -/// -/// \param TDG A TypoDiagnosticGenerator functor that will be used to print -/// diagnostics when the actual typo correction is attempted. -/// -/// \param TRC A TypoRecoveryCallback functor that will be used to build an -/// Expr from a typo correction candidate. -/// -/// \param MemberContext if non-NULL, the context in which to look for -/// a member access expression. -/// -/// \param EnteringContext whether we're entering the context described by -/// the nested-name-specifier SS. -/// -/// \param OPT when non-NULL, the search for visible declarations will -/// also walk the protocols in the qualified interfaces of \p OPT. -/// -/// \returns a new \c TypoExpr that will later be replaced in the AST with an -/// Expr representing the result of performing typo correction, or nullptr if -/// typo correction is not possible. If nullptr is returned, no diagnostics will -/// be emitted and it is the responsibility of the caller to emit any that are -/// needed. TypoExpr *Sema::CorrectTypoDelayed( const DeclarationNameInfo &TypoName, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, @@ -5865,18 +5667,6 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, const NamedDecl *Decl, createImplicitModuleImportForErrorRecovery(UseLoc, Modules[0]); } -/// Diagnose a successfully-corrected typo. Separated from the correction -/// itself to allow external validation of the result, etc. -/// -/// \param Correction The result of performing typo correction. -/// \param TypoDiag The diagnostic to produce. This will have the corrected -/// string added to it (and usually also a fixit). -/// \param PrevNote A note to use when indicating the location of the entity to -/// which we are correcting. Will have the correction string added to it. -/// \param ErrorRecovery If \c true (the default), the caller is going to -/// recover from the typo as if the corrected string had been typed. -/// In this case, \c PDiag must be an error, and we will attach a fixit -/// to it. void Sema::diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, const PartialDiagnostic &PrevNote, diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 98e7971..9655a39 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -841,8 +841,6 @@ void Sema::createImplicitModuleImportForErrorRecovery(SourceLocation Loc, VisibleModules.setVisible(Mod, Loc); } -/// We have parsed the start of an export declaration, including the '{' -/// (if present). Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation ExportLoc, SourceLocation LBraceLoc) { ExportDecl *D = ExportDecl::Create(Context, CurContext, ExportLoc); @@ -978,7 +976,6 @@ static bool checkExportedDecl(Sema &S, Decl *D, SourceLocation BlockStart) { return true; } -/// Complete the definition of an export declaration. Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, SourceLocation RBraceLoc) { auto *ED = cast<ExportDecl>(D); if (RBraceLoc.isValid()) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f8f55ce..982cca6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1146,39 +1146,6 @@ static bool checkArgPlaceholdersForOverload(Sema &S, MultiExprArg Args, return false; } -/// Determine whether the given New declaration is an overload of the -/// declarations in Old. This routine returns Ovl_Match or Ovl_NonFunction if -/// New and Old cannot be overloaded, e.g., if New has the same signature as -/// some function in Old (C++ 1.3.10) or if the Old declarations aren't -/// functions (or function templates) at all. When it does return Ovl_Match or -/// Ovl_NonFunction, MatchedDecl will point to the decl that New cannot be -/// overloaded with. This decl may be a UsingShadowDecl on top of the underlying -/// declaration. -/// -/// Example: Given the following input: -/// -/// void f(int, float); // #1 -/// void f(int, int); // #2 -/// int f(int, int); // #3 -/// -/// When we process #1, there is no previous declaration of "f", so IsOverload -/// will not be used. -/// -/// When we process #2, Old contains only the FunctionDecl for #1. By comparing -/// the parameter types, we see that #1 and #2 are overloaded (since they have -/// different signatures), so this routine returns Ovl_Overload; MatchedDecl is -/// unchanged. -/// -/// When we process #3, Old is an overload set containing #1 and #2. We compare -/// the signatures of #3 to #1 (they're overloaded, so we do nothing) and then -/// #3 to #2. Since the signatures of #3 and #2 are identical (return types of -/// functions are not part of the signature), IsOverload returns Ovl_Match and -/// MatchedDecl will be set to point to the FunctionDecl for #2. -/// -/// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced into a class -/// by a using declaration. The rules for whether to hide shadow declarations -/// ignore some properties which otherwise figure into a function template's -/// signature. Sema::OverloadKind Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, NamedDecl *&Match, bool NewIsUsingDecl) { @@ -1764,11 +1731,6 @@ Sema::TryImplicitConversion(Expr *From, QualType ToType, /*AllowObjCConversionOnExplicit=*/false); } -/// PerformImplicitConversion - Perform an implicit conversion of the -/// expression From to the type ToType. Returns the -/// converted expression. Flavor is the kind of conversion we're -/// performing, used in the error message. If @p AllowExplicit, -/// explicit user-defined conversions are permitted. ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, AssignmentAction Action, bool AllowExplicit) { @@ -1792,9 +1754,6 @@ ExprResult Sema::PerformImplicitConversion(Expr *From, QualType ToType, return PerformImplicitConversion(From, ToType, ICS, Action); } -/// Determine whether the conversion from FromType to ToType is a valid -/// conversion that strips "noexcept" or "noreturn" off the nested function -/// type. bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, QualType &ResultTy) { if (Context.hasSameUnqualifiedType(FromType, ToType)) @@ -2453,10 +2412,6 @@ IsTransparentUnionStandardConversion(Sema &S, Expr* From, return false; } -/// IsIntegralPromotion - Determines whether the conversion from the -/// expression From (whose potentially-adjusted type is FromType) to -/// ToType is an integral promotion (C++ 4.5). If so, returns true and -/// sets PromotedType to the promoted type. bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { const BuiltinType *To = ToType->getAs<BuiltinType>(); // All integers are built-in. @@ -2622,9 +2577,6 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { return false; } -/// IsFloatingPointPromotion - Determines whether the conversion from -/// FromType to ToType is a floating point promotion (C++ 4.6). If so, -/// returns true and sets PromotedType to the promoted type. bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { if (const BuiltinType *FromBuiltin = FromType->getAs<BuiltinType>()) if (const BuiltinType *ToBuiltin = ToType->getAs<BuiltinType>()) { @@ -2662,11 +2614,6 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { return false; } -/// Determine if a conversion is a complex promotion. -/// -/// A complex promotion is defined as a complex -> complex conversion -/// where the conversion between the underlying real types is a -/// floating-point or integral promotion. bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) { const ComplexType *FromComplex = FromType->getAs<ComplexType>(); if (!FromComplex) @@ -2745,22 +2692,6 @@ static bool isNullPointerConstantForConversion(Expr *Expr, : Expr::NPC_ValueDependentIsNull); } -/// IsPointerConversion - Determines whether the conversion of the -/// expression From, which has the (possibly adjusted) type FromType, -/// can be converted to the type ToType via a pointer conversion (C++ -/// 4.10). If so, returns true and places the converted type (that -/// might differ from ToType in its cv-qualifiers at some level) into -/// ConvertedType. -/// -/// This routine also supports conversions to and from block pointers -/// and conversions with Objective-C's 'id', 'id<protocols...>', and -/// pointers to interfaces. FIXME: Once we've determined the -/// appropriate overloading rules for Objective-C, we may want to -/// split the Objective-C checks into a different routine; however, -/// GCC seems to consider all of these conversions to be pointer -/// conversions, so for now they live here. IncompatibleObjC will be -/// set if the conversion is an allowed Objective-C conversion that -/// should result in a warning. bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, bool InOverloadResolution, QualType& ConvertedType, @@ -2909,9 +2840,6 @@ static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ return Context.getQualifiedType(T.getUnqualifiedType(), Qs); } -/// isObjCPointerConversion - Determines whether this is an -/// Objective-C pointer conversion. Subroutine of IsPointerConversion, -/// with the same arguments and return values. bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, QualType& ConvertedType, bool &IncompatibleObjC) { @@ -3198,9 +3126,6 @@ static const FunctionProtoType *tryGetFunctionProtoType(QualType FromType) { return nullptr; } -/// HandleFunctionTypeMismatch - Gives diagnostic information for differeing -/// function types. Catches different number of parameter, mismatch in -/// parameter types, and different return types. void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, QualType FromType, QualType ToType) { // If either type is not valid, include no extra info. @@ -3296,13 +3221,6 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, PDiag << ft_default; } -/// FunctionParamTypesAreEqual - This routine checks two function proto types -/// for equality of their parameter types. Caller has already checked that -/// they have same number of parameters. If the parameters are different, -/// ArgPos will have the parameter index of the first different parameter. -/// If `Reversed` is true, the parameters of `NewType` will be compared in -/// reverse order. That's useful if one of the functions is being used as a C++20 -/// synthesized operator overload with a reversed parameter order. bool Sema::FunctionParamTypesAreEqual(ArrayRef<QualType> Old, ArrayRef<QualType> New, unsigned *ArgPos, bool Reversed) { @@ -3359,12 +3277,6 @@ bool Sema::FunctionNonObjectParamTypesAreEqual(const FunctionDecl *OldFunction, ArgPos, Reversed); } -/// CheckPointerConversion - Check the pointer conversion from the -/// expression From to the type ToType. This routine checks for -/// ambiguous or inaccessible derived-to-base pointer -/// conversions for which IsPointerConversion has already returned -/// true. It returns true and produces a diagnostic if there was an -/// error, or returns false otherwise. bool Sema::CheckPointerConversion(Expr *From, QualType ToType, CastKind &Kind, CXXCastPath& BasePath, @@ -3446,11 +3358,6 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, return false; } -/// IsMemberPointerConversion - Determines whether the conversion of the -/// expression From, which has the (possibly adjusted) type FromType, can be -/// converted to the type ToType via a member pointer conversion (C++ 4.11). -/// If so, returns true and places the converted type (that might differ from -/// ToType in its cv-qualifiers at some level) into ConvertedType. bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, QualType ToType, bool InOverloadResolution, @@ -3487,12 +3394,6 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, return false; } -/// CheckMemberPointerConversion - Check the member pointer conversion from the -/// expression From to the type ToType. This routine checks for ambiguous or -/// virtual or inaccessible base-to-derived member pointer conversions -/// for which IsMemberPointerConversion has already returned true. It returns -/// true and produces a diagnostic if there was an error, or returns false -/// otherwise. bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, CastKind &Kind, CXXCastPath &BasePath, @@ -3645,13 +3546,6 @@ static bool isQualificationConversionStep(QualType FromType, QualType ToType, return true; } -/// IsQualificationConversion - Determines whether the conversion from -/// an rvalue of type FromType to ToType is a qualification conversion -/// (C++ 4.4). -/// -/// \param ObjCLifetimeConversion Output parameter that will be set to indicate -/// when the qualification conversion involves a change in the Objective-C -/// object lifetime. bool Sema::IsQualificationConversion(QualType FromType, QualType ToType, bool CStyle, bool &ObjCLifetimeConversion) { @@ -4925,12 +4819,6 @@ static QualType withoutUnaligned(ASTContext &Ctx, QualType T) { return Ctx.getQualifiedType(T, Q); } -/// CompareReferenceRelationship - Compare the two types T1 and T2 to -/// determine whether they are reference-compatible, -/// reference-related, or incompatible, for use in C++ initialization by -/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference -/// type, and the first type (T1) is the pointee type of the reference -/// type being initialized. Sema::ReferenceCompareResult Sema::CompareReferenceRelationship(SourceLocation Loc, QualType OrigT1, QualType OrigT2, @@ -6045,8 +5933,6 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) { /*AllowObjCConversionOnExplicit=*/false); } -/// PerformContextuallyConvertToBool - Perform a contextual conversion -/// of the expression From to bool (C++0x [conv]p3). ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) { if (checkPlaceholderForOverload(*this, From)) return ExprError(); @@ -6320,9 +6206,6 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, return R; } -/// EvaluateConvertedConstantExpression - Evaluate an Expression -/// That is a converted constant expression -/// (which was built with BuildConvertedConstantExpression) ExprResult Sema::EvaluateConvertedConstantExpression(Expr *E, QualType T, APValue &Value, Sema::CCEKind CCE, bool RequireInt, @@ -6434,9 +6317,6 @@ TryContextuallyConvertToObjCPointer(Sema &S, Expr *From) { return ICS; } -/// PerformContextuallyConvertToObjCPointer - Perform a contextual -/// conversion of the expression From to an Objective-C pointer type. -/// Returns a valid but null ExprResult if no conversion sequence exists. ExprResult Sema::PerformContextuallyConvertToObjCPointer(Expr *From) { if (checkPlaceholderForOverload(*this, From)) return ExprError(); @@ -6917,14 +6797,6 @@ static bool isNonViableMultiVersionOverload(FunctionDecl *FD) { return HasDefault || SeenAt != 0; } -/// AddOverloadCandidate - Adds the given function to the set of -/// candidate functions, using the given function call arguments. If -/// @p SuppressUserConversions, then don't allow user-defined -/// conversions via constructors or conversion operators. -/// -/// \param PartialOverloading true if we are performing "partial" overloading -/// based on an incomplete set of function arguments. This feature is used by -/// code completion. void Sema::AddOverloadCandidate( FunctionDecl *Function, DeclAccessPair FoundDecl, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, @@ -7424,8 +7296,6 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, }); } -/// Add all of the function declarations in the given function set to -/// the overload candidate set. void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -7494,8 +7364,6 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, } } -/// AddMethodCandidate - Adds a named decl (which is some kind of -/// method) as a method candidate to the given overload set. void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, @@ -7522,13 +7390,6 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, } } -/// AddMethodCandidate - Adds the given C++ member function to the set -/// of candidate functions, using the given function call arguments -/// and the object argument (@c Object). For example, in a call -/// @c o.f(a1,a2), @c Object will contain @c o and @c Args will contain -/// both @c a1 and @c a2. If @p SuppressUserConversions, then don't -/// allow user-defined conversions via constructors or conversion -/// operators. void Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, @@ -7717,9 +7578,6 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, } } -/// Add a C++ member function template as a candidate to the candidate -/// set, using template argument deduction to produce an appropriate member -/// function template specialization. void Sema::AddMethodTemplateCandidate( FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -7793,9 +7651,6 @@ static bool isNonDependentlyExplicit(FunctionTemplateDecl *FTD) { return ExplicitSpecifier::getFromDecl(FTD->getTemplatedDecl()).isExplicit(); } -/// Add a C++ function template specialization as a candidate -/// in the candidate set, using template argument deduction to produce -/// an appropriate function template specialization. void Sema::AddTemplateOverloadCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, @@ -7877,9 +7732,6 @@ void Sema::AddTemplateOverloadCandidate( Info.AggregateDeductionCandidateHasMismatchedArity); } -/// Check that implicit conversion sequences can be formed for each argument -/// whose corresponding parameter has a non-dependent type, per DR1391's -/// [temp.deduct.call]p10. bool Sema::CheckNonDependentConversions( FunctionTemplateDecl *FunctionTemplate, ArrayRef<QualType> ParamTypes, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -7995,12 +7847,6 @@ static bool isAllowableExplicitConversion(Sema &S, IncompatibleObjC); } -/// AddConversionCandidate - Add a C++ conversion function as a -/// candidate in the candidate set (C++ [over.match.conv], -/// C++ [over.match.copy]). From is the expression we're converting from, -/// and ToType is the type that we're eventually trying to convert to -/// (which may or may not be the same type as the type that the -/// conversion function produces). void Sema::AddConversionCandidate( CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, @@ -8206,11 +8052,6 @@ void Sema::AddConversionCandidate( } } -/// Adds a conversion function template specialization -/// candidate to the overload set, using template argument deduction -/// to deduce the template arguments of the conversion function -/// template from the type that we are converting to (C++ -/// [temp.deduct.conv]). void Sema::AddTemplateConversionCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingDC, Expr *From, QualType ToType, @@ -8265,11 +8106,6 @@ void Sema::AddTemplateConversionCandidate( AllowExplicit, AllowResultConversion); } -/// AddSurrogateCandidate - Adds a "surrogate" candidate function that -/// converts the given @c Object to a function pointer via the -/// conversion function @c Conversion, and then attempts to call it -/// with the given arguments (C++ [over.call.object]p2-4). Proto is -/// the type of function that we'll eventually be calling. void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, @@ -8397,8 +8233,6 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, } } -/// Add all of the non-member operator function declarations in the given -/// function set to the overload candidate set. void Sema::AddNonMemberOperatorCandidates( const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -8439,14 +8273,6 @@ void Sema::AddNonMemberOperatorCandidates( } } -/// Add overload candidates for overloaded operators that are -/// member functions. -/// -/// Add the overloaded operator candidates that are member functions -/// for the operator Op that was used in an operator expression such -/// as "x Op y". , Args/NumArgs provides the operator arguments, and -/// CandidateSet will store the added overload candidates. (C++ -/// [over.match.oper]). void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, SourceLocation OpLoc, ArrayRef<Expr *> Args, @@ -8495,14 +8321,6 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, } } -/// AddBuiltinCandidate - Add a candidate for a built-in -/// operator. ResultTy and ParamTys are the result and parameter types -/// of the built-in candidate, respectively. Args and NumArgs are the -/// arguments being passed to the candidate. IsAssignmentOperator -/// should be true when this built-in candidate is an assignment -/// operator. NumContextualBoolArguments is the number of arguments -/// (at the beginning of the argument list) that will be contextually -/// converted to bool. void Sema::AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, bool IsAssignmentOperator, @@ -9961,11 +9779,6 @@ public: } // end anonymous namespace -/// AddBuiltinOperatorCandidates - Add the appropriate built-in -/// operator overloads to the candidate set (C++ [over.built]), based -/// on the operator @p Op and the arguments given. For example, if the -/// operator is a binary '+', this routine might add "int -/// operator+(int, int)" to cover integer addition. void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, SourceLocation OpLoc, ArrayRef<Expr *> Args, @@ -10163,13 +9976,6 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, } } -/// Add function candidates found via argument-dependent lookup -/// to the set of overloading candidates. -/// -/// This routine performs argument-dependent name lookup based on the -/// given function name (which may also be an operator name) and adds -/// all of the overload candidates found by ADL to the overload -/// candidate set (C++ [basic.lookup.argdep]). void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, SourceLocation Loc, @@ -13312,21 +13118,6 @@ public: }; } -/// ResolveAddressOfOverloadedFunction - Try to resolve the address of -/// an overloaded function (C++ [over.over]), where @p From is an -/// expression with overloaded function type and @p ToType is the type -/// we're trying to resolve to. For example: -/// -/// @code -/// int f(double); -/// int f(int); -/// -/// int (*pfd)(double) = f; // selects f(double) -/// @endcode -/// -/// This routine returns the resulting FunctionDecl if it could be -/// resolved, and NULL otherwise. When @p Complain is true, this -/// routine will emit diagnostics if there is an error. FunctionDecl * Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, @@ -13367,13 +13158,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, return Fn; } -/// Given an expression that refers to an overloaded function, try to -/// resolve that function to a single function that can have its address taken. -/// This will modify `Pair` iff it returns non-null. -/// -/// This routine can only succeed if from all of the candidates in the overload -/// set for SrcExpr that can have their addresses taken, there is one candidate -/// that is more constrained than the rest. FunctionDecl * Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) { OverloadExpr::FindResult R = OverloadExpr::find(E); @@ -13460,13 +13244,6 @@ Sema::resolveAddressOfSingleOverloadCandidate(Expr *E, DeclAccessPair &Pair) { return Result; } -/// Given an overloaded function, tries to turn it into a non-overloaded -/// function reference using resolveAddressOfSingleOverloadCandidate. This -/// will perform access checks, diagnose the use of the resultant decl, and, if -/// requested, potentially perform a function-to-pointer decay. -/// -/// Returns false if resolveAddressOfSingleOverloadCandidate fails. -/// Otherwise, returns true. This may emit diagnostics and return true. bool Sema::resolveAndFixAddressOfSingleOverloadCandidate( ExprResult &SrcExpr, bool DoFunctionPointerConversion) { Expr *E = SrcExpr.get(); @@ -13494,16 +13271,6 @@ bool Sema::resolveAndFixAddressOfSingleOverloadCandidate( return true; } -/// Given an expression that refers to an overloaded function, try to -/// resolve that overloaded function expression down to a single function. -/// -/// This routine can only resolve template-ids that refer to a single function -/// template, where that template-id refers to a single template whose template -/// arguments are either provided by the template-id or have defaults, -/// as described in C++0x [temp.arg.explicit]p3. -/// -/// If no template-ids are found, no diagnostics are emitted and NULL is -/// returned. FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( OverloadExpr *ovl, bool Complain, DeclAccessPair *FoundResult, TemplateSpecCandidateSet *FailedTSC) { @@ -13578,14 +13345,6 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization( return Matched; } -// Resolve and fix an overloaded expression that can be resolved -// because it identifies a single function template specialization. -// -// Last three arguments should only be supplied if Complain = true -// -// Return true if it was logically possible to so resolve the -// expression, regardless of whether or not it succeeded. Always -// returns true if 'complain' is set. bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( ExprResult &SrcExpr, bool doFunctionPointerConversion, bool complain, SourceRange OpRangeForComplaining, QualType DestTypeForComplaining, @@ -13699,8 +13458,6 @@ static void AddOverloadedCallCandidate(Sema &S, assert(!KnownValid && "unhandled case in overloaded call candidate"); } -/// Add the overload candidates named by callee and/or found by argument -/// dependent lookup to the given overload set. void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, @@ -13755,8 +13512,6 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, CandidateSet, PartialOverloading); } -/// Add the call candidates from the given set of lookup results to the given -/// overload set. Non-function lookup results are ignored. void Sema::AddOverloadedCallCandidates( LookupResult &R, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet) { @@ -14020,9 +13775,6 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, RParenLoc); } -/// Constructs and populates an OverloadedCandidateSet from -/// the given function. -/// \returns true when an the ExprResult output parameter has been set. bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, MultiExprArg Args, @@ -14250,12 +14002,6 @@ static void markUnaddressableCandidatesUnviable(Sema &S, } } -/// BuildOverloadedCallExpr - Given the call expression that calls Fn -/// (which eventually refers to the declaration Func) and the call -/// arguments Args/NumArgs, attempt to resolve the function call down -/// to a specific function. If overload resolution succeeds, returns -/// the call expression produced by overload resolution. -/// Otherwise, emits diagnostics and returns ExprError. ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, @@ -14391,21 +14137,6 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, return CheckForImmediateInvocation(CE, CE->getDirectCallee()); } -/// Create a unary operation that may resolve to an overloaded -/// operator. -/// -/// \param OpLoc The location of the operator itself (e.g., '*'). -/// -/// \param Opc The UnaryOperatorKind that describes this operator. -/// -/// \param Fns The set of non-member functions that will be -/// considered by overload resolution. The caller needs to build this -/// set based on the context using, e.g., -/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This -/// set should not contain any member functions; those will be added -/// by CreateOverloadedUnaryOp(). -/// -/// \param Input The input argument. ExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, @@ -14601,7 +14332,6 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, return CreateBuiltinUnaryOp(OpLoc, Opc, Input); } -/// Perform lookup for an overloaded binary operator. void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet, OverloadedOperatorKind Op, const UnresolvedSetImpl &Fns, @@ -14665,29 +14395,6 @@ void Sema::LookupOverloadedBinOp(OverloadCandidateSet &CandidateSet, AddBuiltinOperatorCandidates(Op, OpLoc, Args, CandidateSet); } -/// Create a binary operation that may resolve to an overloaded -/// operator. -/// -/// \param OpLoc The location of the operator itself (e.g., '+'). -/// -/// \param Opc The BinaryOperatorKind that describes this operator. -/// -/// \param Fns The set of non-member functions that will be -/// considered by overload resolution. The caller needs to build this -/// set based on the context using, e.g., -/// LookupOverloadedOperatorName() and ArgumentDependentLookup(). This -/// set should not contain any member functions; those will be added -/// by CreateOverloadedBinOp(). -/// -/// \param LHS Left-hand argument. -/// \param RHS Right-hand argument. -/// \param PerformADL Whether to consider operator candidates found by ADL. -/// \param AllowRewrittenCandidates Whether to consider candidates found by -/// C++20 operator rewrites. -/// \param DefaultedFn If we are synthesizing a defaulted operator function, -/// the function in question. Such a function is never a candidate in -/// our overload resolution. This also enables synthesizing a three-way -/// comparison from < and == as described in C++20 [class.spaceship]p1. ExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *LHS, @@ -15471,13 +15178,6 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, return CreateBuiltinArraySubscriptExpr(Args[0], LLoc, Args[1], RLoc); } -/// BuildCallToMemberFunction - Build a call to a member -/// function. MemExpr is the expression that refers to the member -/// function (and includes the object parameter), Args/NumArgs are the -/// arguments to the function call (not including the object -/// parameter). The caller needs to validate that the member -/// expression refers to a non-static member function or an overloaded -/// member function. ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, SourceLocation LParenLoc, MultiExprArg Args, @@ -15803,10 +15503,6 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, TheCall->getDirectCallee()); } -/// BuildCallToObjectOfClassType - Build a call to an object of class -/// type (C++ [over.call.object]), which can end up invoking an -/// overloaded function call operator (@c operator()) or performing a -/// user-defined conversion on the object argument. ExprResult Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, SourceLocation LParenLoc, @@ -16079,9 +15775,6 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -/// BuildOverloadedArrowExpr - Build a call to an overloaded @c operator-> -/// (if one exists), where @c Base is an expression of class type and -/// @c Member is the name of the member we're trying to find. ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool *NoArrowOperatorFound) { @@ -16212,8 +15905,6 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, return CheckForImmediateInvocation(MaybeBindToTemporary(TheCall), Method); } -/// BuildLiteralOperatorCall - Build a UserDefinedLiteral by creating a call to -/// a literal operator described by the provided lookup results. ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, DeclarationNameInfo &SuffixInfo, ArrayRef<Expr*> Args, @@ -16289,13 +15980,6 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, return CheckForImmediateInvocation(MaybeBindToTemporary(UDL), FD); } -/// Build a call to 'begin' or 'end' for a C++11 for-range statement. If the -/// given LookupResult is non-empty, it is assumed to describe a member which -/// will be invoked. Otherwise, the function will be found via argument -/// dependent lookup. -/// CallExpr is set to a valid expression and FRS_Success returned on success, -/// otherwise CallExpr is set to ExprError() and some non-success value -/// is returned. Sema::ForRangeStatus Sema::BuildForRangeBeginEndCall(SourceLocation Loc, SourceLocation RangeLoc, @@ -16358,12 +16042,6 @@ Sema::BuildForRangeBeginEndCall(SourceLocation Loc, return FRS_Success; } - -/// FixOverloadedFunctionReference - E is an expression that refers to -/// a C++ overloaded function (possibly with some parentheses and -/// perhaps a '&' around it). We have resolved the overloaded function -/// to the function declaration Fn, so patch up the expression E to -/// refer (possibly indirectly) to Fn. Returns the new expr. ExprResult Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, FunctionDecl *Fn) { if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 1bb8638..34d2d39 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -544,7 +544,6 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal, return CS; } -/// ActOnCaseStmtBody - This installs a statement as the body of a case. void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) { cast<CaseStmt>(S)->setSubStmt(SubStmt); } @@ -2220,10 +2219,6 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, Body, ForLoc, LParenLoc, RParenLoc); } -/// In an Objective C collection iteration statement: -/// for (x in y) -/// x can be an arbitrary l-value expression. Bind it up as a -/// full-expression. StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { // Reduce placeholder expressions here. Note that this rejects the // use of pseudo-object l-values in this position. @@ -2336,24 +2331,6 @@ static bool ObjCEnumerationCollection(Expr *Collection) { && Collection->getType()->getAs<ObjCObjectPointerType>() != nullptr; } -/// ActOnCXXForRangeStmt - Check and build a C++11 for-range statement. -/// -/// C++11 [stmt.ranged]: -/// A range-based for statement is equivalent to -/// -/// { -/// auto && __range = range-init; -/// for ( auto __begin = begin-expr, -/// __end = end-expr; -/// __begin != __end; -/// ++__begin ) { -/// for-range-declaration = *__begin; -/// statement -/// } -/// } -/// -/// The body of the loop is not available yet, since it cannot be analysed until -/// we have determined the type of the for-range-declaration. StmtResult Sema::ActOnCXXForRangeStmt( Scope *S, SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, Stmt *First, SourceLocation ColonLoc, Expr *Range, SourceLocation RParenLoc, @@ -2612,7 +2589,6 @@ static StmtResult RebuildForRangeWithDereference(Sema &SemaRef, Scope *S, AdjustedRange.get(), RParenLoc, Sema::BFRK_Rebuild); } -/// BuildCXXForRangeStmt - Build or instantiate a C++11 for-range statement. StmtResult Sema::BuildCXXForRangeStmt( SourceLocation ForLoc, SourceLocation CoawaitLoc, Stmt *InitStmt, SourceLocation ColonLoc, Stmt *RangeDecl, Stmt *Begin, Stmt *End, @@ -3129,10 +3105,6 @@ static void DiagnoseForRangeVariableCopies(Sema &SemaRef, } } -/// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement. -/// This is a separate step from ActOnCXXForRangeStmt because analysis of the -/// body cannot be performed until after the type of the range variable is -/// determined. StmtResult Sema::FinishCXXForRangeStmt(Stmt *S, Stmt *B) { if (!S || !B) return StmtError(); @@ -3262,20 +3234,6 @@ Sema::ActOnBreakStmt(SourceLocation BreakLoc, Scope *CurScope) { return new (Context) BreakStmt(BreakLoc); } -/// Determine whether the given expression might be move-eligible or -/// copy-elidable in either a (co_)return statement or throw expression, -/// without considering function return type, if applicable. -/// -/// \param E The expression being returned from the function or block, -/// being thrown, or being co_returned from a coroutine. This expression -/// might be modified by the implementation. -/// -/// \param Mode Overrides detection of current language mode -/// and uses the rules for C++23. -/// -/// \returns An aggregate which contains the Candidate and isMoveEligible -/// and isCopyElidable methods. If Candidate is non-null, it means -/// isMoveEligible() would be true under the most permissive language standard. Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, SimplerImplicitMoveMode Mode) { if (!E) @@ -3302,14 +3260,6 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(Expr *&E, return Res; } -/// Determine whether the given NRVO candidate variable is move-eligible or -/// copy-elidable, without considering function return type. -/// -/// \param VD The NRVO candidate variable. -/// -/// \returns An aggregate which contains the Candidate and isMoveEligible -/// and isCopyElidable methods. If Candidate is non-null, it means -/// isMoveEligible() would be true under the most permissive language standard. Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD) { NamedReturnInfo Info{VD, NamedReturnInfo::MoveEligibleAndCopyElidable}; @@ -3362,15 +3312,6 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD) { return Info; } -/// Updates given NamedReturnInfo's move-eligible and -/// copy-elidable statuses, considering the function -/// return type criteria as applicable to return statements. -/// -/// \param Info The NamedReturnInfo object to update. -/// -/// \param ReturnType This is the return type of the function. -/// \returns The copy elision candidate, in case the initial return expression -/// was copy elidable, or nullptr otherwise. const VarDecl *Sema::getCopyElisionCandidate(NamedReturnInfo &Info, QualType ReturnType) { if (!Info.Candidate) @@ -3428,12 +3369,6 @@ VerifyInitializationSequenceCXX98(const Sema &S, return true; } -/// Perform the initialization of a potentially-movable value, which -/// is the result of return value. -/// -/// This routine implements C++20 [class.copy.elision]p3, which attempts to -/// treat returned lvalues as rvalues in certain cases (to prefer move -/// construction), then falls back to treating them as lvalues if that failed. ExprResult Sema::PerformMoveOrCopyInitialization( const InitializedEntity &Entity, const NamedReturnInfo &NRInfo, Expr *Value, bool SupressSimplerImplicitMoves) { @@ -3474,9 +3409,6 @@ static bool hasDeducedReturnType(FunctionDecl *FD) { return FPT->getReturnType()->isUndeducedType(); } -/// ActOnCapScopeReturnStmt - Utility routine to type-check return statements -/// for capturing scopes. -/// StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, NamedReturnInfo &NRInfo, @@ -3690,8 +3622,6 @@ TypeLoc Sema::getReturnTypeLoc(FunctionDecl *FD) const { .getReturnLoc(); } -/// Deduce the return type for a function from a returned expression, per -/// C++1y [dcl.spec.auto]p6. bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, Expr *RetExpr, const AutoType *AT) { @@ -4132,8 +4062,6 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, return Result; } -/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block -/// and creates a proper catch handler from them. StmtResult Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock) { @@ -4255,8 +4183,6 @@ public: }; } -/// ActOnCXXTryBlock - Takes a try compound-statement and a number of -/// handlers and creates a try statement from them. StmtResult Sema::ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, ArrayRef<Stmt *> Handlers) { const llvm::Triple &T = Context.getTargetInfo().getTriple(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9f4acbe..6879a9a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -720,9 +720,6 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, Diag(Found->getLocation(), diag::note_non_template_in_template_id_found); } -/// ActOnDependentIdExpression - Handle a dependent id-expression that -/// was just parsed. This is only possible with an explicit scope -/// specifier naming a dependent type. ExprResult Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, @@ -764,9 +761,6 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, TemplateArgs); } - -/// Determine whether we would be unable to instantiate this template (because -/// it either has no definition, or is in the process of being instantiated). bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, NamedDecl *Instantiation, bool InstantiatedFromMember, @@ -882,9 +876,6 @@ void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl, NoteTemplateParameterLocation(*ND); } -/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset -/// the parameter D to reference the templated declaration and return a pointer -/// to the template declaration. Otherwise, do nothing to D and return null. TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) { if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D)) { D = Temp->getTemplatedDecl(); @@ -938,8 +929,6 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, llvm_unreachable("Unhandled parsed template argument"); } -/// Translates template arguments as provided by the parser -/// into template arguments used by semantic analysis. void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, TemplateArgumentListInfo &TemplateArgs) { for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) @@ -957,10 +946,6 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S, SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl); } -/// Convert a parsed type into a parsed template argument. This is mostly -/// trivial, except that we may have parsed a C++17 deduced class template -/// specialization type, in which case we should form a template template -/// argument instead of a type template argument. ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) { TypeSourceInfo *TInfo; QualType T = GetTypeFromParser(ParsedType.get(), &TInfo); @@ -1003,15 +988,6 @@ ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) { TInfo->getTypeLoc().getBeginLoc()); } -/// ActOnTypeParameter - Called when a C++ template type parameter -/// (e.g., "typename T") has been parsed. Typename specifies whether -/// the keyword "typename" was used to declare the type parameter -/// (otherwise, "class" was used), and KeyLoc is the location of the -/// "class" or "typename" keyword. ParamName is the name of the -/// parameter (NULL indicates an unnamed template parameter) and -/// ParamNameLoc is the location of the parameter name (if any). -/// If the type parameter has a default argument, it will be added -/// later via ActOnTypeParameterDefault. NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename, SourceLocation EllipsisLoc, SourceLocation KeyLoc, @@ -1206,10 +1182,6 @@ static ExprResult formImmediatelyDeclaredConstraint( /*NumExpansions=*/std::nullopt); } -/// Attach a type-constraint to a template parameter. -/// \returns true if an error occurred. This can happen if the -/// immediately-declared constraint could not be formed (e.g. incorrect number -/// of arguments for the named concept). bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS, DeclarationNameInfo NameInfo, ConceptDecl *NamedConcept, NamedDecl *FoundDecl, @@ -1289,11 +1261,6 @@ bool Sema::AttachTypeConstraint(AutoTypeLoc TL, return false; } -/// Check that the type of a non-type template parameter is -/// well-formed. -/// -/// \returns the (possibly-promoted) parameter type if valid; -/// otherwise, produces a diagnostic and returns a NULL type. QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, SourceLocation Loc) { if (TSI->getType()->isUndeducedType()) { @@ -1308,9 +1275,6 @@ QualType Sema::CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI, return CheckNonTypeTemplateParameterType(TSI->getType(), Loc); } -/// Require the given type to be a structural type, and diagnose if it is not. -/// -/// \return \c true if an error was produced. bool Sema::RequireStructuralType(QualType T, SourceLocation Loc) { if (T->isDependentType()) return false; @@ -1606,9 +1570,6 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, return Param; } -/// ActOnTemplateTemplateParameter - Called when a C++ template template -/// parameter (e.g. T in template <template \<typename> class T> class array) -/// has been parsed. S is the current scope. NamedDecl *Sema::ActOnTemplateTemplateParameter( Scope *S, SourceLocation TmpLoc, TemplateParameterList *Params, bool Typename, SourceLocation EllipsisLoc, IdentifierInfo *Name, @@ -1775,9 +1736,6 @@ bool Sema::ConstraintExpressionDependsOnEnclosingTemplate( return Checker.getResult(); } -/// ActOnTemplateParameterList - Builds a TemplateParameterList, optionally -/// constrained by RequiresClause, that contains the template parameters in -/// Params. TemplateParameterList * Sema::ActOnTemplateParameterList(unsigned Depth, SourceLocation ExportLoc, @@ -3508,34 +3466,6 @@ static bool DiagnoseUnexpandedParameterPacks(Sema &S, return false; } -/// Checks the validity of a template parameter list, possibly -/// considering the template parameter list from a previous -/// declaration. -/// -/// If an "old" template parameter list is provided, it must be -/// equivalent (per TemplateParameterListsAreEqual) to the "new" -/// template parameter list. -/// -/// \param NewParams Template parameter list for a new template -/// declaration. This template parameter list will be updated with any -/// default arguments that are carried through from the previous -/// template parameter list. -/// -/// \param OldParams If provided, template parameter list from a -/// previous declaration of the same template. Default template -/// arguments will be merged from the old template parameter list to -/// the new template parameter list. -/// -/// \param TPC Describes the context in which we are checking the given -/// template parameter list. -/// -/// \param SkipBody If we might have already made a prior merged definition -/// of this template visible, the corresponding body-skipping information. -/// Default argument redefinition is not an error when skipping such a body, -/// because (under the ODR) we can assume the default arguments are the same -/// as the prior merged definition. -/// -/// \returns true if an error occurred, false otherwise. bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, TemplateParameterList *OldParams, TemplateParamListContext TPC, @@ -3937,39 +3867,6 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, return SourceRange(); } -/// Match the given template parameter lists to the given scope -/// specifier, returning the template parameter list that applies to the -/// name. -/// -/// \param DeclStartLoc the start of the declaration that has a scope -/// specifier or a template parameter list. -/// -/// \param DeclLoc The location of the declaration itself. -/// -/// \param SS the scope specifier that will be matched to the given template -/// parameter lists. This scope specifier precedes a qualified name that is -/// being declared. -/// -/// \param TemplateId The template-id following the scope specifier, if there -/// is one. Used to check for a missing 'template<>'. -/// -/// \param ParamLists the template parameter lists, from the outermost to the -/// innermost template parameter lists. -/// -/// \param IsFriend Whether to apply the slightly different rules for -/// matching template parameters to scope specifiers in friend -/// declarations. -/// -/// \param IsMemberSpecialization will be set true if the scope specifier -/// denotes a fully-specialized type, and therefore this is a declaration of -/// a member specialization. -/// -/// \returns the template parameter list, if any, that corresponds to the -/// name that is preceded by the scope specifier @p SS. This template -/// parameter list may have template parameters (if we're declaring a -/// template) or may have no template parameters (if we're declaring a -/// template specialization), or may be NULL (if what we're declaring isn't -/// itself a template). TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId, @@ -5742,7 +5639,6 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, return ULE; } -// We actually only call this from template instantiation. ExprResult Sema::BuildQualifiedTemplateIdExpr( CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, @@ -5775,20 +5671,6 @@ ExprResult Sema::BuildQualifiedTemplateIdExpr( return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL=*/false, TemplateArgs); } -/// Form a template name from a name that is syntactically required to name a -/// template, either due to use of the 'template' keyword or because a name in -/// this syntactic context is assumed to name a template (C++ [temp.names]p2-4). -/// -/// This action forms a template name given the name of the template and its -/// optional scope specifier. This is used when the 'template' keyword is used -/// or when the parsing context unambiguously treats a following '<' as -/// introducing a template argument list. Note that this may produce a -/// non-dependent template name if we can perform the lookup now and identify -/// the named template. -/// -/// For example, given "x.MetaFun::template apply", the scope specifier -/// \p SS will be "MetaFun::", \p TemplateKWLoc contains the location -/// of the "template" keyword, and "apply" is the \p Name. TemplateNameKind Sema::ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, @@ -6205,9 +6087,6 @@ static TemplateName SubstDefaultTemplateArgument( TemplateArgLists); } -/// If the given template parameter has a default template -/// argument, substitute into that default template argument and -/// return the corresponding template argument. TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, Decl *Param, @@ -6295,32 +6174,6 @@ convertTypeTemplateArgumentToTemplate(ASTContext &Context, TypeLoc TLoc) { return TemplateArgumentLoc(); } -/// Check that the given template argument corresponds to the given -/// template parameter. -/// -/// \param Param The template parameter against which the argument will be -/// checked. -/// -/// \param Arg The template argument, which may be updated due to conversions. -/// -/// \param Template The template in which the template argument resides. -/// -/// \param TemplateLoc The location of the template name for the template -/// whose argument list we're matching. -/// -/// \param RAngleLoc The location of the right angle bracket ('>') that closes -/// the template argument list. -/// -/// \param ArgumentPackIndex The index into the argument pack where this -/// argument will be placed. Only valid if the parameter is a parameter pack. -/// -/// \param Converted The checked, converted argument will be added to the -/// end of this small vector. -/// -/// \param CTAK Describes how we arrived at this particular template argument: -/// explicitly written, deduced, etc. -/// -/// \returns true on error, false otherwise. bool Sema::CheckTemplateArgument( NamedDecl *Param, TemplateArgumentLoc &Arg, NamedDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, @@ -7225,11 +7078,6 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } -/// Check a template argument against its corresponding -/// template type parameter. -/// -/// This routine implements the semantics of C++ [temp.arg.type]. It -/// returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateArgument(TypeSourceInfo *ArgInfo) { assert(ArgInfo && "invalid TypeSourceInfo"); QualType Arg = ArgInfo->getType(); @@ -7832,13 +7680,6 @@ CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param, return true; } -/// Check a template argument against its corresponding -/// non-type template parameter. -/// -/// This routine implements the semantics of C++ [temp.arg.nontype]. -/// If an error occurred, it returns ExprError(); otherwise, it -/// returns the converted template argument. \p ParamType is the -/// type of the non-type template parameter after it has been instantiated. ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *Arg, TemplateArgument &SugaredConverted, @@ -8446,11 +8287,6 @@ static void DiagnoseTemplateParameterListArityMismatch( Sema &S, TemplateParameterList *New, TemplateParameterList *Old, Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc); -/// Check a template argument against its corresponding -/// template template parameter. -/// -/// This routine implements the semantics of C++ [temp.arg.template]. -/// It returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, TemplateArgumentLoc &Arg, @@ -8580,10 +8416,6 @@ void Sema::NoteTemplateParameterLocation(const NamedDecl &Decl) { diag::note_template_param_external); } -/// Given a non-type template argument that refers to a -/// declaration and the type of its corresponding non-type template -/// parameter, produce an expression that properly refers to that -/// declaration. ExprResult Sema::BuildExpressionFromDeclTemplateArgument( const TemplateArgument &Arg, QualType ParamType, SourceLocation Loc, NamedDecl *TemplateParam) { @@ -9031,29 +8863,6 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S, << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc()); } -/// Determine whether the given template parameter lists are -/// equivalent. -/// -/// \param New The new template parameter list, typically written in the -/// source code as part of a new template declaration. -/// -/// \param Old The old template parameter list, typically found via -/// name lookup of the template declared with this template parameter -/// list. -/// -/// \param Complain If true, this routine will produce a diagnostic if -/// the template parameter lists are not equivalent. -/// -/// \param Kind describes how we are to match the template parameter lists. -/// -/// \param TemplateArgLoc If this source location is valid, then we -/// are actually checking the template parameter list of a template -/// argument (New) against the template parameter list of its -/// corresponding template template parameter (Old). We produce -/// slightly different diagnostics in this scenario. -/// -/// \returns True if the template parameter lists are equal, false -/// otherwise. bool Sema::TemplateParameterListsAreEqual( const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New, const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, @@ -9151,10 +8960,6 @@ bool Sema::TemplateParameterListsAreEqual( return true; } -/// Check whether a template can be declared within this scope. -/// -/// If the template declaration is valid in this scope, returns -/// false. Otherwise, issues a diagnostic and returns true. bool Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { if (!S) @@ -9423,17 +9228,6 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs( return false; } -/// Check the non-type template arguments of a class template -/// partial specialization according to C++ [temp.class.spec]p9. -/// -/// \param TemplateNameLoc the location of the template name. -/// \param PrimaryTemplate the template parameters of the primary class -/// template. -/// \param NumExplicit the number of explicitly-specified template arguments. -/// \param TemplateArgs the template arguments of the class template -/// partial specialization. -/// -/// \returns \c true if there was an error, \c false otherwise. bool Sema::CheckTemplatePartialSpecializationArgs( SourceLocation TemplateNameLoc, TemplateDecl *PrimaryTemplate, unsigned NumExplicit, ArrayRef<TemplateArgument> TemplateArgs) { @@ -9978,28 +9772,6 @@ static SourceLocation DiagLocForExplicitInstantiation( return PrevDiagLoc; } -/// Diagnose cases where we have an explicit template specialization -/// before/after an explicit template instantiation, producing diagnostics -/// for those cases where they are required and determining whether the -/// new specialization/instantiation will have any effect. -/// -/// \param NewLoc the location of the new explicit specialization or -/// instantiation. -/// -/// \param NewTSK the kind of the new explicit specialization or instantiation. -/// -/// \param PrevDecl the previous declaration of the entity. -/// -/// \param PrevTSK the kind of the old explicit specialization or instantiatin. -/// -/// \param PrevPointOfInstantiation if valid, indicates where the previous -/// declaration was instantiated (either implicitly or explicitly). -/// -/// \param HasNoEffect will be set to true to indicate that the new -/// specialization or instantiation has no effect and should be ignored. -/// -/// \returns true if there was an error that should prevent the introduction of -/// the new declaration into the AST, false otherwise. bool Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, TemplateSpecializationKind NewTSK, @@ -10166,21 +9938,6 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, llvm_unreachable("Missing specialization/instantiation case?"); } -/// Perform semantic analysis for the given dependent function -/// template specialization. -/// -/// The only possible way to get a dependent function template specialization -/// is with a friend declaration, like so: -/// -/// \code -/// template \<class T> void foo(T); -/// template \<class T> class A { -/// friend void foo<>(T); -/// }; -/// \endcode -/// -/// There really isn't any useful analysis we can do here, so we -/// just store the information. bool Sema::CheckDependentFunctionTemplateSpecialization( FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous) { @@ -10223,28 +9980,6 @@ bool Sema::CheckDependentFunctionTemplateSpecialization( return false; } -/// Perform semantic analysis for the given function template -/// specialization. -/// -/// This routine performs all of the semantic analysis required for an -/// explicit function template specialization. On successful completion, -/// the function declaration \p FD will become a function template -/// specialization. -/// -/// \param FD the function declaration, which will be updated to become a -/// function template specialization. -/// -/// \param ExplicitTemplateArgs the explicitly-provided template arguments, -/// if any. Note that this may be valid info even when 0 arguments are -/// explicitly provided as in, e.g., \c void sort<>(char*, char*); -/// as it anyway contains info on the angle brackets locations. -/// -/// \param Previous the set of declarations that may be specialized by -/// this function specialization. -/// -/// \param QualifiedFriend whether this is a lookup for a qualified friend -/// declaration with no explicit template argument list that might be -/// befriending a function template specialization. bool Sema::CheckFunctionTemplateSpecialization( FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous, bool QualifiedFriend) { @@ -10505,20 +10240,6 @@ bool Sema::CheckFunctionTemplateSpecialization( return false; } -/// Perform semantic analysis for the given non-template member -/// specialization. -/// -/// This routine performs all of the semantic analysis required for an -/// explicit member function specialization. On successful completion, -/// the function declaration \p FD will become a member function -/// specialization. -/// -/// \param Member the member declaration, which will be updated to become a -/// specialization. -/// -/// \param Previous the set of declarations, one of which may be specialized -/// by this function specialization; the set will be modified to contain the -/// redeclared member. bool Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { assert(!isa<TemplateDecl>(Member) && "Only for non-template members"); @@ -10868,7 +10589,6 @@ static void dllExportImportClassTemplateSpecialization( S.referenceDLLExportedClassMethods(); } -// Explicit instantiation of a class template specialization DeclResult Sema::ActOnExplicitInstantiation( Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, @@ -11163,7 +10883,6 @@ DeclResult Sema::ActOnExplicitInstantiation( return Specialization; } -// Explicit instantiation of a member class of a class template. DeclResult Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, unsigned TagSpec, @@ -12149,32 +11868,6 @@ namespace { }; } // end anonymous namespace -/// Rebuilds a type within the context of the current instantiation. -/// -/// The type \p T is part of the type of an out-of-line member definition of -/// a class template (or class template partial specialization) that was parsed -/// and constructed before we entered the scope of the class template (or -/// partial specialization thereof). This routine will rebuild that type now -/// that we have entered the declarator's scope, which may produce different -/// canonical types, e.g., -/// -/// \code -/// template<typename T> -/// struct X { -/// typedef T* pointer; -/// pointer data(); -/// }; -/// -/// template<typename T> -/// typename X<T>::pointer X<T>::data() { ... } -/// \endcode -/// -/// Here, the type "typename X<T>::pointer" will be created as a DependentNameType, -/// since we do not know that we can look into X<T> when we parsed the type. -/// This function will rebuild the type, performing the lookup of "pointer" -/// in X<T> and returning an ElaboratedType whose canonical type is the same -/// as the canonical type of T*, allowing the return types of the out-of-line -/// definition and the declaration to match. TypeSourceInfo *Sema::RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, SourceLocation Loc, DeclarationName Name) { @@ -12207,8 +11900,6 @@ bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) { return false; } -/// Rebuild the template parameters now that we know we're in a current -/// instantiation. bool Sema::RebuildTemplateParamsInCurrentInstantiation( TemplateParameterList *Params) { for (unsigned I = 0, N = Params->size(); I != N; ++I) { @@ -12255,8 +11946,6 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation( return false; } -/// Produces a formatted string that describes the binding of -/// template parameters to template arguments. std::string Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args) { @@ -12502,10 +12191,6 @@ void Sema::checkSpecializationReachability(SourceLocation Loc, .check(Spec); } -/// Returns the top most location responsible for the definition of \p N. -/// If \p N is a a template specialization, this is the location -/// of the top of the instantiation stack. -/// Otherwise, the location of \p N is returned. SourceLocation Sema::getTopMostPointOfInstantiation(const NamedDecl *N) const { if (!getLangOpts().CPlusPlus || CodeSynthesisContexts.empty()) return N->getLocation(); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index a432918..b7b857e 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -1336,13 +1336,6 @@ static bool hasInconsistentOrSupersetQualifiersOf(QualType ParamType, return (ParamQs.getCVRQualifiers() & ~ArgQs.getCVRQualifiers()) != 0; } -/// Compare types for equality with respect to possibly compatible -/// function types (noreturn adjustment, implicit calling conventions). If any -/// of parameter and argument is not a function, just perform type comparison. -/// -/// \param P the template parameter type. -/// -/// \param A the argument type. bool Sema::isSameOrCompatibleFunctionType(QualType P, QualType A) { const FunctionType *PF = P->getAs<FunctionType>(), *AF = A->getAs<FunctionType>(); @@ -2754,19 +2747,6 @@ static bool isSameTemplateArg(ASTContext &Context, llvm_unreachable("Invalid TemplateArgument Kind!"); } -/// Allocate a TemplateArgumentLoc where all locations have -/// been initialized to the given location. -/// -/// \param Arg The template argument we are producing template argument -/// location information for. -/// -/// \param NTTPType For a declaration template argument, the type of -/// the non-type template parameter that corresponds to this template -/// argument. Can be null if no type sugar is available to add to the -/// type from the template argument. -/// -/// \param Loc The source location to use for the resulting template -/// argument. TemplateArgumentLoc Sema::getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, @@ -3448,30 +3428,6 @@ static bool isSimpleTemplateIdType(QualType T) { return false; } -/// Substitute the explicitly-provided template arguments into the -/// given function template according to C++ [temp.arg.explicit]. -/// -/// \param FunctionTemplate the function template into which the explicit -/// template arguments will be substituted. -/// -/// \param ExplicitTemplateArgs the explicitly-specified template -/// arguments. -/// -/// \param Deduced the deduced template arguments, which will be populated -/// with the converted and checked explicit template arguments. -/// -/// \param ParamTypes will be populated with the instantiated function -/// parameters. -/// -/// \param FunctionType if non-NULL, the result type of the function template -/// will also be instantiated and the pointed-to value will be updated with -/// the instantiated function type. -/// -/// \param Info if substitution fails for any reason, this object will be -/// populated with more information about the failure. -/// -/// \returns TemplateDeductionResult::Success if substitution was successful, or -/// some failure condition. TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo &ExplicitTemplateArgs, @@ -3849,12 +3805,6 @@ static TemplateDeductionResult instantiateExplicitSpecifierDeferred( return TemplateDeductionResult::Success; } -/// Finish template argument deduction for a function template, -/// checking the deduced template arguments for completeness and forming -/// the function template specialization. -/// -/// \param OriginalCallArgs If non-NULL, the original call arguments against -/// which the deduced argument types should be compared. TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( FunctionTemplateDecl *FunctionTemplate, SmallVectorImpl<DeducedTemplateArgument> &Deduced, @@ -4409,31 +4359,6 @@ static TemplateDeductionResult DeduceTemplateArgumentsFromCallArgument( ArgType, Info, Deduced, TDF); } -/// Perform template argument deduction from a function call -/// (C++ [temp.deduct.call]). -/// -/// \param FunctionTemplate the function template for which we are performing -/// template argument deduction. -/// -/// \param ExplicitTemplateArgs the explicit template arguments provided -/// for this call. -/// -/// \param Args the function call arguments -/// -/// \param Specialization if template argument deduction was successful, -/// this will be set to the function template specialization produced by -/// template argument deduction. -/// -/// \param Info the argument will be updated to provide additional information -/// about template argument deduction. -/// -/// \param CheckNonDependent A callback to invoke to check conversions for -/// non-dependent parameters, between deduction and substitution, per DR1391. -/// If this returns true, substitution will be skipped and we return -/// TemplateDeductionResult::NonDependentConversionFailure. The callback is -/// passed the parameter types (after substituting explicit template arguments). -/// -/// \returns the result of template argument deduction. TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, @@ -4695,34 +4620,6 @@ QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, ArgFunctionTypeP->getParamTypes(), EPI); } -/// Deduce template arguments when taking the address of a function -/// template (C++ [temp.deduct.funcaddr]) or matching a specialization to -/// a template. -/// -/// \param FunctionTemplate the function template for which we are performing -/// template argument deduction. -/// -/// \param ExplicitTemplateArgs the explicitly-specified template -/// arguments. -/// -/// \param ArgFunctionType the function type that will be used as the -/// "argument" type (A) when performing template argument deduction from the -/// function template's function type. This type may be NULL, if there is no -/// argument type to compare against, in C++0x [temp.arg.explicit]p3. -/// -/// \param Specialization if template argument deduction was successful, -/// this will be set to the function template specialization produced by -/// template argument deduction. -/// -/// \param Info the argument will be updated to provide additional information -/// about template argument deduction. -/// -/// \param IsAddressOfFunction If \c true, we are deducing as part of taking -/// the address of a function template per [temp.deduct.funcaddr] and -/// [over.over]. If \c false, we are looking up a function template -/// specialization based on its signature, per [temp.deduct.decl]. -/// -/// \returns the result of template argument deduction. TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, @@ -4850,9 +4747,6 @@ TemplateDeductionResult Sema::DeduceTemplateArguments( return TemplateDeductionResult::Success; } -/// Deduce template arguments for a templated conversion -/// function (C++ [temp.deduct.conv]) and, if successful, produce a -/// conversion function template specialization. TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *ConversionTemplate, QualType ObjectType, Expr::Classification ObjectClassification, QualType ToType, @@ -4984,30 +4878,6 @@ TemplateDeductionResult Sema::DeduceTemplateArguments( return Result; } -/// Deduce template arguments for a function template when there is -/// nothing to deduce against (C++0x [temp.arg.explicit]p3). -/// -/// \param FunctionTemplate the function template for which we are performing -/// template argument deduction. -/// -/// \param ExplicitTemplateArgs the explicitly-specified template -/// arguments. -/// -/// \param Specialization if template argument deduction was successful, -/// this will be set to the function template specialization produced by -/// template argument deduction. -/// -/// \param Info the argument will be updated to provide additional information -/// about template argument deduction. -/// -/// \param IsAddressOfFunction If \c true, we are deducing as part of taking -/// the address of a function template in a context where we do not have a -/// target type, per [over.over]. If \c false, we are looking up a function -/// template specialization based on its signature, which only happens when -/// deducing a function parameter type from an argument that is a template-id -/// naming a function template specialization. -/// -/// \returns the result of template argument deduction. TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, @@ -5171,24 +5041,6 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type, return false; } -/// Deduce the type for an auto type-specifier (C++11 [dcl.spec.auto]p6) -/// -/// Note that this is done even if the initializer is dependent. (This is -/// necessary to support partial ordering of templates using 'auto'.) -/// A dependent type will be produced when deducing from a dependent type. -/// -/// \param Type the type pattern using the auto type-specifier. -/// \param Init the initializer for the variable whose type is to be deduced. -/// \param Result if type deduction was successful, this will be set to the -/// deduced type. -/// \param Info the argument will be updated to provide additional information -/// about template argument deduction. -/// \param DependentDeduction Set if we should permit deduction in -/// dependent cases. This is necessary for template partial ordering with -/// 'auto' template parameters. The template parameter depth to be used -/// should be specified in the 'Info' parameter. -/// \param IgnoreConstraints Set if we should not fail if the deduced type does -/// not satisfy the type-constraint in the auto type. TemplateDeductionResult Sema::DeduceAutoType(TypeLoc Type, Expr *Init, QualType &Result, TemplateDeductionInfo &Info, bool DependentDeduction, @@ -5675,34 +5527,6 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc, return true; } -/// Returns the more specialized function template according -/// to the rules of function template partial ordering (C++ [temp.func.order]). -/// -/// \param FT1 the first function template -/// -/// \param FT2 the second function template -/// -/// \param TPOC the context in which we are performing partial ordering of -/// function templates. -/// -/// \param NumCallArguments1 The number of arguments in the call to FT1, used -/// only when \c TPOC is \c TPOC_Call. Does not include the object argument when -/// calling a member function. -/// -/// \param RawObj1Ty The type of the object parameter of FT1 if a member -/// function only used if \c TPOC is \c TPOC_Call and FT1 is a Function -/// template from a member function -/// -/// \param RawObj2Ty The type of the object parameter of FT2 if a member -/// function only used if \c TPOC is \c TPOC_Call and FT2 is a Function -/// template from a member function -/// -/// \param Reversed If \c true, exactly one of FT1 and FT2 is an overload -/// candidate with a reversed parameter order. In this case, the corresponding -/// P/A pairs between FT1 and FT2 are reversed. -/// -/// \returns the more specialized function template. If neither -/// template is more specialized, returns NULL. FunctionTemplateDecl *Sema::getMoreSpecializedTemplate( FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, SourceLocation Loc, TemplatePartialOrderingContext TPOC, unsigned NumCallArguments1, @@ -5921,31 +5745,6 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { return T1->getCanonicalDecl() == T2->getCanonicalDecl(); } -/// Retrieve the most specialized of the given function template -/// specializations. -/// -/// \param SpecBegin the start iterator of the function template -/// specializations that we will be comparing. -/// -/// \param SpecEnd the end iterator of the function template -/// specializations, paired with \p SpecBegin. -/// -/// \param Loc the location where the ambiguity or no-specializations -/// diagnostic should occur. -/// -/// \param NoneDiag partial diagnostic used to diagnose cases where there are -/// no matching candidates. -/// -/// \param AmbigDiag partial diagnostic used to diagnose an ambiguity, if one -/// occurs. -/// -/// \param CandidateDiag partial diagnostic used for each function template -/// specialization that is a candidate in the ambiguous ordering. One parameter -/// in this diagnostic should be unbound, which will correspond to the string -/// describing the template arguments for the function template specialization. -/// -/// \returns the most specialized function template specialization, if -/// found. Otherwise, returns SpecEnd. UnresolvedSetIterator Sema::getMostSpecialized( UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd, TemplateSpecCandidateSet &FailedCandidates, @@ -6021,15 +5820,6 @@ UnresolvedSetIterator Sema::getMostSpecialized( return SpecEnd; } -/// Returns the more constrained function according to the rules of -/// partial ordering by constraints (C++ [temp.constr.order]). -/// -/// \param FD1 the first function -/// -/// \param FD2 the second function -/// -/// \returns the more constrained function. If neither function is -/// more constrained, returns NULL. FunctionDecl *Sema::getMoreConstrainedFunction(FunctionDecl *FD1, FunctionDecl *FD2) { assert(!FD1->getDescribedTemplate() && !FD2->getDescribedTemplate() && @@ -6289,16 +6079,6 @@ getMoreSpecialized(Sema &S, QualType T1, QualType T2, TemplateLikeDecl *P1, return AtLeastAsConstrained1 ? P1 : GetP2()(P1, P2); } -/// Returns the more specialized class template partial specialization -/// according to the rules of partial ordering of class template partial -/// specializations (C++ [temp.class.order]). -/// -/// \param PS1 the first class template partial specialization -/// -/// \param PS2 the second class template partial specialization -/// -/// \returns the more specialized class template partial specialization. If -/// neither partial specialization is more specialized, returns NULL. ClassTemplatePartialSpecializationDecl * Sema::getMoreSpecializedPartialSpecialization( ClassTemplatePartialSpecializationDecl *PS1, @@ -6911,13 +6691,6 @@ MarkUsedTemplateParameters(ASTContext &Ctx, } } -/// Mark which template parameters are used in a given expression. -/// -/// \param E the expression from which template parameters will be deduced. -/// -/// \param Used a bit vector whose elements will be set to \c true -/// to indicate when the corresponding template parameter will be -/// deduced. void Sema::MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, @@ -6925,15 +6698,6 @@ Sema::MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, ::MarkUsedTemplateParameters(Context, E, OnlyDeduced, Depth, Used); } -/// Mark which template parameters can be deduced from a given -/// template argument list. -/// -/// \param TemplateArgs the template argument list from which template -/// parameters will be deduced. -/// -/// \param Used a bit vector whose elements will be set to \c true -/// to indicate when the corresponding template parameter will be -/// deduced. void Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, unsigned Depth, @@ -6951,8 +6715,6 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, Depth, Used); } -/// Marks all of the template parameters that will be deduced by a -/// call to the given function template. void Sema::MarkDeducedTemplateParameters( ASTContext &Ctx, const FunctionTemplateDecl *FunctionTemplate, llvm::SmallBitVector &Deduced) { diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 1fe1fe9..a7bc674 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -463,34 +463,6 @@ Response HandleGenericDeclContext(const Decl *CurDecl) { } // namespace TemplateInstArgsHelpers } // namespace -/// Retrieve the template argument list(s) that should be used to -/// instantiate the definition of the given declaration. -/// -/// \param ND the declaration for which we are computing template instantiation -/// arguments. -/// -/// \param DC In the event we don't HAVE a declaration yet, we instead provide -/// the decl context where it will be created. In this case, the `Innermost` -/// should likely be provided. If ND is non-null, this is ignored. -/// -/// \param Innermost if non-NULL, specifies a template argument list for the -/// template declaration passed as ND. -/// -/// \param RelativeToPrimary true if we should get the template -/// arguments relative to the primary template, even when we're -/// dealing with a specialization. This is only relevant for function -/// template specializations. -/// -/// \param Pattern If non-NULL, indicates the pattern from which we will be -/// instantiating the definition of the given declaration, \p ND. This is -/// used to determine the proper set of template instantiation arguments for -/// friend function template specializations. -/// -/// \param ForConstraintInstantiation when collecting arguments, -/// ForConstraintInstantiation indicates we should continue looking when -/// encountering a lambda generic call operator, and continue looking for -/// arguments on an enclosing class template. - MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( const NamedDecl *ND, const DeclContext *DC, bool Final, std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary, @@ -924,8 +896,6 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth( return true; } -/// Prints the current instantiation stack through a series of -/// notes. void Sema::PrintInstantiationStack() { // Determine which template instantiations to skip, if any. unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart; @@ -2822,37 +2792,6 @@ TemplateInstantiator::TransformNestedRequirement( SemaRef.Context, TransConstraint.get(), Satisfaction); } - -/// Perform substitution on the type T with a given set of template -/// arguments. -/// -/// This routine substitutes the given template arguments into the -/// type T and produces the instantiated type. -/// -/// \param T the type into which the template arguments will be -/// substituted. If this type is not dependent, it will be returned -/// immediately. -/// -/// \param Args the template arguments that will be -/// substituted for the top-level template parameters within T. -/// -/// \param Loc the location in the source code where this substitution -/// is being performed. It will typically be the location of the -/// declarator (if we're instantiating the type of some declaration) -/// or the location of the type in the source code (if, e.g., we're -/// instantiating the type of a cast expression). -/// -/// \param Entity the name of the entity associated with a declaration -/// being instantiated (if any). May be empty to indicate that there -/// is no such entity (if, e.g., this is a type that occurs as part of -/// a cast expression) or that the entity has no name (e.g., an -/// unnamed function parameter). -/// -/// \param AllowDeducedTST Whether a DeducedTemplateSpecializationType is -/// acceptable as the top level type of the result. -/// -/// \returns If the instantiation succeeds, the instantiated -/// type. Otherwise, produces diagnostics and returns a NULL type. TypeSourceInfo *Sema::SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &Args, SourceLocation Loc, @@ -2940,10 +2879,6 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) { return false; } -/// A form of SubstType intended specifically for instantiating the -/// type of a FunctionDecl. Its purpose is solely to force the -/// instantiation of default-argument expressions and to avoid -/// instantiating an exception-specification. TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &Args, SourceLocation Loc, @@ -3255,9 +3190,6 @@ ParmVarDecl *Sema::SubstParmVarDecl( return NewParm; } -/// Substitute the given template arguments into the given set of -/// parameters, producing the set of parameter types that would be generated -/// from such a substitution. bool Sema::SubstParmTypes( SourceLocation Loc, ArrayRef<ParmVarDecl *> Params, const FunctionProtoType::ExtParameterInfo *ExtParamInfos, @@ -3275,7 +3207,6 @@ bool Sema::SubstParmTypes( Loc, Params, nullptr, ExtParamInfos, ParamTypes, OutParams, ParamInfos); } -/// Substitute the given template arguments into the default argument. bool Sema::SubstDefaultArgument( SourceLocation Loc, ParmVarDecl *Param, @@ -3367,12 +3298,6 @@ bool Sema::SubstDefaultArgument( return false; } -/// Perform substitution on the base class specifiers of the -/// given class template specialization. -/// -/// Produces a diagnostic and returns true on error, returns false and -/// attaches the instantiated base classes to the class template -/// specialization if successful. bool Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, @@ -3487,28 +3412,6 @@ namespace clang { } } -/// Instantiate the definition of a class from a given pattern. -/// -/// \param PointOfInstantiation The point of instantiation within the -/// source code. -/// -/// \param Instantiation is the declaration whose definition is being -/// instantiated. This will be either a class template specialization -/// or a member class of a class template specialization. -/// -/// \param Pattern is the pattern from which the instantiation -/// occurs. This will be either the declaration of a class template or -/// the declaration of a member class of a class template. -/// -/// \param TemplateArgs The template arguments to be substituted into -/// the pattern. -/// -/// \param TSK the kind of implicit or explicit instantiation to perform. -/// -/// \param Complain whether to complain if the class cannot be instantiated due -/// to the lack of a definition. -/// -/// \returns true if an error occurred, false otherwise. bool Sema::InstantiateClass(SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern, @@ -3754,21 +3657,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, return Instantiation->isInvalidDecl(); } -/// Instantiate the definition of an enum from a given pattern. -/// -/// \param PointOfInstantiation The point of instantiation within the -/// source code. -/// \param Instantiation is the declaration whose definition is being -/// instantiated. This will be a member enumeration of a class -/// temploid specialization, or a local enumeration within a -/// function temploid specialization. -/// \param Pattern The templated declaration from which the instantiation -/// occurs. -/// \param TemplateArgs The template arguments to be substituted into -/// the pattern. -/// \param TSK The kind of implicit or explicit instantiation to perform. -/// -/// \return \c true if an error occurred, \c false otherwise. bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation, EnumDecl *Instantiation, EnumDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -3819,21 +3707,6 @@ bool Sema::InstantiateEnum(SourceLocation PointOfInstantiation, return Instantiation->isInvalidDecl(); } - -/// Instantiate the definition of a field from the given pattern. -/// -/// \param PointOfInstantiation The point of instantiation within the -/// source code. -/// \param Instantiation is the declaration whose definition is being -/// instantiated. This will be a class of a class temploid -/// specialization, or a local enumeration within a function temploid -/// specialization. -/// \param Pattern The templated declaration from which the instantiation -/// occurs. -/// \param TemplateArgs The template arguments to be substituted into -/// the pattern. -/// -/// \return \c true if an error occurred, \c false otherwise. bool Sema::InstantiateInClassInitializer( SourceLocation PointOfInstantiation, FieldDecl *Instantiation, FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs) { @@ -4101,9 +3974,6 @@ bool Sema::InstantiateClassTemplateSpecialization( getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain); } -/// Instantiates the definitions of all of the member -/// of the given class, which is an instantiation of a class template -/// or a member class of a template. void Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, @@ -4333,9 +4203,6 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, } } -/// Instantiate the definitions of all of the members of the -/// given class template specialization, which was named as part of an -/// explicit instantiation. void Sema::InstantiateClassTemplateSpecializationMembers( SourceLocation PointOfInstantiation, @@ -4445,7 +4312,6 @@ Sema::SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, return Instantiator.TransformNestedNameSpecifierLoc(NNS); } -/// Do template substitution on declaration name info. DeclarationNameInfo Sema::SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0681520..64f6b01 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -893,12 +893,6 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, } } -/// Update instantiation attributes after template was late parsed. -/// -/// Some attributes are evaluated based on the body of template. If it is -/// late parsed, such attributes cannot be evaluated when declaration is -/// instantiated. This function is used to update instantiation attributes when -/// template definition is ready. void Sema::updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst) { for (const auto *Attr : Pattern->attrs()) { if (auto *A = dyn_cast<StrictFPAttr>(Attr)) { @@ -909,10 +903,6 @@ void Sema::updateAttrsForLateParsedTemplate(const Decl *Pattern, Decl *Inst) { } } -/// In the MS ABI, we need to instantiate default arguments of dllexported -/// default constructors along with the constructor definition. This allows IR -/// gen to emit a constructor closure which calls the default constructor with -/// its default arguments. void Sema::InstantiateDefaultCtorDefaultArgs(CXXConstructorDecl *Ctor) { assert(Context.getTargetInfo().getCXXABI().isMicrosoft() && Ctor->isDefaultConstructor()); @@ -4548,8 +4538,6 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, return NewTInfo; } -/// Introduce the instantiated local variables into the local -/// instantiation scope. void Sema::addInstantiatedLocalVarsToScope(FunctionDecl *Function, const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope) { @@ -4578,9 +4566,6 @@ void Sema::addInstantiatedLocalVarsToScope(FunctionDecl *Function, } } -/// Introduce the instantiated function parameters into the local -/// instantiation scope, and set the parameter names to those used -/// in the template. bool Sema::addInstantiatedParametersToScope( FunctionDecl *Function, const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope, @@ -4858,11 +4843,6 @@ bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New, return false; } -/// Instantiate (or find existing instantiation of) a function template with a -/// given set of template arguments. -/// -/// Usually this should not be used, and template argument deduction should be -/// used in its place. FunctionDecl *Sema::InstantiateFunctionDeclaration( FunctionTemplateDecl *FTD, const TemplateArgumentList *Args, SourceLocation Loc, CodeSynthesisContext::SynthesisKind CSC) { @@ -4880,23 +4860,6 @@ FunctionDecl *Sema::InstantiateFunctionDeclaration( return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs)); } -/// Instantiate the definition of the given function from its -/// template. -/// -/// \param PointOfInstantiation the point at which the instantiation was -/// required. Note that this is not precisely a "point of instantiation" -/// for the function, but it's close. -/// -/// \param Function the already-instantiated declaration of a -/// function template specialization or member function of a class template -/// specialization. -/// -/// \param Recursive if true, recursively instantiates any functions that -/// are required by this instantiation. -/// -/// \param DefinitionRequired if true, then we are performing an explicit -/// instantiation where the body of the function is required. Complain if -/// there is no such body. void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive, @@ -5275,8 +5238,6 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( VarTemplate, FromVar, TemplateArgsInfo, Converted)); } -/// Instantiates a variable template specialization by completing it -/// with appropriate type information and initializer. VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl, const MultiLevelTemplateArgumentList &TemplateArgs) { @@ -5305,9 +5266,6 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( return VarSpec; } -/// BuildVariableInstantiation - Used after a new variable has been created. -/// Sets basic variable data and decides whether to postpone the -/// variable instantiation. void Sema::BuildVariableInstantiation( VarDecl *NewVar, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -5438,7 +5396,6 @@ void Sema::BuildVariableInstantiation( DiagnoseUnusedDecl(NewVar); } -/// Instantiate the initializer of a variable. void Sema::InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs) { @@ -5508,21 +5465,6 @@ void Sema::InstantiateVariableInitializer( CUDA().checkAllowedInitializer(Var); } -/// Instantiate the definition of the given variable from its -/// template. -/// -/// \param PointOfInstantiation the point at which the instantiation was -/// required. Note that this is not precisely a "point of instantiation" -/// for the variable, but it's close. -/// -/// \param Var the already-instantiated declaration of a templated variable. -/// -/// \param Recursive if true, recursively instantiates any functions that -/// are required by this instantiation. -/// -/// \param DefinitionRequired if true, then we are performing an explicit -/// instantiation where a definition of the variable is required. Complain -/// if there is no such definition. void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive, bool DefinitionRequired, bool AtEndOfTU) { @@ -6089,10 +6031,6 @@ static NamedDecl *findInstantiationOf(ASTContext &Ctx, return nullptr; } -/// Finds the instantiation of the given declaration context -/// within the current instantiation. -/// -/// \returns NULL if there was an error DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, const MultiLevelTemplateArgumentList &TemplateArgs) { if (NamedDecl *D = dyn_cast<NamedDecl>(DC)) { @@ -6115,32 +6053,6 @@ static bool isDependentContextAtLevel(DeclContext *DC, unsigned Level) { return cast<Decl>(DC)->getTemplateDepth() > Level; } -/// Find the instantiation of the given declaration within the -/// current instantiation. -/// -/// This routine is intended to be used when \p D is a declaration -/// referenced from within a template, that needs to mapped into the -/// corresponding declaration within an instantiation. For example, -/// given: -/// -/// \code -/// template<typename T> -/// struct X { -/// enum Kind { -/// KnownValue = sizeof(T) -/// }; -/// -/// bool getKind() const { return KnownValue; } -/// }; -/// -/// template struct X<int>; -/// \endcode -/// -/// In the instantiation of X<int>::getKind(), we need to map the \p -/// EnumConstantDecl for \p KnownValue (which refers to -/// X<T>::<Kind>::KnownValue) to its instantiation (X<int>::<Kind>::KnownValue). -/// \p FindInstantiatedDecl performs this mapping from within the instantiation -/// of X<int>. NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext) { @@ -6440,8 +6352,6 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, return D; } -/// Performs template instantiation for all implicit template -/// instantiations we have seen until this point. void Sema::PerformPendingInstantiations(bool LocalOnly) { std::deque<PendingImplicitInstantiation> delayedPCHInstantiations; while (!PendingLocalImplicitInstantiations.empty() || diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index 7a44b97..6df7f22 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -1010,20 +1010,6 @@ class ParameterPackValidatorCCC final : public CorrectionCandidateCallback { } -/// Called when an expression computing the size of a parameter pack -/// is parsed. -/// -/// \code -/// template<typename ...Types> struct count { -/// static const unsigned value = sizeof...(Types); -/// }; -/// \endcode -/// -// -/// \param OpLoc The location of the "sizeof" keyword. -/// \param Name The name of the parameter pack whose size will be determined. -/// \param NameLoc The source location of the name of the parameter pack. -/// \param RParenLoc The location of the closing parentheses. ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc, IdentifierInfo &Name, diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 3082747..50c15a1 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1649,7 +1649,6 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, return BuildQualifiedType(T, Loc, Q, DS); } -/// Build a paren type including \p T. QualType Sema::BuildParenType(QualType T) { return Context.getParenType(T); } @@ -1780,19 +1779,6 @@ static QualType deduceOpenCLPointeeAddrSpace(Sema &S, QualType PointeeType) { return PointeeType; } -/// Build a pointer type. -/// -/// \param T The type to which we'll be building a pointer. -/// -/// \param Loc The location of the entity whose type involves this -/// pointer type or, if there is no such entity, the location of the -/// type that will have pointer type. -/// -/// \param Entity The name of the entity that involves the pointer -/// type, if known. -/// -/// \returns A suitable pointer type, if there are no -/// errors. Otherwise, returns a NULL type. QualType Sema::BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity) { if (T->isReferenceType()) { @@ -1845,19 +1831,6 @@ QualType Sema::BuildPointerType(QualType T, return Context.getPointerType(T); } -/// Build a reference type. -/// -/// \param T The type to which we'll be building a reference. -/// -/// \param Loc The location of the entity whose type involves this -/// reference type or, if there is no such entity, the location of the -/// type that will have reference type. -/// -/// \param Entity The name of the entity that involves the reference -/// type, if known. -/// -/// \returns A suitable reference type, if there are no -/// errors. Otherwise, returns a NULL type. QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, SourceLocation Loc, DeclarationName Entity) { @@ -1933,38 +1906,14 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, return Context.getRValueReferenceType(T); } -/// Build a Read-only Pipe type. -/// -/// \param T The type to which we'll be building a Pipe. -/// -/// \param Loc We do not use it for now. -/// -/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a -/// NULL type. QualType Sema::BuildReadPipeType(QualType T, SourceLocation Loc) { return Context.getReadPipeType(T); } -/// Build a Write-only Pipe type. -/// -/// \param T The type to which we'll be building a Pipe. -/// -/// \param Loc We do not use it for now. -/// -/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a -/// NULL type. QualType Sema::BuildWritePipeType(QualType T, SourceLocation Loc) { return Context.getWritePipeType(T); } -/// Build a bit-precise integer type. -/// -/// \param IsUnsigned Boolean representing the signedness of the type. -/// -/// \param BitWidth Size of this int type in bits, or an expression representing -/// that. -/// -/// \param Loc Location of the keyword. QualType Sema::BuildBitIntType(bool IsUnsigned, Expr *BitWidth, SourceLocation Loc) { if (BitWidth->isInstantiationDependent()) @@ -2073,21 +2022,6 @@ bool Sema::checkArrayElementAlignment(QualType EltTy, SourceLocation Loc) { return false; } -/// Build an array type. -/// -/// \param T The type of each element in the array. -/// -/// \param ASM C99 array size modifier (e.g., '*', 'static'). -/// -/// \param ArraySize Expression describing the size of the array. -/// -/// \param Brackets The range from the opening '[' to the closing ']'. -/// -/// \param Entity The name of the entity that involves the array -/// type, if known. -/// -/// \returns A suitable array type, if there are no errors. Otherwise, -/// returns a NULL type. QualType Sema::BuildArrayType(QualType T, ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, SourceRange Brackets, DeclarationName Entity) { @@ -2427,9 +2361,6 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, VectorKind::Generic); } -/// Build an ext-vector type. -/// -/// Run the required checks for the extended vector type. QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc) { // Unlike gcc's vector_size attribute, we do not allow vectors to be defined @@ -2718,15 +2649,6 @@ QualType Sema::BuildFunctionType(QualType T, return Context.getFunctionType(T, ParamTypes, EPI); } -/// Build a member pointer type \c T Class::*. -/// -/// \param T the type to which the member pointer refers. -/// \param Class the class type into which the member pointer points. -/// \param Loc the location where this type begins -/// \param Entity the name of the entity that will have this member pointer type -/// -/// \returns a member pointer type, if successful, or a NULL type if there was -/// an error. QualType Sema::BuildMemberPointerType(QualType T, QualType Class, SourceLocation Loc, DeclarationName Entity) { @@ -2779,17 +2701,6 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, return Context.getMemberPointerType(T, Class.getTypePtr()); } -/// Build a block pointer type. -/// -/// \param T The type to which we'll be building a block pointer. -/// -/// \param Loc The source location, used for diagnostics. -/// -/// \param Entity The name of the entity that involves the block pointer -/// type, if known. -/// -/// \returns A suitable block pointer type, if there are no -/// errors. Otherwise, returns a NULL type. QualType Sema::BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity) { @@ -5675,11 +5586,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, return GetTypeSourceInfoForDeclarator(state, T, TInfo); } -/// GetTypeForDeclarator - Convert the type for the specified -/// declarator to Type instances. -/// -/// The result of this call will never be null, but the associated -/// type may be a null type if there's an unrecoverable error. TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D) { // Determine the type of the declarator. Not all forms of declarator // have a type. @@ -6460,10 +6366,6 @@ static bool BuildAddressSpaceIndex(Sema &S, LangAS &ASIdx, return true; } -/// BuildAddressSpaceAttr - Builds a DependentAddressSpaceType if an expression -/// is uninstantiated. If instantiated it will apply the appropriate address -/// space to the type. This function allows dependent template variables to be -/// used in conjunction with the address_space attribute QualType Sema::BuildAddressSpaceAttr(QualType &T, LangAS ASIdx, Expr *AddrSpace, SourceLocation AttrLoc) { if (!AddrSpace->isValueDependent()) { @@ -8914,21 +8816,6 @@ QualType Sema::getCompletedType(Expr *E) { return E->getType(); } -/// Ensure that the type of the given expression is complete. -/// -/// This routine checks whether the expression \p E has a complete type. If the -/// expression refers to an instantiable construct, that instantiation is -/// performed as needed to complete its type. Furthermore -/// Sema::RequireCompleteType is called for the expression's type (or in the -/// case of a reference type, the referred-to type). -/// -/// \param E The expression whose type is required to be complete. -/// \param Kind Selects which completeness rules should be applied. -/// \param Diagnoser The object that will emit a diagnostic if the type is -/// incomplete. -/// -/// \returns \c true if the type of \p E is incomplete and diagnosed, \c false -/// otherwise. bool Sema::RequireCompleteExprType(Expr *E, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser) { return RequireCompleteType(E->getExprLoc(), getCompletedType(E), Kind, @@ -8940,25 +8827,6 @@ bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) { return RequireCompleteExprType(E, CompleteTypeKind::Default, Diagnoser); } -/// Ensure that the type T is a complete type. -/// -/// This routine checks whether the type @p T is complete in any -/// context where a complete type is required. If @p T is a complete -/// type, returns false. If @p T is a class template specialization, -/// this routine then attempts to perform class template -/// instantiation. If instantiation fails, or if @p T is incomplete -/// and cannot be completed, issues the diagnostic @p diag (giving it -/// the type @p T) and returns true. -/// -/// @param Loc The location in the source that the incomplete type -/// diagnostic should refer to. -/// -/// @param T The type that this routine is examining for completeness. -/// -/// @param Kind Selects which completeness rules should be applied. -/// -/// @returns @c true if @p T is incomplete and a diagnostic was emitted, -/// @c false otherwise. bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser) { @@ -9135,7 +9003,6 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) { } } -/// The implementation of RequireCompleteType bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser *Diagnoser) { @@ -9327,24 +9194,6 @@ static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) { } } -/// Ensure that the type T is a literal type. -/// -/// This routine checks whether the type @p T is a literal type. If @p T is an -/// incomplete type, an attempt is made to complete it. If @p T is a literal -/// type, or @p AllowIncompleteType is true and @p T is an incomplete type, -/// returns false. Otherwise, this routine issues the diagnostic @p PD (giving -/// it the type @p T), along with notes explaining why the type is not a -/// literal type, and returns true. -/// -/// @param Loc The location in the source that the non-literal type -/// diagnostic should refer to. -/// -/// @param T The type that this routine is examining for literalness. -/// -/// @param Diagnoser Emits a diagnostic if T is not a literal type. -/// -/// @returns @c true if @p T is not a literal type and a diagnostic was emitted, -/// @c false otherwise. bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, TypeDiagnoser &Diagnoser) { assert(!T->isDependentType() && "type should not be dependent"); @@ -9441,9 +9290,6 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) { return RequireLiteralType(Loc, T, Diagnoser); } -/// Retrieve a version of the type 'T' that is elaborated by Keyword, qualified -/// by the nested-name-specifier contained in SS, and that is (re)declared by -/// OwnedTagDecl, which is nullptr if this is not a (re)declaration. QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword, const CXXScopeSpec &SS, QualType T, TagDecl *OwnedTagDecl) { |