Add include needed for MSVC.
[clang/acc.git] / lib / Sema / SemaInherit.cpp
blob2f914f14a81fa488e6b3bf7f4e9e5d7c2b48a92a
1 //===---- SemaInherit.cpp - C++ Inheritance ---------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides Sema routines for C++ inheritance semantics,
11 // including searching the inheritance hierarchy.
13 //===----------------------------------------------------------------------===//
15 #include "SemaInherit.h"
16 #include "Sema.h"
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/Type.h"
20 #include "clang/AST/TypeOrdering.h"
21 #include <algorithm>
22 #include <memory>
23 #include <set>
24 #include <string>
26 using namespace clang;
28 /// \brief Computes the set of declarations referenced by these base
29 /// paths.
30 void BasePaths::ComputeDeclsFound() {
31 assert(NumDeclsFound == 0 && !DeclsFound &&
32 "Already computed the set of declarations");
34 std::set<NamedDecl *> Decls;
35 for (BasePaths::paths_iterator Path = begin(), PathEnd = end();
36 Path != PathEnd; ++Path)
37 Decls.insert(*Path->Decls.first);
39 NumDeclsFound = Decls.size();
40 DeclsFound = new NamedDecl * [NumDeclsFound];
41 std::copy(Decls.begin(), Decls.end(), DeclsFound);
44 BasePaths::decl_iterator BasePaths::found_decls_begin() {
45 if (NumDeclsFound == 0)
46 ComputeDeclsFound();
47 return DeclsFound;
50 BasePaths::decl_iterator BasePaths::found_decls_end() {
51 if (NumDeclsFound == 0)
52 ComputeDeclsFound();
53 return DeclsFound + NumDeclsFound;
56 /// isAmbiguous - Determines whether the set of paths provided is
57 /// ambiguous, i.e., there are two or more paths that refer to
58 /// different base class subobjects of the same type. BaseType must be
59 /// an unqualified, canonical class type.
60 bool BasePaths::isAmbiguous(QualType BaseType) {
61 assert(BaseType->isCanonical() && "Base type must be the canonical type");
62 assert(BaseType.getCVRQualifiers() == 0 && "Base type must be unqualified");
63 std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];
64 return Subobjects.second + (Subobjects.first? 1 : 0) > 1;
67 /// clear - Clear out all prior path information.
68 void BasePaths::clear() {
69 Paths.clear();
70 ClassSubobjects.clear();
71 ScratchPath.clear();
72 DetectedVirtual = 0;
75 /// @brief Swaps the contents of this BasePaths structure with the
76 /// contents of Other.
77 void BasePaths::swap(BasePaths &Other) {
78 std::swap(Origin, Other.Origin);
79 Paths.swap(Other.Paths);
80 ClassSubobjects.swap(Other.ClassSubobjects);
81 std::swap(FindAmbiguities, Other.FindAmbiguities);
82 std::swap(RecordPaths, Other.RecordPaths);
83 std::swap(DetectVirtual, Other.DetectVirtual);
84 std::swap(DetectedVirtual, Other.DetectedVirtual);
87 /// IsDerivedFrom - Determine whether the type Derived is derived from
88 /// the type Base, ignoring qualifiers on Base and Derived. This
89 /// routine does not assess whether an actual conversion from a
90 /// Derived* to a Base* is legal, because it does not account for
91 /// ambiguous conversions or conversions to private/protected bases.
92 bool Sema::IsDerivedFrom(QualType Derived, QualType Base) {
93 BasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false,
94 /*DetectVirtual=*/false);
95 return IsDerivedFrom(Derived, Base, Paths);
98 /// IsDerivedFrom - Determine whether the type Derived is derived from
99 /// the type Base, ignoring qualifiers on Base and Derived. This
100 /// routine does not assess whether an actual conversion from a
101 /// Derived* to a Base* is legal, because it does not account for
102 /// ambiguous conversions or conversions to private/protected
103 /// bases. This routine will use Paths to determine if there are
104 /// ambiguous paths (if @c Paths.isFindingAmbiguities()) and record
105 /// information about all of the paths (if @c Paths.isRecordingPaths()).
106 bool Sema::IsDerivedFrom(QualType Derived, QualType Base, BasePaths &Paths) {
107 Derived = Context.getCanonicalType(Derived).getUnqualifiedType();
108 Base = Context.getCanonicalType(Base).getUnqualifiedType();
110 if (!Derived->isRecordType() || !Base->isRecordType())
111 return false;
113 if (Derived == Base)
114 return false;
116 Paths.setOrigin(Derived);
117 return LookupInBases(cast<CXXRecordDecl>(Derived->getAsRecordType()->getDecl()),
118 MemberLookupCriteria(Base), Paths);
121 /// LookupInBases - Look for something that meets the specified
122 /// Criteria within the base classes of Class (or any of its base
123 /// classes, transitively). This routine populates BasePaths with the
124 /// list of paths that one can take to find the entity that meets the
125 /// search criteria, and returns true if any such entity is found. The
126 /// various options passed to the BasePath constructor will affect the
127 /// behavior of this lookup, e.g., whether it finds ambiguities,
128 /// records paths, or attempts to detect the use of virtual base
129 /// classes.
130 bool Sema::LookupInBases(CXXRecordDecl *Class,
131 const MemberLookupCriteria& Criteria,
132 BasePaths &Paths) {
133 bool FoundPath = false;
135 for (CXXRecordDecl::base_class_const_iterator BaseSpec = Class->bases_begin(),
136 BaseSpecEnd = Class->bases_end();
137 BaseSpec != BaseSpecEnd; ++BaseSpec) {
138 // Find the record of the base class subobjects for this type.
139 QualType BaseType = Context.getCanonicalType(BaseSpec->getType());
140 BaseType = BaseType.getUnqualifiedType();
142 // If a base class of the class template depends on a template-parameter,
143 // the base class scope is not examined during unqualified name lookup.
144 // [temp.dep]p3.
145 if (BaseType->isDependentType())
146 continue;
148 // Determine whether we need to visit this base class at all,
149 // updating the count of subobjects appropriately.
150 std::pair<bool, unsigned>& Subobjects = Paths.ClassSubobjects[BaseType];
151 bool VisitBase = true;
152 bool SetVirtual = false;
153 if (BaseSpec->isVirtual()) {
154 VisitBase = !Subobjects.first;
155 Subobjects.first = true;
156 if (Paths.isDetectingVirtual() && Paths.DetectedVirtual == 0) {
157 // If this is the first virtual we find, remember it. If it turns out
158 // there is no base path here, we'll reset it later.
159 Paths.DetectedVirtual = BaseType->getAsRecordType();
160 SetVirtual = true;
162 } else
163 ++Subobjects.second;
165 if (Paths.isRecordingPaths()) {
166 // Add this base specifier to the current path.
167 BasePathElement Element;
168 Element.Base = &*BaseSpec;
169 Element.Class = Class;
170 if (BaseSpec->isVirtual())
171 Element.SubobjectNumber = 0;
172 else
173 Element.SubobjectNumber = Subobjects.second;
174 Paths.ScratchPath.push_back(Element);
177 CXXRecordDecl *BaseRecord
178 = cast<CXXRecordDecl>(BaseSpec->getType()->getAsRecordType()->getDecl());
180 // Either look at the base class type or look into the base class
181 // type to see if we've found a member that meets the search
182 // criteria.
183 bool FoundPathToThisBase = false;
184 switch (Criteria.Kind) {
185 case MemberLookupCriteria::LK_Base:
186 FoundPathToThisBase
187 = (Context.getCanonicalType(BaseSpec->getType()) == Criteria.Base);
188 break;
189 case MemberLookupCriteria::LK_NamedMember:
190 Paths.ScratchPath.Decls = BaseRecord->lookup(Criteria.Name);
191 while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) {
192 if (isAcceptableLookupResult(*Paths.ScratchPath.Decls.first,
193 Criteria.NameKind, Criteria.IDNS)) {
194 FoundPathToThisBase = true;
195 break;
197 ++Paths.ScratchPath.Decls.first;
199 break;
200 case MemberLookupCriteria::LK_OverriddenMember:
201 Paths.ScratchPath.Decls =
202 BaseRecord->lookup(Criteria.Method->getDeclName());
203 while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) {
204 if (CXXMethodDecl *MD =
205 dyn_cast<CXXMethodDecl>(*Paths.ScratchPath.Decls.first)) {
206 OverloadedFunctionDecl::function_iterator MatchedDecl;
207 if (MD->isVirtual() &&
208 !IsOverload(Criteria.Method, MD, MatchedDecl)) {
209 FoundPathToThisBase = true;
210 break;
214 ++Paths.ScratchPath.Decls.first;
216 break;
219 if (FoundPathToThisBase) {
220 // We've found a path that terminates that this base.
221 FoundPath = true;
222 if (Paths.isRecordingPaths()) {
223 // We have a path. Make a copy of it before moving on.
224 Paths.Paths.push_back(Paths.ScratchPath);
225 } else if (!Paths.isFindingAmbiguities()) {
226 // We found a path and we don't care about ambiguities;
227 // return immediately.
228 return FoundPath;
231 // C++ [class.member.lookup]p2:
232 // A member name f in one sub-object B hides a member name f in
233 // a sub-object A if A is a base class sub-object of B. Any
234 // declarations that are so hidden are eliminated from
235 // consideration.
236 else if (VisitBase && LookupInBases(BaseRecord, Criteria, Paths)) {
237 // There is a path to a base class that meets the criteria. If we're not
238 // collecting paths or finding ambiguities, we're done.
239 FoundPath = true;
240 if (!Paths.isFindingAmbiguities())
241 return FoundPath;
244 // Pop this base specifier off the current path (if we're
245 // collecting paths).
246 if (Paths.isRecordingPaths())
247 Paths.ScratchPath.pop_back();
248 // If we set a virtual earlier, and this isn't a path, forget it again.
249 if (SetVirtual && !FoundPath) {
250 Paths.DetectedVirtual = 0;
254 return FoundPath;
257 /// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
258 /// conversion (where Derived and Base are class types) is
259 /// well-formed, meaning that the conversion is unambiguous (and
260 /// that all of the base classes are accessible). Returns true
261 /// and emits a diagnostic if the code is ill-formed, returns false
262 /// otherwise. Loc is the location where this routine should point to
263 /// if there is an error, and Range is the source range to highlight
264 /// if there is an error.
265 bool
266 Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
267 unsigned InaccessibleBaseID,
268 unsigned AmbigiousBaseConvID,
269 SourceLocation Loc, SourceRange Range,
270 DeclarationName Name) {
271 // First, determine whether the path from Derived to Base is
272 // ambiguous. This is slightly more expensive than checking whether
273 // the Derived to Base conversion exists, because here we need to
274 // explore multiple paths to determine if there is an ambiguity.
275 BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
276 /*DetectVirtual=*/false);
277 bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths);
278 assert(DerivationOkay &&
279 "Can only be used with a derived-to-base conversion");
280 (void)DerivationOkay;
282 if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
283 // Check that the base class can be accessed.
284 return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc,
285 Name);
288 // We know that the derived-to-base conversion is ambiguous, and
289 // we're going to produce a diagnostic. Perform the derived-to-base
290 // search just one more time to compute all of the possible paths so
291 // that we can print them out. This is more expensive than any of
292 // the previous derived-to-base checks we've done, but at this point
293 // performance isn't as much of an issue.
294 Paths.clear();
295 Paths.setRecordingPaths(true);
296 bool StillOkay = IsDerivedFrom(Derived, Base, Paths);
297 assert(StillOkay && "Can only be used with a derived-to-base conversion");
298 (void)StillOkay;
300 // Build up a textual representation of the ambiguous paths, e.g.,
301 // D -> B -> A, that will be used to illustrate the ambiguous
302 // conversions in the diagnostic. We only print one of the paths
303 // to each base class subobject.
304 std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);
306 Diag(Loc, AmbigiousBaseConvID)
307 << Derived << Base << PathDisplayStr << Range << Name;
308 return true;
311 bool
312 Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
313 SourceLocation Loc, SourceRange Range) {
314 return CheckDerivedToBaseConversion(Derived, Base,
315 diag::err_conv_to_inaccessible_base,
316 diag::err_ambiguous_derived_to_base_conv,
317 Loc, Range, DeclarationName());
321 /// @brief Builds a string representing ambiguous paths from a
322 /// specific derived class to different subobjects of the same base
323 /// class.
325 /// This function builds a string that can be used in error messages
326 /// to show the different paths that one can take through the
327 /// inheritance hierarchy to go from the derived class to different
328 /// subobjects of a base class. The result looks something like this:
329 /// @code
330 /// struct D -> struct B -> struct A
331 /// struct D -> struct C -> struct A
332 /// @endcode
333 std::string Sema::getAmbiguousPathsDisplayString(BasePaths &Paths) {
334 std::string PathDisplayStr;
335 std::set<unsigned> DisplayedPaths;
336 for (BasePaths::paths_iterator Path = Paths.begin();
337 Path != Paths.end(); ++Path) {
338 if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) {
339 // We haven't displayed a path to this particular base
340 // class subobject yet.
341 PathDisplayStr += "\n ";
342 PathDisplayStr += Paths.getOrigin().getAsString();
343 for (BasePath::const_iterator Element = Path->begin();
344 Element != Path->end(); ++Element)
345 PathDisplayStr += " -> " + Element->Base->getType().getAsString();
349 return PathDisplayStr;