1f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- C++ -*-===//
2f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
3f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//                     The LLVM Compiler Infrastructure
4f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
5f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// This file is distributed under the University of Illinois Open Source
6f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot// License. See LICENSE.TXT for details.
7f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//
8f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
9f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot///
10f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// \file
11f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// \brief Implements a partial diagnostic that can be emitted anwyhere
12f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// in a DiagnosticBuilder stream.
13f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot///
14f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot//===----------------------------------------------------------------------===//
15f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
16f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
17f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H
18f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
19f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "clang/Basic/Diagnostic.h"
20f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "clang/Basic/SourceLocation.h"
21f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/ADT/STLExtras.h"
22f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/Support/Compiler.h"
23f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include "llvm/Support/DataTypes.h"
24f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#include <cassert>
25f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
26f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotnamespace clang {
27f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
28f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotclass PartialDiagnostic {
29f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
30f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  enum {
31f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      // The MaxArguments and MaxFixItHints member enum values from
32f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      // DiagnosticsEngine are private but DiagnosticsEngine declares
33f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      // PartialDiagnostic a friend.  These enum values are redeclared
34f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      // here so that the nested Storage class below can access them.
35f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      MaxArguments = DiagnosticsEngine::MaxArguments
36f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  };
37f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
38f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  struct Storage {
39f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Storage() : NumDiagArgs(0) { }
40f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
41f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    enum {
42f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        /// \brief The maximum number of arguments we can hold. We
43f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        /// currently only support up to 10 arguments (%0-%9).
44f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        ///
45f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        /// A single diagnostic with more than that almost certainly has to
46f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        /// be simplified anyway.
47f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        MaxArguments = PartialDiagnostic::MaxArguments
48f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    };
49f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
50f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief The number of entries in Arguments.
51f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned char NumDiagArgs;
52f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
53f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief Specifies for each argument whether it is in DiagArgumentsStr
54f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// or in DiagArguments.
55f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned char DiagArgumentsKind[MaxArguments];
56f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
57f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief The values for the various substitution positions.
58f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ///
59f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// This is used when the argument is not an std::string. The specific value
60f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// is mangled into an intptr_t and the interpretation depends on exactly
61f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// what sort of argument kind it is.
62f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    intptr_t DiagArgumentsVal[MaxArguments];
63f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
64f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief The values for the various substitution positions that have
65f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// string arguments.
66f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    std::string DiagArgumentsStr[MaxArguments];
67f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
68f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief The list of ranges added to this diagnostic.
69f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    SmallVector<CharSourceRange, 8> DiagRanges;
70f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
71f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief If valid, provides a hint with some code to insert, remove, or
72f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// modify at a particular position.
73f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    SmallVector<FixItHint, 6>  FixItHints;
74f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  };
75f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
76f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// \brief An allocator for Storage objects, which uses a small cache to
77f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// objects, used to reduce malloc()/free() traffic for partial diagnostics.
78f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  class StorageAllocator {
79f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    static const unsigned NumCached = 16;
80f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Storage Cached[NumCached];
81f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Storage *FreeList[NumCached];
82f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    unsigned NumFreeListEntries;
83f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
84f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  public:
85f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    StorageAllocator();
86f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    ~StorageAllocator();
87f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
88f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief Allocate new storage.
89f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Storage *Allocate() {
90f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (NumFreeListEntries == 0)
91f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return new Storage;
92f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
93f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Storage *Result = FreeList[--NumFreeListEntries];
94f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Result->NumDiagArgs = 0;
95f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Result->DiagRanges.clear();
96f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Result->FixItHints.clear();
97f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return Result;
98f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
99f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
100f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    /// \brief Free the given storage object.
101f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    void Deallocate(Storage *S) {
102f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (S >= Cached && S <= Cached + NumCached) {
103f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        FreeList[NumFreeListEntries++] = S;
104f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        return;
105f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      }
106f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
107f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      delete S;
108f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
109f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  };
110f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
111f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotprivate:
112f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // NOTE: Sema assumes that PartialDiagnostic is location-invariant
113f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // in the sense that its bits can be safely memcpy'ed and destructed
114f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // in the new location.
115f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
116f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// \brief The diagnostic ID.
117f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  mutable unsigned DiagID;
118f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
119f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// \brief Storage for args and ranges.
120f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  mutable Storage *DiagStorage;
121f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
122f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// \brief Allocator used to allocate storage for this diagnostic.
123f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  StorageAllocator *Allocator;
124f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
125f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// \brief Retrieve storage for this particular diagnostic.
126f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  Storage *getStorage() const {
127f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (DiagStorage)
128f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return DiagStorage;
129f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
130f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Allocator)
131f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DiagStorage = Allocator->Allocate();
132f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    else {
133f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      assert(Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)));
134f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DiagStorage = new Storage;
135f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
136f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return DiagStorage;
137f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
138f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
139f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void freeStorage() {
140f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!DiagStorage)
141f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return;
142f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
143f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // The hot path for PartialDiagnostic is when we just used it to wrap an ID
144f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // (typically so we have the flexibility of passing a more complex
145f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // diagnostic into the callee, but that does not commonly occur).
146f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    //
147f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Split this out into a slow function for silly compilers (*cough*) which
148f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // can't do decent partial inlining.
149f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    freeStorageSlow();
150f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
151f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
152f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void freeStorageSlow() {
153f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Allocator)
154f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Allocator->Deallocate(DiagStorage);
155f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
156f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      delete DiagStorage;
157f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage = nullptr;
158f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
159f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
160f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void AddSourceRange(const CharSourceRange &R) const {
161f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!DiagStorage)
162f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DiagStorage = getStorage();
163f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
164f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage->DiagRanges.push_back(R);
165f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
166f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
167f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void AddFixItHint(const FixItHint &Hint) const {
168f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Hint.isNull())
169f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return;
170f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
171f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!DiagStorage)
172f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DiagStorage = getStorage();
173f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
174f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage->FixItHints.push_back(Hint);
175f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
176f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
177f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotpublic:
178f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  struct NullDiagnostic {};
179f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// \brief Create a null partial diagnostic, which cannot carry a payload,
180f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// and only exists to be swapped with a real partial diagnostic.
181f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic(NullDiagnostic)
182f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : DiagID(0), DiagStorage(nullptr), Allocator(nullptr) { }
183f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
184f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator)
185f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : DiagID(DiagID), DiagStorage(nullptr), Allocator(&Allocator) { }
186f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
187f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic(const PartialDiagnostic &Other)
188f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : DiagID(Other.DiagID), DiagStorage(nullptr), Allocator(Other.Allocator)
189f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  {
190f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Other.DiagStorage) {
191f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DiagStorage = getStorage();
192f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      *DiagStorage = *Other.DiagStorage;
193f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
194f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
195f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
196f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic(PartialDiagnostic &&Other)
197f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage),
198f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Allocator(Other.Allocator) {
199f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Other.DiagStorage = nullptr;
200f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
201f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
202f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage)
203f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : DiagID(Other.DiagID), DiagStorage(DiagStorage),
204f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0)))
205f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  {
206f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Other.DiagStorage)
207f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      *this->DiagStorage = *Other.DiagStorage;
208f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
209f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
210f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator)
211f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    : DiagID(Other.getID()), DiagStorage(nullptr), Allocator(&Allocator)
212f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  {
213f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Copy arguments.
214f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) {
215f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (Other.getArgKind(I) == DiagnosticsEngine::ak_std_string)
216f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        AddString(Other.getArgStdStr(I));
217f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      else
218f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        AddTaggedVal(Other.getRawArg(I), Other.getArgKind(I));
219f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
220f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
221f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Copy source ranges.
222f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for (unsigned I = 0, N = Other.getNumRanges(); I != N; ++I)
223f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      AddSourceRange(Other.getRange(I));
224f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
225f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Copy fix-its.
226f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for (unsigned I = 0, N = Other.getNumFixItHints(); I != N; ++I)
227f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      AddFixItHint(Other.getFixItHint(I));
228f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
229f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
230f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic &operator=(const PartialDiagnostic &Other) {
231f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagID = Other.DiagID;
232f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (Other.DiagStorage) {
233f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if (!DiagStorage)
234f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        DiagStorage = getStorage();
235f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
236f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      *DiagStorage = *Other.DiagStorage;
237f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    } else {
238f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      freeStorage();
239f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
240f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
241f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
242f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
243f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
244f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PartialDiagnostic &operator=(PartialDiagnostic &&Other) {
245f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    freeStorage();
246f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
247f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagID = Other.DiagID;
248f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage = Other.DiagStorage;
249f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Allocator = Other.Allocator;
250f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
251f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Other.DiagStorage = nullptr;
252f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return *this;
253f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
254f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
255f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  ~PartialDiagnostic() {
256f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    freeStorage();
257f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
258f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
259f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void swap(PartialDiagnostic &PD) {
260f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    std::swap(DiagID, PD.DiagID);
261f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    std::swap(DiagStorage, PD.DiagStorage);
262f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    std::swap(Allocator, PD.Allocator);
263f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
264f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
265f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  unsigned getDiagID() const { return DiagID; }
266f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
267f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
268f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!DiagStorage)
269f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DiagStorage = getStorage();
270f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
271f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
272f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           "Too many arguments to diagnostic!");
273f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind;
274f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V;
275f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
276f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
277f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void AddString(StringRef V) const {
278f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!DiagStorage)
279f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DiagStorage = getStorage();
280f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
281f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    assert(DiagStorage->NumDiagArgs < Storage::MaxArguments &&
282f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot           "Too many arguments to diagnostic!");
283f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs]
284f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      = DiagnosticsEngine::ak_std_string;
285f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagStorage->DiagArgumentsStr[DiagStorage->NumDiagArgs++] = V;
286f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
287f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
288f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void Emit(const DiagnosticBuilder &DB) const {
289f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    if (!DiagStorage)
290f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      return;
291f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
292f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Add all arguments.
293f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for (unsigned i = 0, e = DiagStorage->NumDiagArgs; i != e; ++i) {
294f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      if ((DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]
295f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot            == DiagnosticsEngine::ak_std_string)
296f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        DB.AddString(DiagStorage->DiagArgumentsStr[i]);
297f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      else
298f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot        DB.AddTaggedVal(DiagStorage->DiagArgumentsVal[i],
299f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot            (DiagnosticsEngine::ArgumentKind)DiagStorage->DiagArgumentsKind[i]);
300f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    }
301f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
302f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Add all ranges.
303f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for (const CharSourceRange &Range : DiagStorage->DiagRanges)
304f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DB.AddSourceRange(Range);
305f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
306f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // Add all fix-its.
307f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    for (const FixItHint &Fix : DiagStorage->FixItHints)
308f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot      DB.AddFixItHint(Fix);
309f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
310f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
311f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void EmitToString(DiagnosticsEngine &Diags,
312f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                    SmallVectorImpl<char> &Buf) const {
313f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    // FIXME: It should be possible to render a diagnostic to a string without
314f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    //        messing with the state of the diagnostics engine.
315f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DiagnosticBuilder DB(Diags.Report(getDiagID()));
316f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Emit(DB);
317f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DB.FlushCounts();
318f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Diagnostic(&Diags).FormatDiagnostic(Buf);
319f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    DB.Clear();
320f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    Diags.Clear();
321f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
322f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
323f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID
324f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  /// and removing all of its arguments, ranges, and fix-it hints.
325f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  void Reset(unsigned DiagID = 0) {
326f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    this->DiagID = DiagID;
327f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    freeStorage();
328f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
329f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
330f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  bool hasStorage() const { return DiagStorage != nullptr; }
331f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
332f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
333f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                             unsigned I) {
334f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
335f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
336f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
337f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
338f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
339f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                             int I) {
340f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
341f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
342f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
343f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
344f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
345f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                                    const char *S) {
346f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddTaggedVal(reinterpret_cast<intptr_t>(S),
347f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                    DiagnosticsEngine::ak_c_string);
348f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
349f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
350f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
351f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
352f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                                    StringRef S) {
353f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
354f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddString(S);
355f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
356f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
357f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
358f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
359f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                                    const IdentifierInfo *II) {
360f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddTaggedVal(reinterpret_cast<intptr_t>(II),
361f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                    DiagnosticsEngine::ak_identifierinfo);
362f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
363f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
364f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
365f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // Adds a DeclContext to the diagnostic. The enable_if template magic is here
366f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // so that we only match those arguments that are (statically) DeclContexts;
367f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // other arguments that derive from DeclContext (e.g., RecordDecls) will not
368f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  // match.
369f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  template<typename T>
370f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend inline
371f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  typename std::enable_if<std::is_same<T, DeclContext>::value,
372f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                          const PartialDiagnostic &>::type
373f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  operator<<(const PartialDiagnostic &PD, T *DC) {
374f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
375f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                    DiagnosticsEngine::ak_declcontext);
376f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
377f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
378f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
379f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
380f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                                    SourceRange R) {
381f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddSourceRange(CharSourceRange::getTokenRange(R));
382f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
383f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
384f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
385f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
386f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                                    const CharSourceRange &R) {
387f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddSourceRange(R);
388f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
389f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
390f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
391f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
392f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                             const FixItHint &Hint) {
393f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    PD.AddFixItHint(Hint);
394f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot    return PD;
395f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  }
396f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
397f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot};
398f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
399f3014761c955345d6e05491608e73228d014afbandroid-build-team Robotinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
400f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot                                           const PartialDiagnostic &PD) {
401f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  PD.Emit(DB);
402f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot  return DB;
403f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot}
404f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
405f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// \brief A partial diagnostic along with the source location where this
406f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot/// diagnostic occurs.
407f3014761c955345d6e05491608e73228d014afbandroid-build-team Robottypedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt;
408f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot
409f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot}  // end namespace clang
410f3014761c955345d6e05491608e73228d014afbandroid-build-team Robot#endif
411