clang  10.0.0svn
ComparisonCategories.cpp
Go to the documentation of this file.
1 //===- ComparisonCategories.cpp - Three Way Comparison Data -----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the Comparison Category enum and data types, which
10 // store the types and expressions needed to support operator<=>
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "clang/AST/Decl.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/Type.h"
18 #include "llvm/ADT/SmallVector.h"
19 
20 using namespace clang;
21 
23  assert(VD && "must have var decl");
24  if (!VD->checkInitIsICE())
25  return false;
26 
27  // Before we attempt to get the value of the first field, ensure that we
28  // actually have one (and only one) field.
29  auto *Record = VD->getType()->getAsCXXRecordDecl();
30  if (std::distance(Record->field_begin(), Record->field_end()) != 1 ||
31  !Record->field_begin()->getType()->isIntegralOrEnumerationType())
32  return false;
33 
34  return true;
35 }
36 
37 /// Attempt to determine the integer value used to represent the comparison
38 /// category result by evaluating the initializer for the specified VarDecl as
39 /// a constant expression and retreiving the value of the class's first
40 /// (and only) field.
41 ///
42 /// Note: The STL types are expected to have the form:
43 /// struct X { T value; };
44 /// where T is an integral or enumeration type.
46  assert(hasValidIntValue() && "must have a valid value");
47  return VD->evaluateValue()->getStructField(0).getInt();
48 }
49 
50 ComparisonCategoryInfo::ValueInfo *ComparisonCategoryInfo::lookupValueInfo(
51  ComparisonCategoryResult ValueKind) const {
52  // Check if we already have a cache entry for this value.
53  auto It = llvm::find_if(
54  Objects, [&](ValueInfo const &Info) { return Info.Kind == ValueKind; });
55  if (It != Objects.end())
56  return &(*It);
57 
58  // We don't have a cached result. Lookup the variable declaration and create
59  // a new entry representing it.
61  &Ctx.Idents.get(ComparisonCategories::getResultString(ValueKind)));
62  if (Lookup.size() != 1 || !isa<VarDecl>(Lookup.front()))
63  return nullptr;
64  Objects.emplace_back(ValueKind, cast<VarDecl>(Lookup.front()));
65  return &Objects.back();
66 }
67 
68 static const NamespaceDecl *lookupStdNamespace(const ASTContext &Ctx,
69  NamespaceDecl *&StdNS) {
70  if (!StdNS) {
72  Ctx.getTranslationUnitDecl()->lookup(&Ctx.Idents.get("std"));
73  if (Lookup.size() == 1)
74  StdNS = dyn_cast<NamespaceDecl>(Lookup.front());
75  }
76  return StdNS;
77 }
78 
80  const NamespaceDecl *StdNS,
82  StringRef Name = ComparisonCategories::getCategoryString(Kind);
83  DeclContextLookupResult Lookup = StdNS->lookup(&Ctx.Idents.get(Name));
84  if (Lookup.size() == 1)
85  if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Lookup.front()))
86  return RD;
87  return nullptr;
88 }
89 
92  auto It = Data.find(static_cast<char>(Kind));
93  if (It != Data.end())
94  return &It->second;
95 
96  if (const NamespaceDecl *NS = lookupStdNamespace(Ctx, StdNS))
97  if (CXXRecordDecl *RD = lookupCXXRecordDecl(Ctx, NS, Kind))
98  return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second;
99 
100  return nullptr;
101 }
102 
104 ComparisonCategories::lookupInfoForType(QualType Ty) const {
105  assert(!Ty.isNull() && "type must be non-null");
106  using CCT = ComparisonCategoryType;
107  auto *RD = Ty->getAsCXXRecordDecl();
108  if (!RD)
109  return nullptr;
110 
111  // Check to see if we have information for the specified type cached.
112  const auto *CanonRD = RD->getCanonicalDecl();
113  for (auto &KV : Data) {
114  const ComparisonCategoryInfo &Info = KV.second;
115  if (CanonRD == Info.Record->getCanonicalDecl())
116  return &Info;
117  }
118 
119  if (!RD->getEnclosingNamespaceContext()->isStdNamespace())
120  return nullptr;
121 
122  // If not, check to see if the decl names a type in namespace std with a name
123  // matching one of the comparison category types.
124  for (unsigned I = static_cast<unsigned>(CCT::First),
125  End = static_cast<unsigned>(CCT::Last);
126  I <= End; ++I) {
127  CCT Kind = static_cast<CCT>(I);
128 
129  // We've found the comparison category type. Build a new cache entry for
130  // it.
131  if (getCategoryString(Kind) == RD->getName())
132  return &Data.try_emplace((char)Kind, Ctx, RD, Kind).first->second;
133  }
134 
135  // We've found nothing. This isn't a comparison category type.
136  return nullptr;
137 }
138 
140  const ComparisonCategoryInfo *Info = lookupInfoForType(Ty);
141  assert(Info && "info for comparison category not found");
142  return *Info;
143 }
144 
146  assert(Record);
147  return QualType(Record->getTypeForDecl(), 0);
148 }
149 
151  using CCKT = ComparisonCategoryType;
152  switch (Kind) {
153  case CCKT::WeakEquality:
154  return "weak_equality";
156  return "strong_equality";
158  return "partial_ordering";
159  case CCKT::WeakOrdering:
160  return "weak_ordering";
162  return "strong_ordering";
163  }
164  llvm_unreachable("unhandled cases in switch");
165 }
166 
168  using CCVT = ComparisonCategoryResult;
169  switch (Kind) {
170  case CCVT::Equal:
171  return "equal";
172  case CCVT::Nonequal:
173  return "nonequal";
174  case CCVT::Equivalent:
175  return "equivalent";
176  case CCVT::Nonequivalent:
177  return "nonequivalent";
178  case CCVT::Less:
179  return "less";
180  case CCVT::Greater:
181  return "greater";
182  case CCVT::Unordered:
183  return "unordered";
184  }
185  llvm_unreachable("unhandled case in switch");
186 }
187 
188 std::vector<ComparisonCategoryResult>
190  using CCT = ComparisonCategoryType;
191  using CCR = ComparisonCategoryResult;
192  std::vector<CCR> Values;
193  Values.reserve(6);
194  Values.push_back(CCR::Equivalent);
195  bool IsStrong = (Type == CCT::StrongEquality || Type == CCT::StrongOrdering);
196  if (IsStrong)
197  Values.push_back(CCR::Equal);
198  if (Type == CCT::StrongOrdering || Type == CCT::WeakOrdering ||
199  Type == CCT::PartialOrdering) {
200  Values.push_back(CCR::Less);
201  Values.push_back(CCR::Greater);
202  } else {
203  Values.push_back(CCR::Nonequivalent);
204  if (IsStrong)
205  Values.push_back(CCR::Nonequal);
206  }
207  if (Type == CCT::PartialOrdering)
208  Values.push_back(CCR::Unordered);
209  return Values;
210 }
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
A (possibly-)qualified type.
Definition: Type.h:643
static CXXRecordDecl * lookupCXXRecordDecl(const ASTContext &Ctx, const NamespaceDecl *StdNS, ComparisonCategoryType Kind)
C Language Family Type Representation.
const Type * getTypeForDecl() const
Definition: Decl.h:2967
The base class of the type hierarchy.
Definition: Type.h:1436
Represent a C++ namespace.
Definition: Decl.h:522
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
reference back() const
Definition: DeclBase.h:1243
static std::vector< ComparisonCategoryResult > getPossibleResultsForType(ComparisonCategoryType Type)
Return the list of results which are valid for the specified comparison category type.
reference front() const
Definition: DeclBase.h:1242
static StringRef getResultString(ComparisonCategoryResult Kind)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:160
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1195
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
IdentifierTable & Idents
Definition: ASTContext.h:579
CXXRecordDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclCXX.h:491
field_iterator field_begin() const
Definition: Decl.cpp:4341
const ComparisonCategoryInfo & getInfoForType(QualType Ty) const
Return the comparison category information as specified by getCategoryForType(Ty).
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Definition: DeclBase.cpp:1609
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1692
static StringRef getCategoryString(ComparisonCategoryType Kind)
SourceLocation End
llvm::APSInt getIntValue() const
Get the constant integer value used by this variable to represent the comparison category result type...
field_iterator field_end() const
Definition: Decl.h:3880
APValue & getStructField(unsigned i)
Definition: APValue.h:507
APValue * evaluateValue() const
Attempt to evaluate the value of the initializer attached to this declaration, and produce notes expl...
Definition: Decl.cpp:2339
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:708
bool hasValidIntValue() const
True iff we&#39;ve successfully evaluated the variable as a constant expression and extracted its integer...
Kind
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
llvm::APSInt APSInt
const ComparisonCategoryInfo * lookupInfo(ComparisonCategoryType Kind) const
Return the cached comparison category information for the specified &#39;Kind&#39;.
Dataflow Directional Tag Classes.
static const NamespaceDecl * lookupStdNamespace(const ASTContext &Ctx, NamespaceDecl *&StdNS)
CXXRecordDecl * Record
The declaration for the comparison category type from the standard library.
bool checkInitIsICE() const
Determine whether the value of the initializer attached to this declaration is an integral constant e...
Definition: Decl.cpp:2411
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1008
Represents a C++ struct/union/class.
Definition: DeclCXX.h:255
QualType getType() const
Definition: Decl.h:655
APSInt & getInt()
Definition: APValue.h:380
ComparisonCategoryType
An enumeration representing the different comparison categories types.