diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/clang/AST/Expr.h | 3 | ||||
| -rw-r--r-- | include/clang/Basic/Attr.td | 27 | ||||
| -rw-r--r-- | include/clang/Basic/AttrDocs.td | 59 | ||||
| -rw-r--r-- | include/clang/Basic/DiagnosticCommonKinds.td | 2 | ||||
| -rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 4 | ||||
| -rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 15 | ||||
| -rw-r--r-- | include/clang/Basic/LangOptions.def | 1 | ||||
| -rw-r--r-- | include/clang/Driver/CC1Options.td | 3 | ||||
| -rw-r--r-- | include/clang/Frontend/CodeGenOptions.def | 1 | ||||
| -rw-r--r-- | include/clang/Frontend/FrontendActions.h | 2 | ||||
| -rw-r--r-- | include/clang/Index/IndexSymbol.h | 9 | ||||
| -rw-r--r-- | include/clang/Sema/Initialization.h | 4 | ||||
| -rw-r--r-- | include/clang/Sema/Overload.h | 141 | ||||
| -rw-r--r-- | include/clang/Sema/Sema.h | 120 | ||||
| -rw-r--r-- | include/clang/StaticAnalyzer/Checkers/Checkers.td | 8 | 
15 files changed, 330 insertions, 69 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 41ae6d2b721e..56b99ccd8971 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -651,7 +651,8 @@ public:    /// constant.    bool EvaluateWithSubstitution(APValue &Value, ASTContext &Ctx,                                  const FunctionDecl *Callee, -                                ArrayRef<const Expr*> Args) const; +                                ArrayRef<const Expr*> Args, +                                const Expr *This = nullptr) const;    /// \brief If the current Expr is a pointer, this will try to statically    /// determine the number of bytes available where the pointer is pointing. diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index e3c2b0e45d3d..fa60d512a6ff 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -140,12 +140,15 @@ class Argument<string name, bit optional, bit fake = 0> {    bit Fake = fake;  } -class BoolArgument<string name, bit opt = 0> : Argument<name, opt>; +class BoolArgument<string name, bit opt = 0, bit fake = 0> : Argument<name, opt, +                                                                      fake>;  class IdentifierArgument<string name, bit opt = 0> : Argument<name, opt>;  class IntArgument<string name, bit opt = 0> : Argument<name, opt>;  class StringArgument<string name, bit opt = 0> : Argument<name, opt>;  class ExprArgument<string name, bit opt = 0> : Argument<name, opt>; -class FunctionArgument<string name, bit opt = 0> : Argument<name, opt>; +class FunctionArgument<string name, bit opt = 0, bit fake = 0> : Argument<name, +                                                                          opt, +                                                                          fake>;  class TypeArgument<string name, bit opt = 0> : Argument<name, opt>;  class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>;  class VariadicUnsignedArgument<string name> : Argument<name, 1>; @@ -1591,6 +1594,26 @@ def Unavailable : InheritableAttr {    let Documentation = [Undocumented];  } +def DiagnoseIf : InheritableAttr { +  let Spellings = [GNU<"diagnose_if">]; +  let Subjects = SubjectList<[Function]>; +  let Args = [ExprArgument<"Cond">, StringArgument<"Message">, +              EnumArgument<"DiagnosticType", +                           "DiagnosticType", +                           ["error", "warning"], +                           ["DT_Error", "DT_Warning"]>, +              BoolArgument<"ArgDependent", 0, /*fake*/ 1>, +              FunctionArgument<"Parent", 0, /*fake*/ 1>]; +  let DuplicatesAllowedWhileMerging = 1; +  let LateParsed = 1; +  let AdditionalMembers = [{ +    bool isError() const { return diagnosticType == DT_Error; } +    bool isWarning() const { return diagnosticType == DT_Warning; } +  }]; +  let TemplateDependent = 1; +  let Documentation = [DiagnoseIfDocs]; +} +  def ArcWeakrefUnavailable : InheritableAttr {    let Spellings = [GNU<"objc_arc_weak_reference_unavailable">];    let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index b57833a15f31..49b0a533cec3 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -378,6 +378,65 @@ template instantiation, so the value for ``T::number`` is known.    }];  } +def DiagnoseIfDocs : Documentation { +  let Category = DocCatFunction; +  let Content = [{ +The ``diagnose_if`` attribute can be placed on function declarations to emit +warnings or errors at compile-time if calls to the attributed function meet +certain user-defined criteria. For example: + +.. code-block:: c +  void abs(int a) +    __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); +  void must_abs(int a) +    __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error"))); + +  int val = abs(1); // warning: Redundant abs call +  int val2 = must_abs(1); // error: Redundant abs call +  int val3 = abs(val); +  int val4 = must_abs(val); // Because run-time checks are not emitted for +                            // diagnose_if attributes, this executes without +                            // issue. + + +``diagnose_if`` is closely related to ``enable_if``, with a few key differences: + +* Overload resolution is not aware of ``diagnose_if`` attributes: they're +  considered only after we select the best candidate from a given candidate set. +* Function declarations that differ only in their ``diagnose_if`` attributes are +  considered to be redeclarations of the same function (not overloads). +* If the condition provided to ``diagnose_if`` cannot be evaluated, no +  diagnostic will be emitted. + +Otherwise, ``diagnose_if`` is essentially the logical negation of ``enable_if``. + +As a result of bullet number two, ``diagnose_if`` attributes will stack on the +same function. For example: + +.. code-block:: c + +  int foo() __attribute__((diagnose_if(1, "diag1", "warning"))); +  int foo() __attribute__((diagnose_if(1, "diag2", "warning"))); + +  int bar = foo(); // warning: diag1 +                   // warning: diag2 +  int (*fooptr)(void) = foo; // warning: diag1 +                             // warning: diag2 + +  constexpr int supportsAPILevel(int N) { return N < 5; } +  int baz(int a) +    __attribute__((diagnose_if(!supportsAPILevel(10), +                               "Upgrade to API level 10 to use baz", "error"))); +  int baz(int a) +    __attribute__((diagnose_if(!a, "0 is not recommended.", "warning"))); + +  int (*bazptr)(int) = baz; // error: Upgrade to API level 10 to use baz +  int v = baz(0); // error: Upgrade to API level 10 to use baz + +Query for this feature with ``__has_attribute(diagnose_if)``. +  }]; +} +  def PassObjectSizeDocs : Documentation {    let Category = DocCatVariable; // Technically it's a parameter doc, but eh.    let Content = [{ diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index e8180eb1db48..af0612a829e1 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -161,6 +161,8 @@ def ext_old_implicitly_unsigned_long_cxx : ExtWarn<    InGroup<CXX11Compat>;  def ext_clang_enable_if : Extension<"'enable_if' is a clang extension">,                            InGroup<GccCompat>; +def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">, +                            InGroup<GccCompat>;  // SEH  def err_seh_expected_handler : Error< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index ba82b36cea31..4173d03de9f0 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -495,6 +495,7 @@ def UnusedPropertyIvar :  DiagGroup<"unused-property-ivar">;  def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;  def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;  def UserDefinedLiterals : DiagGroup<"user-defined-literals">; +def UserDefinedWarnings : DiagGroup<"user-defined-warnings">;  def Reorder : DiagGroup<"reorder">;  def UndeclaredSelector : DiagGroup<"undeclared-selector">;  def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">; @@ -683,7 +684,8 @@ def Most : DiagGroup<"most", [      OverloadedVirtual,      PrivateExtern,      SelTypeCast, -    ExternCCompat +    ExternCCompat, +    UserDefinedWarnings   ]>;  // Thread Safety warnings  diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0807bba45fc4..6a8933f23ecd 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2141,8 +2141,11 @@ def err_constexpr_local_var_no_init : Error<  def ext_constexpr_function_never_constant_expr : ExtWarn<    "constexpr %select{function|constructor}0 never produces a "    "constant expression">, InGroup<DiagGroup<"invalid-constexpr">>, DefaultError; -def err_enable_if_never_constant_expr : Error< -  "'enable_if' attribute expression never produces a constant expression">; +def err_attr_cond_never_constant_expr : Error< +  "%0 attribute expression never produces a constant expression">; +def err_diagnose_if_invalid_diagnostic_type : Error< +  "invalid diagnostic type for 'diagnose_if'; use \"error\" or \"warning\" " +  "instead">;  def err_constexpr_body_no_return : Error<    "no return statement in constexpr function">;  def err_constexpr_return_missing_expr : Error< @@ -3333,6 +3336,9 @@ def note_ovl_candidate : Note<"candidate "  def note_ovl_candidate_inherited_constructor : Note<      "constructor from base class %0 inherited here">; +def note_ovl_candidate_inherited_constructor_slice : Note< +    "constructor inherited from base class cannot be used to initialize from " +    "an argument of the derived class type">;  def note_ovl_candidate_illegal_constructor : Note<      "candidate %select{constructor|template}0 ignored: "      "instantiation %select{takes|would take}0 its own class type by value">; @@ -3366,7 +3372,9 @@ def note_ovl_candidate_disabled_by_enable_if : Note<  def note_ovl_candidate_has_pass_object_size_params: Note<      "candidate address cannot be taken because parameter %0 has "      "pass_object_size attribute">; -def note_ovl_candidate_disabled_by_enable_if_attr : Note< +def err_diagnose_if_succeeded : Error<"%0">; +def warn_diagnose_if_succeeded : Warning<"%0">, InGroup<UserDefinedWarnings>; +def note_ovl_candidate_disabled_by_function_cond_attr : Note<      "candidate disabled: %0">;  def note_ovl_candidate_disabled_by_extension : Note<      "candidate disabled due to OpenCL extension">; @@ -4395,6 +4403,7 @@ def note_not_found_by_two_phase_lookup : Note<"%0 should be declared prior to th  def err_undeclared_use : Error<"use of undeclared %0">;  def warn_deprecated : Warning<"%0 is deprecated">,      InGroup<DeprecatedDeclarations>; +def note_from_diagnose_if : Note<"from 'diagnose_if' attribute on %0:">;  def warn_property_method_deprecated :      Warning<"property access is using %0 method which is deprecated">,      InGroup<DeprecatedDeclarations>; diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 47db50c52b74..d944a9d78ab9 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -146,6 +146,7 @@ LANGOPT(Modules           , 1, 0, "modules extension to C")  COMPATIBLE_LANGOPT(ModulesTS  , 1, 0, "C++ Modules TS")  BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None,                      "compiling a module interface") +BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch")  COMPATIBLE_LANGOPT(ModulesDeclUse    , 1, 0, "require declaration of module uses")  BENIGN_LANGOPT(ModulesSearchAll  , 1, 1, "searching even non-imported modules to find unresolved references")  COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules") diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 2910b8521bab..ab296ebb9f6a 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -167,6 +167,9 @@ def disable_llvm_passes : Flag<["-"], "disable-llvm-passes">,             "frontend by not running any LLVM passes at all">;  def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,    Alias<disable_llvm_passes>; +def disable_lifetimemarkers : Flag<["-"], "disable-lifetime-markers">, +  HelpText<"Disable lifetime-markers emission even when optimizations are " +           "enabled">;  def disable_red_zone : Flag<["-"], "disable-red-zone">,    HelpText<"Do not emit code that uses the red zone.">;  def dwarf_column_info : Flag<["-"], "dwarf-column-info">, diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 54c9f81265a6..964a6cc2a007 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -52,6 +52,7 @@ CODEGENOPT(DisableGCov       , 1, 0) ///< Don't run the GCov pass, for testing.  CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get                                       ///< the pristine IR generated by the                                       ///< frontend. +CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers  CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental                                               ///< pass manager.  CODEGENOPT(DisableRedZone    , 1, 0) ///< Set when -mno-red-zone is enabled. diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index a073ca5bfd2a..20fddc4d5a52 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -88,6 +88,8 @@ public:    static std::unique_ptr<raw_pwrite_stream>    ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile,                                std::string &Sysroot, std::string &OutputFile); + +  bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override;  };  class GenerateModuleAction : public ASTFrontendAction { diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index cac0b53a939e..559b212b9266 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -59,6 +59,13 @@ enum class SymbolLanguage {    CXX,  }; +/// Language specific sub-kinds. +enum class SymbolSubKind { +  None, +  CXXCopyConstructor, +  CXXMoveConstructor, +}; +  /// Set of properties that provide additional info about a symbol.  enum class SymbolProperty : uint8_t {    Generic                       = 1 << 0, @@ -107,6 +114,7 @@ struct SymbolRelation {  struct SymbolInfo {    SymbolKind Kind; +  SymbolSubKind SubKind;    SymbolPropertySet Properties;    SymbolLanguage Lang;  }; @@ -121,6 +129,7 @@ void printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS);  bool printSymbolName(const Decl *D, const LangOptions &LO, raw_ostream &OS);  StringRef getSymbolKindString(SymbolKind K); +StringRef getSymbolSubKindString(SymbolSubKind K);  StringRef getSymbolLanguageString(SymbolLanguage K);  void applyForEachSymbolProperty(SymbolPropertySet Props, diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index a7b8cce32691..94be58ac8aeb 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -215,14 +215,14 @@ public:    /// \brief Create the initialization entity for a parameter.    static InitializedEntity InitializeParameter(ASTContext &Context, -                                               ParmVarDecl *Parm) { +                                               const ParmVarDecl *Parm) {      return InitializeParameter(Context, Parm, Parm->getType());    }    /// \brief Create the initialization entity for a parameter, but use    /// another type.    static InitializedEntity InitializeParameter(ASTContext &Context, -                                               ParmVarDecl *Parm, +                                               const ParmVarDecl *Parm,                                                 QualType Type) {      bool Consumed = (Context.getLangOpts().ObjCAutoRefCount &&                       Parm->hasAttr<NSConsumedAttr>()); diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 376db92d03bd..88fdc991f394 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -531,6 +531,13 @@ namespace clang {        Ambiguous.construct();      } +    void setAsIdentityConversion(QualType T) { +      setStandard(); +      Standard.setAsIdentityConversion(); +      Standard.setFromType(T); +      Standard.setAllToTypes(T); +    } +      /// \brief Whether the target is really a std::initializer_list, and the      /// sequence only represents the worst element conversion.      bool isStdInitializerListElement() const { @@ -601,8 +608,17 @@ namespace clang {      /// This candidate was not viable because its OpenCL extension is disabled.      ovl_fail_ext_disabled, + +    /// This inherited constructor is not viable because it would slice the +    /// argument. +    ovl_fail_inhctor_slice,    }; +  /// A list of implicit conversion sequences for the arguments of an +  /// OverloadCandidate. +  typedef llvm::MutableArrayRef<ImplicitConversionSequence> +      ConversionSequenceList; +    /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).    struct OverloadCandidate {      /// Function - The actual function that this candidate @@ -627,18 +643,13 @@ namespace clang {      /// is a surrogate, but only if IsSurrogate is true.      CXXConversionDecl *Surrogate; -    /// Conversions - The conversion sequences used to convert the -    /// function arguments to the function parameters, the pointer points to a -    /// fixed size array with NumConversions elements. The memory is owned by -    /// the OverloadCandidateSet. -    ImplicitConversionSequence *Conversions; +    /// The conversion sequences used to convert the function arguments +    /// to the function parameters. +    ConversionSequenceList Conversions;      /// The FixIt hints which can be used to fix the Bad candidate.      ConversionFixItGenerator Fix; -    /// NumConversions - The number of elements in the Conversions array. -    unsigned NumConversions; -      /// Viable - True to indicate that this overload candidate is viable.      bool Viable; @@ -664,6 +675,26 @@ namespace clang {      /// to be used while performing partial ordering of function templates.      unsigned ExplicitCallArguments; +    /// The number of diagnose_if attributes that this overload triggered. +    /// If any of the triggered attributes are errors, this won't count +    /// diagnose_if warnings. +    unsigned NumTriggeredDiagnoseIfs = 0; + +    /// Basically a TinyPtrVector<DiagnoseIfAttr *> that doesn't own the vector: +    /// If NumTriggeredDiagnoseIfs is 0 or 1, this is a DiagnoseIfAttr *, +    /// otherwise it's a pointer to an array of `NumTriggeredDiagnoseIfs` +    /// DiagnoseIfAttr *s. +    llvm::PointerUnion<DiagnoseIfAttr *, DiagnoseIfAttr **> DiagnoseIfInfo; + +    /// Gets an ArrayRef for the data at DiagnoseIfInfo. Note that this may give +    /// you a pointer into DiagnoseIfInfo. +    ArrayRef<DiagnoseIfAttr *> getDiagnoseIfInfo() const { +      auto *Ptr = NumTriggeredDiagnoseIfs <= 1 +                      ? DiagnoseIfInfo.getAddrOfPtr1() +                      : DiagnoseIfInfo.get<DiagnoseIfAttr **>(); +      return {Ptr, NumTriggeredDiagnoseIfs}; +    } +      union {        DeductionFailureInfo DeductionFailure; @@ -677,9 +708,9 @@ namespace clang {      /// hasAmbiguousConversion - Returns whether this overload      /// candidate requires an ambiguous conversion or not.      bool hasAmbiguousConversion() const { -      for (unsigned i = 0, e = NumConversions; i != e; ++i) { -        if (!Conversions[i].isInitialized()) return false; -        if (Conversions[i].isAmbiguous()) return true; +      for (auto &C : Conversions) { +        if (!C.isInitialized()) return false; +        if (C.isAmbiguous()) return true;        }        return false;      } @@ -728,17 +759,42 @@ namespace clang {      SmallVector<OverloadCandidate, 16> Candidates;      llvm::SmallPtrSet<Decl *, 16> Functions; -    // Allocator for OverloadCandidate::Conversions. We store the first few -    // elements inline to avoid allocation for small sets. -    llvm::BumpPtrAllocator ConversionSequenceAllocator; +    // Allocator for ConversionSequenceLists and DiagnoseIfAttr* arrays. +    // We store the first few of each of these inline to avoid allocation for +    // small sets. +    llvm::BumpPtrAllocator SlabAllocator;      SourceLocation Loc;      CandidateSetKind Kind; -    unsigned NumInlineSequences; -    llvm::AlignedCharArray<alignof(ImplicitConversionSequence), -                           16 * sizeof(ImplicitConversionSequence)> -        InlineSpace; +    constexpr static unsigned NumInlineBytes = +        24 * sizeof(ImplicitConversionSequence); +    unsigned NumInlineBytesUsed; +    llvm::AlignedCharArray<alignof(void *), NumInlineBytes> InlineSpace; + +    /// If we have space, allocates from inline storage. Otherwise, allocates +    /// from the slab allocator. +    /// FIXME: It would probably be nice to have a SmallBumpPtrAllocator +    /// instead. +    template <typename T> +    T *slabAllocate(unsigned N) { +      // It's simpler if this doesn't need to consider alignment. +      static_assert(alignof(T) == alignof(void *), +                    "Only works for pointer-aligned types."); +      static_assert(std::is_trivial<T>::value || +                        std::is_same<ImplicitConversionSequence, T>::value, +                    "Add destruction logic to OverloadCandidateSet::clear()."); + +      unsigned NBytes = sizeof(T) * N; +      if (NBytes > NumInlineBytes - NumInlineBytesUsed) +        return SlabAllocator.Allocate<T>(N); +      char *FreeSpaceStart = InlineSpace.buffer + NumInlineBytesUsed; +      assert(uintptr_t(FreeSpaceStart) % alignof(void *) == 0 && +             "Misaligned storage!"); + +      NumInlineBytesUsed += NBytes; +      return reinterpret_cast<T *>(FreeSpaceStart); +    }      OverloadCandidateSet(const OverloadCandidateSet &) = delete;      void operator=(const OverloadCandidateSet &) = delete; @@ -747,12 +803,17 @@ namespace clang {    public:      OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK) -        : Loc(Loc), Kind(CSK), NumInlineSequences(0) {} +        : Loc(Loc), Kind(CSK), NumInlineBytesUsed(0) {}      ~OverloadCandidateSet() { destroyCandidates(); }      SourceLocation getLocation() const { return Loc; }      CandidateSetKind getKind() const { return Kind; } +    /// Make a DiagnoseIfAttr* array in a block of memory that will live for +    /// as long as this OverloadCandidateSet. Returns a pointer to the start +    /// of that array. +    DiagnoseIfAttr **addDiagnoseIfComplaints(ArrayRef<DiagnoseIfAttr *> CA); +      /// \brief Determine when this overload candidate will be new to the      /// overload set.      bool isNewCandidate(Decl *F) { @@ -769,30 +830,32 @@ namespace clang {      size_t size() const { return Candidates.size(); }      bool empty() const { return Candidates.empty(); } +    /// \brief Allocate storage for conversion sequences for NumConversions +    /// conversions. +    ConversionSequenceList +    allocateConversionSequences(unsigned NumConversions) { +      ImplicitConversionSequence *Conversions = +          slabAllocate<ImplicitConversionSequence>(NumConversions); + +      // Construct the new objects. +      for (unsigned I = 0; I != NumConversions; ++I) +        new (&Conversions[I]) ImplicitConversionSequence(); + +      return ConversionSequenceList(Conversions, NumConversions); +    } +      /// \brief Add a new candidate with NumConversions conversion sequence slots      /// to the overload set. -    OverloadCandidate &addCandidate(unsigned NumConversions = 0) { +    OverloadCandidate &addCandidate(unsigned NumConversions = 0, +                                    ConversionSequenceList Conversions = None) { +      assert((Conversions.empty() || Conversions.size() == NumConversions) && +             "preallocated conversion sequence has wrong length"); +        Candidates.push_back(OverloadCandidate());        OverloadCandidate &C = Candidates.back(); - -      // Assign space from the inline array if there are enough free slots -      // available. -      if (NumConversions + NumInlineSequences <= 16) { -        ImplicitConversionSequence *I = -            (ImplicitConversionSequence *)InlineSpace.buffer; -        C.Conversions = &I[NumInlineSequences]; -        NumInlineSequences += NumConversions; -      } else { -        // Otherwise get memory from the allocator. -        C.Conversions = ConversionSequenceAllocator -                          .Allocate<ImplicitConversionSequence>(NumConversions); -      } - -      // Construct the new objects. -      for (unsigned i = 0; i != NumConversions; ++i) -        new (&C.Conversions[i]) ImplicitConversionSequence(); - -      C.NumConversions = NumConversions; +      C.Conversions = Conversions.empty() +                          ? allocateConversionSequences(NumConversions) +                          : Conversions;        return C;      } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index ca984a360a60..d5e4b069f8b7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -27,6 +27,7 @@  #include "clang/AST/NSAPI.h"  #include "clang/AST/PrettyPrinter.h"  #include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeOrdering.h"  #include "clang/Basic/ExpressionTraits.h"  #include "clang/Basic/LangOptions.h"  #include "clang/Basic/Module.h" @@ -119,6 +120,7 @@ namespace clang {    class FunctionProtoType;    class FunctionTemplateDecl;    class ImplicitConversionSequence; +  typedef MutableArrayRef<ImplicitConversionSequence> ConversionSequenceList;    class InitListExpr;    class InitializationKind;    class InitializationSequence; @@ -806,6 +808,12 @@ public:      /// run time.      Unevaluated, +    /// \brief The current expression occurs within a braced-init-list within +    /// an unevaluated operand. This is mostly like a regular unevaluated +    /// context, except that we still instantiate constexpr functions that are +    /// referenced here so that we can perform narrowing checks correctly. +    UnevaluatedList, +      /// \brief The current expression occurs within a discarded statement.      /// This behaves largely similarly to an unevaluated operand in preventing      /// definitions from being required, but not in other ways. @@ -898,7 +906,8 @@ public:      MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx);      bool isUnevaluated() const { -      return Context == Unevaluated || Context == UnevaluatedAbstract; +      return Context == Unevaluated || Context == UnevaluatedAbstract || +             Context == UnevaluatedList;      }    }; @@ -2510,10 +2519,11 @@ public:    void AddOverloadCandidate(FunctionDecl *Function,                              DeclAccessPair FoundDecl,                              ArrayRef<Expr *> Args, -                            OverloadCandidateSet& CandidateSet, +                            OverloadCandidateSet &CandidateSet,                              bool SuppressUserConversions = false,                              bool PartialOverloading = false, -                            bool AllowExplicit = false); +                            bool AllowExplicit = false, +                            ConversionSequenceList EarlyConversions = None);    void AddFunctionCandidates(const UnresolvedSetImpl &Functions,                        ArrayRef<Expr *> Args,                        OverloadCandidateSet &CandidateSet, @@ -2523,23 +2533,25 @@ public:    void AddMethodCandidate(DeclAccessPair FoundDecl,                            QualType ObjectType,                            Expr::Classification ObjectClassification, -                          ArrayRef<Expr *> Args, +                          Expr *ThisArg, ArrayRef<Expr *> Args,                            OverloadCandidateSet& CandidateSet,                            bool SuppressUserConversion = false);    void AddMethodCandidate(CXXMethodDecl *Method,                            DeclAccessPair FoundDecl,                            CXXRecordDecl *ActingContext, QualType ObjectType,                            Expr::Classification ObjectClassification, -                          ArrayRef<Expr *> Args, +                          Expr *ThisArg, ArrayRef<Expr *> Args,                            OverloadCandidateSet& CandidateSet,                            bool SuppressUserConversions = false, -                          bool PartialOverloading = false); +                          bool PartialOverloading = false, +                          ConversionSequenceList EarlyConversions = None);    void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,                                    DeclAccessPair FoundDecl,                                    CXXRecordDecl *ActingContext,                                   TemplateArgumentListInfo *ExplicitTemplateArgs,                                    QualType ObjectType,                                    Expr::Classification ObjectClassification, +                                  Expr *ThisArg,                                    ArrayRef<Expr *> Args,                                    OverloadCandidateSet& CandidateSet,                                    bool SuppressUserConversions = false, @@ -2551,6 +2563,16 @@ public:                                      OverloadCandidateSet& CandidateSet,                                      bool SuppressUserConversions = false,                                      bool PartialOverloading = false); +  bool CheckNonDependentConversions(FunctionTemplateDecl *FunctionTemplate, +                                    ArrayRef<QualType> ParamTypes, +                                    ArrayRef<Expr *> Args, +                                    OverloadCandidateSet &CandidateSet, +                                    ConversionSequenceList &Conversions, +                                    bool SuppressUserConversions, +                                    CXXRecordDecl *ActingContext = nullptr, +                                    QualType ObjectType = QualType(), +                                    Expr::Classification +                                        ObjectClassification = {});    void AddConversionCandidate(CXXConversionDecl *Conversion,                                DeclAccessPair FoundDecl,                                CXXRecordDecl *ActingContext, @@ -2603,6 +2625,38 @@ public:    EnableIfAttr *CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args,                                bool MissingImplicitThis = false); +  /// Check the diagnose_if attributes on the given function. Returns the +  /// first succesful fatal attribute, or null if calling Function(Args) isn't +  /// an error. +  /// +  /// This only considers ArgDependent DiagnoseIfAttrs. +  /// +  /// This will populate Nonfatal with all non-error DiagnoseIfAttrs that +  /// succeed. If this function returns non-null, the contents of Nonfatal are +  /// unspecified. +  DiagnoseIfAttr * +  checkArgDependentDiagnoseIf(FunctionDecl *Function, ArrayRef<Expr *> Args, +                              SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal, +                              bool MissingImplicitThis = false, +                              Expr *ThisArg = nullptr); + +  /// Check the diagnose_if expressions on the given function. Returns the +  /// first succesful fatal attribute, or null if using Function isn't +  /// an error. +  /// +  /// This ignores all ArgDependent DiagnoseIfAttrs. +  /// +  /// This will populate Nonfatal with all non-error DiagnoseIfAttrs that +  /// succeed. If this function returns non-null, the contents of Nonfatal are +  /// unspecified. +  DiagnoseIfAttr * +  checkArgIndependentDiagnoseIf(FunctionDecl *Function, +                                SmallVectorImpl<DiagnoseIfAttr *> &Nonfatal); + +  /// Emits the diagnostic contained in the given DiagnoseIfAttr at Loc. Also +  /// emits a note about the location of said attribute. +  void emitDiagnoseIfDiagnostic(SourceLocation Loc, const DiagnoseIfAttr *DIA); +    /// Returns whether the given function's address can be taken or not,    /// optionally emitting a diagnostic if the address can't be taken.    /// @@ -3801,6 +3855,9 @@ public:    /// variable will have in the given scope.    QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); +  /// Mark all of the declarations referenced within a particular AST node as +  /// referenced. Used when template instantiation instantiates a non-dependent +  /// type -- entities referenced by the type are now referenced.    void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);    void MarkDeclarationsReferencedInExpr(Expr *E,                                          bool SkipLocalVariables = false); @@ -6580,6 +6637,8 @@ public:      /// \brief The explicitly-specified template arguments were not valid      /// template arguments for the given template.      TDK_InvalidExplicitArguments, +    /// \brief Checking non-dependent argument conversions failed. +    TDK_NonDependentConversionFailure,      /// \brief Deduction failed; that's all we know.      TDK_MiscellaneousDeductionFailure,      /// \brief CUDA Target attributes do not match. @@ -6618,22 +6677,21 @@ public:      QualType OriginalArgType;    }; -  TemplateDeductionResult -  FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, -                      SmallVectorImpl<DeducedTemplateArgument> &Deduced, -                                  unsigned NumExplicitlySpecified, -                                  FunctionDecl *&Specialization, -                                  sema::TemplateDeductionInfo &Info, -           SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr, -                                  bool PartialOverloading = false); +  TemplateDeductionResult FinishTemplateArgumentDeduction( +      FunctionTemplateDecl *FunctionTemplate, +      SmallVectorImpl<DeducedTemplateArgument> &Deduced, +      unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, +      sema::TemplateDeductionInfo &Info, +      SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr, +      bool PartialOverloading = false, +      llvm::function_ref<bool()> CheckNonDependent = []{ return false; }); -  TemplateDeductionResult -  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, -                          TemplateArgumentListInfo *ExplicitTemplateArgs, -                          ArrayRef<Expr *> Args, -                          FunctionDecl *&Specialization, -                          sema::TemplateDeductionInfo &Info, -                          bool PartialOverloading = false); +  TemplateDeductionResult DeduceTemplateArguments( +      FunctionTemplateDecl *FunctionTemplate, +      TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, +      FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, +      bool PartialOverloading, +      llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent);    TemplateDeductionResult    DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, @@ -6877,6 +6935,10 @@ public:    /// Specializations whose definitions are currently being instantiated.    llvm::DenseSet<std::pair<Decl *, unsigned>> InstantiatingSpecializations; +  /// Non-dependent types used in templates that have already been instantiated +  /// by some template instantiation. +  llvm::DenseSet<QualType> InstantiatedNonDependentTypes; +    /// \brief Extra modules inspected when performing a lookup during a template    /// instantiation. Computed lazily.    SmallVector<Module*, 16> ActiveTemplateInstantiationLookupModules; @@ -10186,6 +10248,22 @@ public:                                              IsDecltype);    } +  enum InitListTag { InitList }; +  EnterExpressionEvaluationContext(Sema &Actions, InitListTag, +                                   bool ShouldEnter = true) +      : Actions(Actions), Entered(false) { +    // In C++11 onwards, narrowing checks are performed on the contents of +    // braced-init-lists, even when they occur within unevaluated operands. +    // Therefore we still need to instantiate constexpr functions used in such +    // a context. +    if (ShouldEnter && Actions.isUnevaluatedContext() && +        Actions.getLangOpts().CPlusPlus11) { +      Actions.PushExpressionEvaluationContext(Sema::UnevaluatedList, nullptr, +                                              false); +      Entered = true; +    } +  } +    ~EnterExpressionEvaluationContext() {      if (Entered)        Actions.PopExpressionEvaluationContext(); diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index 2e58debf80fc..69578910499f 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -278,6 +278,14 @@ def VirtualCallChecker : Checker<"VirtualCall">,  } // end: "optin.cplusplus" +let ParentPackage = CplusplusAlpha in { + +def IteratorPastEndChecker : Checker<"IteratorPastEnd">, +  HelpText<"Check iterators used past end">, +  DescFile<"IteratorPastEndChecker.cpp">; + +} // end: "alpha.cplusplus" +  //===----------------------------------------------------------------------===//  // Valist checkers.  | 
