diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-10-15 17:07:18 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-10-15 17:07:18 +0000 |
commit | e5557c18e5d41b4b62f2af8a24af20eba40b0225 (patch) | |
tree | 06710cc8b660a5b76972f4e154656b80b8a37662 /lib/Sema | |
parent | 7dc062fe0c5b1560bb94c297bf1b71df517c9767 (diff) | |
download | FreeBSD-src-e5557c18e5d41b4b62f2af8a24af20eba40b0225.zip FreeBSD-src-e5557c18e5d41b4b62f2af8a24af20eba40b0225.tar.gz |
Delete some more files.
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaInherit.cpp | 350 | ||||
-rw-r--r-- | lib/Sema/SemaInherit.h | 248 | ||||
-rw-r--r-- | lib/Sema/SemaNamedCast.cpp | 932 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 1350 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateStmt.cpp | 450 |
5 files changed, 0 insertions, 3330 deletions
diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp deleted file mode 100644 index 2f914f1..0000000 --- a/lib/Sema/SemaInherit.cpp +++ /dev/null @@ -1,350 +0,0 @@ -//===---- SemaInherit.cpp - C++ Inheritance ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides Sema routines for C++ inheritance semantics, -// including searching the inheritance hierarchy. -// -//===----------------------------------------------------------------------===// - -#include "SemaInherit.h" -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeOrdering.h" -#include <algorithm> -#include <memory> -#include <set> -#include <string> - -using namespace clang; - -/// \brief Computes the set of declarations referenced by these base -/// paths. -void BasePaths::ComputeDeclsFound() { - assert(NumDeclsFound == 0 && !DeclsFound && - "Already computed the set of declarations"); - - std::set<NamedDecl *> Decls; - for (BasePaths::paths_iterator Path = begin(), PathEnd = end(); - Path != PathEnd; ++Path) - Decls.insert(*Path->Decls.first); - - NumDeclsFound = Decls.size(); - DeclsFound = new NamedDecl * [NumDeclsFound]; - std::copy(Decls.begin(), Decls.end(), DeclsFound); -} - -BasePaths::decl_iterator BasePaths::found_decls_begin() { - if (NumDeclsFound == 0) - ComputeDeclsFound(); - return DeclsFound; -} - -BasePaths::decl_iterator BasePaths::found_decls_end() { - if (NumDeclsFound == 0) - ComputeDeclsFound(); - return DeclsFound + NumDeclsFound; -} - -/// isAmbiguous - Determines whether the set of paths provided is -/// ambiguous, i.e., there are two or more paths that refer to -/// different base class subobjects of the same type. BaseType must be -/// an unqualified, canonical class type. -bool BasePaths::isAmbiguous(QualType BaseType) { - assert(BaseType->isCanonical() && "Base type must be the canonical type"); - assert(BaseType.getCVRQualifiers() == 0 && "Base type must be unqualified"); - std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; - return Subobjects.second + (Subobjects.first? 1 : 0) > 1; -} - -/// clear - Clear out all prior path information. -void BasePaths::clear() { - Paths.clear(); - ClassSubobjects.clear(); - ScratchPath.clear(); - DetectedVirtual = 0; -} - -/// @brief Swaps the contents of this BasePaths structure with the -/// contents of Other. -void BasePaths::swap(BasePaths &Other) { - std::swap(Origin, Other.Origin); - Paths.swap(Other.Paths); - ClassSubobjects.swap(Other.ClassSubobjects); - std::swap(FindAmbiguities, Other.FindAmbiguities); - std::swap(RecordPaths, Other.RecordPaths); - std::swap(DetectVirtual, Other.DetectVirtual); - std::swap(DetectedVirtual, Other.DetectedVirtual); -} - -/// IsDerivedFrom - Determine whether the type Derived is derived from -/// the type Base, ignoring qualifiers on Base and Derived. This -/// routine does not assess whether an actual conversion from a -/// Derived* to a Base* is legal, because it does not account for -/// ambiguous conversions or conversions to private/protected bases. -bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { - BasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/false, - /*DetectVirtual=*/false); - return IsDerivedFrom(Derived, Base, Paths); -} - -/// IsDerivedFrom - Determine whether the type Derived is derived from -/// the type Base, ignoring qualifiers on Base and Derived. This -/// routine does not assess whether an actual conversion from a -/// Derived* to a Base* is legal, because it does not account for -/// ambiguous conversions or conversions to private/protected -/// bases. This routine will use Paths to determine if there are -/// ambiguous paths (if @c Paths.isFindingAmbiguities()) and record -/// information about all of the paths (if @c Paths.isRecordingPaths()). -bool Sema::IsDerivedFrom(QualType Derived, QualType Base, BasePaths &Paths) { - Derived = Context.getCanonicalType(Derived).getUnqualifiedType(); - Base = Context.getCanonicalType(Base).getUnqualifiedType(); - - if (!Derived->isRecordType() || !Base->isRecordType()) - return false; - - if (Derived == Base) - return false; - - Paths.setOrigin(Derived); - return LookupInBases(cast<CXXRecordDecl>(Derived->getAsRecordType()->getDecl()), - MemberLookupCriteria(Base), Paths); -} - -/// LookupInBases - Look for something that meets the specified -/// Criteria within the base classes of Class (or any of its base -/// classes, transitively). This routine populates BasePaths with the -/// list of paths that one can take to find the entity that meets the -/// search criteria, and returns true if any such entity is found. The -/// various options passed to the BasePath constructor will affect the -/// behavior of this lookup, e.g., whether it finds ambiguities, -/// records paths, or attempts to detect the use of virtual base -/// classes. -bool Sema::LookupInBases(CXXRecordDecl *Class, - const MemberLookupCriteria& Criteria, - BasePaths &Paths) { - bool FoundPath = false; - - for (CXXRecordDecl::base_class_const_iterator BaseSpec = Class->bases_begin(), - BaseSpecEnd = Class->bases_end(); - BaseSpec != BaseSpecEnd; ++BaseSpec) { - // Find the record of the base class subobjects for this type. - QualType BaseType = Context.getCanonicalType(BaseSpec->getType()); - BaseType = BaseType.getUnqualifiedType(); - - // If a base class of the class template depends on a template-parameter, - // the base class scope is not examined during unqualified name lookup. - // [temp.dep]p3. - if (BaseType->isDependentType()) - continue; - - // Determine whether we need to visit this base class at all, - // updating the count of subobjects appropriately. - std::pair<bool, unsigned>& Subobjects = Paths.ClassSubobjects[BaseType]; - bool VisitBase = true; - bool SetVirtual = false; - if (BaseSpec->isVirtual()) { - VisitBase = !Subobjects.first; - Subobjects.first = true; - if (Paths.isDetectingVirtual() && Paths.DetectedVirtual == 0) { - // If this is the first virtual we find, remember it. If it turns out - // there is no base path here, we'll reset it later. - Paths.DetectedVirtual = BaseType->getAsRecordType(); - SetVirtual = true; - } - } else - ++Subobjects.second; - - if (Paths.isRecordingPaths()) { - // Add this base specifier to the current path. - BasePathElement Element; - Element.Base = &*BaseSpec; - Element.Class = Class; - if (BaseSpec->isVirtual()) - Element.SubobjectNumber = 0; - else - Element.SubobjectNumber = Subobjects.second; - Paths.ScratchPath.push_back(Element); - } - - CXXRecordDecl *BaseRecord - = cast<CXXRecordDecl>(BaseSpec->getType()->getAsRecordType()->getDecl()); - - // Either look at the base class type or look into the base class - // type to see if we've found a member that meets the search - // criteria. - bool FoundPathToThisBase = false; - switch (Criteria.Kind) { - case MemberLookupCriteria::LK_Base: - FoundPathToThisBase - = (Context.getCanonicalType(BaseSpec->getType()) == Criteria.Base); - break; - case MemberLookupCriteria::LK_NamedMember: - Paths.ScratchPath.Decls = BaseRecord->lookup(Criteria.Name); - while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) { - if (isAcceptableLookupResult(*Paths.ScratchPath.Decls.first, - Criteria.NameKind, Criteria.IDNS)) { - FoundPathToThisBase = true; - break; - } - ++Paths.ScratchPath.Decls.first; - } - break; - case MemberLookupCriteria::LK_OverriddenMember: - Paths.ScratchPath.Decls = - BaseRecord->lookup(Criteria.Method->getDeclName()); - while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) { - if (CXXMethodDecl *MD = - dyn_cast<CXXMethodDecl>(*Paths.ScratchPath.Decls.first)) { - OverloadedFunctionDecl::function_iterator MatchedDecl; - if (MD->isVirtual() && - !IsOverload(Criteria.Method, MD, MatchedDecl)) { - FoundPathToThisBase = true; - break; - } - } - - ++Paths.ScratchPath.Decls.first; - } - break; - } - - if (FoundPathToThisBase) { - // We've found a path that terminates that this base. - FoundPath = true; - if (Paths.isRecordingPaths()) { - // We have a path. Make a copy of it before moving on. - Paths.Paths.push_back(Paths.ScratchPath); - } else if (!Paths.isFindingAmbiguities()) { - // We found a path and we don't care about ambiguities; - // return immediately. - return FoundPath; - } - } - // C++ [class.member.lookup]p2: - // A member name f in one sub-object B hides a member name f in - // a sub-object A if A is a base class sub-object of B. Any - // declarations that are so hidden are eliminated from - // consideration. - else if (VisitBase && LookupInBases(BaseRecord, Criteria, Paths)) { - // There is a path to a base class that meets the criteria. If we're not - // collecting paths or finding ambiguities, we're done. - FoundPath = true; - if (!Paths.isFindingAmbiguities()) - return FoundPath; - } - - // Pop this base specifier off the current path (if we're - // collecting paths). - if (Paths.isRecordingPaths()) - Paths.ScratchPath.pop_back(); - // If we set a virtual earlier, and this isn't a path, forget it again. - if (SetVirtual && !FoundPath) { - Paths.DetectedVirtual = 0; - } - } - - return FoundPath; -} - -/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base -/// conversion (where Derived and Base are class types) is -/// well-formed, meaning that the conversion is unambiguous (and -/// that all of the base classes are accessible). Returns true -/// and emits a diagnostic if the code is ill-formed, returns false -/// otherwise. Loc is the location where this routine should point to -/// if there is an error, and Range is the source range to highlight -/// if there is an error. -bool -Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, - unsigned InaccessibleBaseID, - unsigned AmbigiousBaseConvID, - SourceLocation Loc, SourceRange Range, - DeclarationName Name) { - // First, determine whether the path from Derived to Base is - // ambiguous. This is slightly more expensive than checking whether - // the Derived to Base conversion exists, because here we need to - // explore multiple paths to determine if there is an ambiguity. - BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, - /*DetectVirtual=*/false); - bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths); - assert(DerivationOkay && - "Can only be used with a derived-to-base conversion"); - (void)DerivationOkay; - - if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { - // Check that the base class can be accessed. - return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc, - Name); - } - - // We know that the derived-to-base conversion is ambiguous, and - // we're going to produce a diagnostic. Perform the derived-to-base - // search just one more time to compute all of the possible paths so - // that we can print them out. This is more expensive than any of - // the previous derived-to-base checks we've done, but at this point - // performance isn't as much of an issue. - Paths.clear(); - Paths.setRecordingPaths(true); - bool StillOkay = IsDerivedFrom(Derived, Base, Paths); - assert(StillOkay && "Can only be used with a derived-to-base conversion"); - (void)StillOkay; - - // Build up a textual representation of the ambiguous paths, e.g., - // D -> B -> A, that will be used to illustrate the ambiguous - // conversions in the diagnostic. We only print one of the paths - // to each base class subobject. - std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); - - Diag(Loc, AmbigiousBaseConvID) - << Derived << Base << PathDisplayStr << Range << Name; - return true; -} - -bool -Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, - SourceLocation Loc, SourceRange Range) { - return CheckDerivedToBaseConversion(Derived, Base, - diag::err_conv_to_inaccessible_base, - diag::err_ambiguous_derived_to_base_conv, - Loc, Range, DeclarationName()); -} - - -/// @brief Builds a string representing ambiguous paths from a -/// specific derived class to different subobjects of the same base -/// class. -/// -/// This function builds a string that can be used in error messages -/// to show the different paths that one can take through the -/// inheritance hierarchy to go from the derived class to different -/// subobjects of a base class. The result looks something like this: -/// @code -/// struct D -> struct B -> struct A -/// struct D -> struct C -> struct A -/// @endcode -std::string Sema::getAmbiguousPathsDisplayString(BasePaths &Paths) { - std::string PathDisplayStr; - std::set<unsigned> DisplayedPaths; - for (BasePaths::paths_iterator Path = Paths.begin(); - Path != Paths.end(); ++Path) { - if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { - // We haven't displayed a path to this particular base - // class subobject yet. - PathDisplayStr += "\n "; - PathDisplayStr += Paths.getOrigin().getAsString(); - for (BasePath::const_iterator Element = Path->begin(); - Element != Path->end(); ++Element) - PathDisplayStr += " -> " + Element->Base->getType().getAsString(); - } - } - - return PathDisplayStr; -} diff --git a/lib/Sema/SemaInherit.h b/lib/Sema/SemaInherit.h deleted file mode 100644 index b1e791a..0000000 --- a/lib/Sema/SemaInherit.h +++ /dev/null @@ -1,248 +0,0 @@ -//===------ SemaInherit.h - C++ Inheritance ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file provides Sema data structures that help analyse C++ -// inheritance semantics, including searching the inheritance -// hierarchy. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_SEMA_INHERIT_H -#define LLVM_CLANG_SEMA_INHERIT_H - -#include "Sema.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/DeclBase.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeOrdering.h" -#include "llvm/ADT/SmallVector.h" -#include <list> -#include <map> - -namespace clang { - class CXXBaseSpecifier; - - /// BasePathElement - An element in a path from a derived class to a - /// base class. Each step in the path references the link from a - /// derived class to one of its direct base classes, along with a - /// base "number" that identifies which base subobject of the - /// original derived class we are referencing. - struct BasePathElement { - /// Base - The base specifier that states the link from a derived - /// class to a base class, which will be followed by this base - /// path element. - const CXXBaseSpecifier *Base; - - /// Class - The record decl of the class that the base is a base of. - const CXXRecordDecl *Class; - - /// SubobjectNumber - Identifies which base class subobject (of type - /// @c Base->getType()) this base path element refers to. This - /// value is only valid if @c !Base->isVirtual(), because there - /// is no base numbering for the zero or one virtual bases of a - /// given type. - int SubobjectNumber; - }; - - /// BasePath - Represents a path from a specific derived class - /// (which is not represented as part of the path) to a particular - /// (direct or indirect) base class subobject that contains some - /// number of declarations with the same name. Individual elements - /// in the path are described by the BasePathElement structure, - /// which captures both the link from a derived class to one of its - /// direct bases and identification describing which base class - /// subobject is being used. - struct BasePath : public llvm::SmallVector<BasePathElement, 4> { - /// Decls - The set of declarations found inside this base class - /// subobject. - DeclContext::lookup_result Decls; - }; - - /// BasePaths - Represents the set of paths from a derived class to - /// one of its (direct or indirect) bases. For example, given the - /// following class hierachy: - /// - /// @code - /// class A { }; - /// class B : public A { }; - /// class C : public A { }; - /// class D : public B, public C{ }; - /// @endcode - /// - /// There are two potential BasePaths to represent paths from D to a - /// base subobject of type A. One path is (D,0) -> (B,0) -> (A,0) - /// and another is (D,0)->(C,0)->(A,1). These two paths actually - /// refer to two different base class subobjects of the same type, - /// so the BasePaths object refers to an ambiguous path. On the - /// other hand, consider the following class hierarchy: - /// - /// @code - /// class A { }; - /// class B : public virtual A { }; - /// class C : public virtual A { }; - /// class D : public B, public C{ }; - /// @endcode - /// - /// Here, there are two potential BasePaths again, (D, 0) -> (B, 0) - /// -> (A,v) and (D, 0) -> (C, 0) -> (A, v), but since both of them - /// refer to the same base class subobject of type A (the virtual - /// one), there is no ambiguity. - class BasePaths { - /// Origin - The type from which this search originated. - QualType Origin; - - /// Paths - The actual set of paths that can be taken from the - /// derived class to the same base class. - std::list<BasePath> Paths; - - /// ClassSubobjects - Records the class subobjects for each class - /// type that we've seen. The first element in the pair says - /// whether we found a path to a virtual base for that class type, - /// while the element contains the number of non-virtual base - /// class subobjects for that class type. The key of the map is - /// the cv-unqualified canonical type of the base class subobject. - std::map<QualType, std::pair<bool, unsigned>, QualTypeOrdering> - ClassSubobjects; - - /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find - /// ambiguous paths while it is looking for a path from a derived - /// type to a base type. - bool FindAmbiguities; - - /// RecordPaths - Whether Sema::IsDerivedFrom should record paths - /// while it is determining whether there are paths from a derived - /// type to a base type. - bool RecordPaths; - - /// DetectVirtual - Whether Sema::IsDerivedFrom should abort the search - /// if it finds a path that goes across a virtual base. The virtual class - /// is also recorded. - bool DetectVirtual; - - /// ScratchPath - A BasePath that is used by Sema::IsDerivedFrom - /// to help build the set of paths. - BasePath ScratchPath; - - /// DetectedVirtual - The base class that is virtual. - const RecordType *DetectedVirtual; - - /// \brief Array of the declarations that have been found. This - /// array is constructed only if needed, e.g., to iterate over the - /// results within LookupResult. - NamedDecl **DeclsFound; - unsigned NumDeclsFound; - - friend class Sema; - - void ComputeDeclsFound(); - - public: - typedef std::list<BasePath>::const_iterator paths_iterator; - typedef NamedDecl **decl_iterator; - - /// BasePaths - Construct a new BasePaths structure to record the - /// paths for a derived-to-base search. - explicit BasePaths(bool FindAmbiguities = true, - bool RecordPaths = true, - bool DetectVirtual = true) - : FindAmbiguities(FindAmbiguities), RecordPaths(RecordPaths), - DetectVirtual(DetectVirtual), DetectedVirtual(0), DeclsFound(0), - NumDeclsFound(0) - {} - - ~BasePaths() { delete [] DeclsFound; } - - paths_iterator begin() const { return Paths.begin(); } - paths_iterator end() const { return Paths.end(); } - - BasePath& front() { return Paths.front(); } - const BasePath& front() const { return Paths.front(); } - - decl_iterator found_decls_begin(); - decl_iterator found_decls_end(); - - bool isAmbiguous(QualType BaseType); - - /// isFindingAmbiguities - Whether we are finding multiple paths - /// to detect ambiguities. - bool isFindingAmbiguities() const { return FindAmbiguities; } - - /// isRecordingPaths - Whether we are recording paths. - bool isRecordingPaths() const { return RecordPaths; } - - /// setRecordingPaths - Specify whether we should be recording - /// paths or not. - void setRecordingPaths(bool RP) { RecordPaths = RP; } - - /// isDetectingVirtual - Whether we are detecting virtual bases. - bool isDetectingVirtual() const { return DetectVirtual; } - - /// getDetectedVirtual - The virtual base discovered on the path. - const RecordType* getDetectedVirtual() const { - return DetectedVirtual; - } - - /// @brief Retrieve the type from which this base-paths search - /// began - QualType getOrigin() const { return Origin; } - void setOrigin(QualType Type) { Origin = Type; } - - void clear(); - - void swap(BasePaths &Other); - }; - - /// MemberLookupCriteria - Criteria for performing lookup of a - /// member of a C++ class. Objects of this type are used to direct - /// Sema::LookupCXXClassMember. - struct MemberLookupCriteria { - /// LookupKind - the kind of lookup we're doing. - enum LookupKind { - LK_Base, - LK_NamedMember, - LK_OverriddenMember - }; - - /// MemberLookupCriteria - Constructs member lookup criteria to - /// search for a base class of type Base. - explicit MemberLookupCriteria(QualType Base) - : Kind(LK_Base), Base(Base) { } - - /// MemberLookupCriteria - Constructs member lookup criteria to - /// search for a class member with the given Name. - explicit MemberLookupCriteria(DeclarationName Name, - Sema::LookupNameKind NameKind, - unsigned IDNS) - : Kind(LK_NamedMember), Name(Name), NameKind(NameKind), IDNS(IDNS) { } - - explicit MemberLookupCriteria(CXXMethodDecl *MD) - : Kind(LK_OverriddenMember), Method(MD) { } - - /// Kind - The kind of lookup we're doing. - /// LK_Base if we are looking for a base class (whose - /// type is Base). LK_NamedMember if we are looking for a named member of - /// the class (with the name Name). - LookupKind Kind; - - /// Base - The type of the base class we're searching for, if - /// LookupBase is true. - QualType Base; - - /// Name - The name of the member we're searching for, if - /// LookupBase is false. - DeclarationName Name; - - Sema::LookupNameKind NameKind; - unsigned IDNS; - - CXXMethodDecl *Method; - }; -} - -#endif diff --git a/lib/Sema/SemaNamedCast.cpp b/lib/Sema/SemaNamedCast.cpp deleted file mode 100644 index daf6800..0000000 --- a/lib/Sema/SemaNamedCast.cpp +++ /dev/null @@ -1,932 +0,0 @@ -//===--- SemaNamedCast.cpp - Semantic Analysis for Named Casts ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements semantic analysis for C++ named casts. -// -//===----------------------------------------------------------------------===// - -#include "Sema.h" -#include "SemaInherit.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ASTContext.h" -#include "llvm/ADT/SmallVector.h" -#include <set> -using namespace clang; - -enum TryStaticCastResult { - TSC_NotApplicable, ///< The cast method is not applicable. - TSC_Success, ///< The cast method is appropriate and successful. - TSC_Failed ///< The cast method is appropriate, but failed. A - ///< diagnostic has been emitted. -}; - -static void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, - const SourceRange &DestRange); -static void CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, - const SourceRange &DestRange); -static void CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange); -static void CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, - const SourceRange &DestRange); - -static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType); -static TryStaticCastResult TryLValueToRValueCast( - Sema &Self, Expr *SrcExpr, QualType DestType, const SourceRange &OpRange); -static TryStaticCastResult TryStaticReferenceDowncast( - Sema &Self, Expr *SrcExpr, QualType DestType, const SourceRange &OpRange); -static TryStaticCastResult TryStaticPointerDowncast( - Sema &Self, QualType SrcType, QualType DestType, const SourceRange &OpRange); -static TryStaticCastResult TryStaticMemberPointerUpcast( - Sema &Self, QualType SrcType, QualType DestType, const SourceRange &OpRange); -static TryStaticCastResult TryStaticDowncast(Sema &Self, QualType SrcType, - QualType DestType, - const SourceRange &OpRange, - QualType OrigSrcType, - QualType OrigDestType); -static TryStaticCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, - QualType DestType, - const SourceRange &OpRange); - -/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. -Action::OwningExprResult -Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, - SourceLocation LAngleBracketLoc, TypeTy *Ty, - SourceLocation RAngleBracketLoc, - SourceLocation LParenLoc, ExprArg E, - SourceLocation RParenLoc) { - Expr *Ex = E.takeAs<Expr>(); - QualType DestType = QualType::getFromOpaquePtr(Ty); - SourceRange OpRange(OpLoc, RParenLoc); - SourceRange DestRange(LAngleBracketLoc, RAngleBracketLoc); - - // If the type is dependent, we won't do the semantic analysis now. - // FIXME: should we check this in a more fine-grained manner? - bool TypeDependent = DestType->isDependentType() || Ex->isTypeDependent(); - - switch (Kind) { - default: assert(0 && "Unknown C++ cast!"); - - case tok::kw_const_cast: - if (!TypeDependent) - CheckConstCast(*this, Ex, DestType, OpRange, DestRange); - return Owned(new (Context) CXXConstCastExpr(DestType.getNonReferenceType(), - Ex, DestType, OpLoc)); - - case tok::kw_dynamic_cast: - if (!TypeDependent) - CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange); - return Owned(new (Context)CXXDynamicCastExpr(DestType.getNonReferenceType(), - Ex, DestType, OpLoc)); - - case tok::kw_reinterpret_cast: - if (!TypeDependent) - CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange); - return Owned(new (Context) CXXReinterpretCastExpr( - DestType.getNonReferenceType(), - Ex, DestType, OpLoc)); - - case tok::kw_static_cast: - if (!TypeDependent) - CheckStaticCast(*this, Ex, DestType, OpRange); - return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(), - Ex, DestType, OpLoc)); - } - - return ExprError(); -} - -/// CheckConstCast - Check that a const_cast\<DestType\>(SrcExpr) is valid. -/// Refer to C++ 5.2.11 for details. const_cast is typically used in code -/// like this: -/// const char *str = "literal"; -/// legacy_function(const_cast\<char*\>(str)); -void -CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, const SourceRange &DestRange) -{ - QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); - - DestType = Self.Context.getCanonicalType(DestType); - QualType SrcType = SrcExpr->getType(); - if (const LValueReferenceType *DestTypeTmp = - DestType->getAsLValueReferenceType()) { - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { - // Cannot cast non-lvalue to lvalue reference type. - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) - << "const_cast" << OrigDestType << SrcExpr->getSourceRange(); - return; - } - - // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2 - // [...] if a pointer to T1 can be [cast] to the type pointer to T2. - DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); - SrcType = Self.Context.getPointerType(SrcType); - } else { - // C++ 5.2.11p1: Otherwise, the result is an rvalue and the - // lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard - // conversions are performed on the expression. - Self.DefaultFunctionArrayConversion(SrcExpr); - SrcType = SrcExpr->getType(); - } - - // C++ 5.2.11p5: For a const_cast involving pointers to data members [...] - // the rules for const_cast are the same as those used for pointers. - - if (!DestType->isPointerType() && !DestType->isMemberPointerType()) { - // Cannot cast to non-pointer, non-reference type. Note that, if DestType - // was a reference type, we converted it to a pointer above. - // The status of rvalue references isn't entirely clear, but it looks like - // conversion to them is simply invalid. - // C++ 5.2.11p3: For two pointer types [...] - Self.Diag(OpRange.getBegin(), diag::err_bad_const_cast_dest) - << OrigDestType << DestRange; - return; - } - if (DestType->isFunctionPointerType() || - DestType->isMemberFunctionPointerType()) { - // Cannot cast direct function pointers. - // C++ 5.2.11p2: [...] where T is any object type or the void type [...] - // T is the ultimate pointee of source and target type. - Self.Diag(OpRange.getBegin(), diag::err_bad_const_cast_dest) - << OrigDestType << DestRange; - return; - } - SrcType = Self.Context.getCanonicalType(SrcType); - - // Unwrap the pointers. Ignore qualifiers. Terminate early if the types are - // completely equal. - // FIXME: const_cast should probably not be able to convert between pointers - // to different address spaces. - // C++ 5.2.11p3 describes the core semantics of const_cast. All cv specifiers - // in multi-level pointers may change, but the level count must be the same, - // as must be the final pointee type. - while (SrcType != DestType && - Self.UnwrapSimilarPointerTypes(SrcType, DestType)) { - SrcType = SrcType.getUnqualifiedType(); - DestType = DestType.getUnqualifiedType(); - } - - // Doug Gregor said to disallow this until users complain. -#if 0 - // If we end up with constant arrays of equal size, unwrap those too. A cast - // from const int [N] to int (&)[N] is invalid by my reading of the - // standard, but g++ accepts it even with -ansi -pedantic. - // No more than one level, though, so don't embed this in the unwrap loop - // above. - const ConstantArrayType *SrcTypeArr, *DestTypeArr; - if ((SrcTypeArr = Self.Context.getAsConstantArrayType(SrcType)) && - (DestTypeArr = Self.Context.getAsConstantArrayType(DestType))) - { - if (SrcTypeArr->getSize() != DestTypeArr->getSize()) { - // Different array sizes. - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) - << "const_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } - SrcType = SrcTypeArr->getElementType().getUnqualifiedType(); - DestType = DestTypeArr->getElementType().getUnqualifiedType(); - } -#endif - - // Since we're dealing in canonical types, the remainder must be the same. - if (SrcType != DestType) { - // Cast between unrelated types. - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) - << "const_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } -} - -/// CheckReinterpretCast - Check that a reinterpret_cast\<DestType\>(SrcExpr) is -/// valid. -/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code -/// like this: -/// char *bytes = reinterpret_cast\<char*\>(int_ptr); -void -CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, const SourceRange &DestRange) -{ - QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); - - DestType = Self.Context.getCanonicalType(DestType); - QualType SrcType = SrcExpr->getType(); - if (const LValueReferenceType *DestTypeTmp = - DestType->getAsLValueReferenceType()) { - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { - // Cannot cast non-lvalue to reference type. - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) - << "reinterpret_cast" << OrigDestType << SrcExpr->getSourceRange(); - return; - } - - // C++ 5.2.10p10: [...] a reference cast reinterpret_cast<T&>(x) has the - // same effect as the conversion *reinterpret_cast<T*>(&x) with the - // built-in & and * operators. - // This code does this transformation for the checked types. - DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); - SrcType = Self.Context.getPointerType(SrcType); - } else if (const RValueReferenceType *DestTypeTmp = - DestType->getAsRValueReferenceType()) { - // Both the reference conversion and the rvalue rules apply. - Self.DefaultFunctionArrayConversion(SrcExpr); - SrcType = SrcExpr->getType(); - - DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); - SrcType = Self.Context.getPointerType(SrcType); - } else { - // C++ 5.2.10p1: [...] the lvalue-to-rvalue, array-to-pointer, and - // function-to-pointer standard conversions are performed on the - // expression v. - Self.DefaultFunctionArrayConversion(SrcExpr); - SrcType = SrcExpr->getType(); - } - - // Canonicalize source for comparison. - SrcType = Self.Context.getCanonicalType(SrcType); - - const MemberPointerType *DestMemPtr = DestType->getAsMemberPointerType(), - *SrcMemPtr = SrcType->getAsMemberPointerType(); - if (DestMemPtr && SrcMemPtr) { - // C++ 5.2.10p9: An rvalue of type "pointer to member of X of type T1" - // can be explicitly converted to an rvalue of type "pointer to member - // of Y of type T2" if T1 and T2 are both function types or both object - // types. - if (DestMemPtr->getPointeeType()->isFunctionType() != - SrcMemPtr->getPointeeType()->isFunctionType()) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) - << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } - - // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away - // constness. - if (CastsAwayConstness(Self, SrcType, DestType)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) - << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } - - // A valid member pointer cast. - return; - } - - // See below for the enumeral issue. - if (SrcType->isNullPtrType() && DestType->isIntegralType() && - !DestType->isEnumeralType()) { - // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral - // type large enough to hold it. A value of std::nullptr_t can be - // converted to an integral type; the conversion has the same meaning - // and validity as a conversion of (void*)0 to the integral type. - if (Self.Context.getTypeSize(SrcType) > - Self.Context.getTypeSize(DestType)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_small_int) - << OrigDestType << DestRange; - } - return; - } - - bool destIsPtr = DestType->isPointerType(); - bool srcIsPtr = SrcType->isPointerType(); - if (!destIsPtr && !srcIsPtr) { - // Except for std::nullptr_t->integer and lvalue->reference, which are - // handled above, at least one of the two arguments must be a pointer. - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) - << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } - - if (SrcType == DestType) { - // C++ 5.2.10p2 has a note that mentions that, subject to all other - // restrictions, a cast to the same type is allowed. The intent is not - // entirely clear here, since all other paragraphs explicitly forbid casts - // to the same type. However, the behavior of compilers is pretty consistent - // on this point: allow same-type conversion if the involved types are - // pointers, disallow otherwise. - return; - } - - // Note: Clang treats enumeration types as integral types. If this is ever - // changed for C++, the additional check here will be redundant. - if (DestType->isIntegralType() && !DestType->isEnumeralType()) { - assert(srcIsPtr && "One type must be a pointer"); - // C++ 5.2.10p4: A pointer can be explicitly converted to any integral - // type large enough to hold it. - if (Self.Context.getTypeSize(SrcType) > - Self.Context.getTypeSize(DestType)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_reinterpret_cast_small_int) - << OrigDestType << DestRange; - } - return; - } - - if (SrcType->isIntegralType() || SrcType->isEnumeralType()) { - assert(destIsPtr && "One type must be a pointer"); - // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly - // converted to a pointer. - return; - } - - if (!destIsPtr || !srcIsPtr) { - // With the valid non-pointer conversions out of the way, we can be even - // more stringent. - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) - << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } - - // C++ 5.2.10p2: The reinterpret_cast operator shall not cast away constness. - if (CastsAwayConstness(Self, SrcType, DestType)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) - << "reinterpret_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } - - // Not casting away constness, so the only remaining check is for compatible - // pointer categories. - - if (SrcType->isFunctionPointerType()) { - if (DestType->isFunctionPointerType()) { - // C++ 5.2.10p6: A pointer to a function can be explicitly converted to - // a pointer to a function of a different type. - return; - } - - // C++0x 5.2.10p8: Converting a pointer to a function into a pointer to - // an object type or vice versa is conditionally-supported. - // Compilers support it in C++03 too, though, because it's necessary for - // casting the return value of dlsym() and GetProcAddress(). - // FIXME: Conditionally-supported behavior should be configurable in the - // TargetInfo or similar. - if (!Self.getLangOptions().CPlusPlus0x) { - Self.Diag(OpRange.getBegin(), diag::ext_reinterpret_cast_fn_obj) - << OpRange; - } - return; - } - - if (DestType->isFunctionPointerType()) { - // See above. - if (!Self.getLangOptions().CPlusPlus0x) { - Self.Diag(OpRange.getBegin(), diag::ext_reinterpret_cast_fn_obj) - << OpRange; - } - return; - } - - // C++ 5.2.10p7: A pointer to an object can be explicitly converted to - // a pointer to an object of different type. - // Void pointers are not specified, but supported by every compiler out there. - // So we finish by allowing everything that remains - it's got to be two - // object pointers. -} - -/// CastsAwayConstness - Check if the pointer conversion from SrcType to -/// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by -/// the cast checkers. Both arguments must denote pointer (possibly to member) -/// types. -bool -CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) -{ - // Casting away constness is defined in C++ 5.2.11p8 with reference to - // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since - // the rules are non-trivial. So first we construct Tcv *...cv* as described - // in C++ 5.2.11p8. - assert((SrcType->isPointerType() || SrcType->isMemberPointerType()) && - "Source type is not pointer or pointer to member."); - assert((DestType->isPointerType() || DestType->isMemberPointerType()) && - "Destination type is not pointer or pointer to member."); - - QualType UnwrappedSrcType = SrcType, UnwrappedDestType = DestType; - llvm::SmallVector<unsigned, 8> cv1, cv2; - - // Find the qualifications. - while (Self.UnwrapSimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { - cv1.push_back(UnwrappedSrcType.getCVRQualifiers()); - cv2.push_back(UnwrappedDestType.getCVRQualifiers()); - } - assert(cv1.size() > 0 && "Must have at least one pointer level."); - - // Construct void pointers with those qualifiers (in reverse order of - // unwrapping, of course). - QualType SrcConstruct = Self.Context.VoidTy; - QualType DestConstruct = Self.Context.VoidTy; - for (llvm::SmallVector<unsigned, 8>::reverse_iterator i1 = cv1.rbegin(), - i2 = cv2.rbegin(); - i1 != cv1.rend(); ++i1, ++i2) - { - SrcConstruct = Self.Context.getPointerType( - SrcConstruct.getQualifiedType(*i1)); - DestConstruct = Self.Context.getPointerType( - DestConstruct.getQualifiedType(*i2)); - } - - // Test if they're compatible. - return SrcConstruct != DestConstruct && - !Self.IsQualificationConversion(SrcConstruct, DestConstruct); -} - -/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid. -/// Refer to C++ 5.2.9 for details. Static casts are mostly used for making -/// implicit conversions explicit and getting rid of data loss warnings. -void -CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange) -{ - // The order the tests is not entirely arbitrary. There is one conversion - // that can be handled in two different ways. Given: - // struct A {}; - // struct B : public A { - // B(); B(const A&); - // }; - // const A &a = B(); - // the cast static_cast<const B&>(a) could be seen as either a static - // reference downcast, or an explicit invocation of the user-defined - // conversion using B's conversion constructor. - // DR 427 specifies that the downcast is to be applied here. - - // FIXME: With N2812, casts to rvalue refs will change. - - // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". - if (DestType->isVoidType()) { - return; - } - - // C++ 5.2.9p5, reference downcast. - // See the function for details. - // DR 427 specifies that this is to be applied before paragraph 2. - if (TryStaticReferenceDowncast(Self, SrcExpr, DestType, OpRange) - > TSC_NotApplicable) { - return; - } - - // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue - // reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". - if (TryLValueToRValueCast(Self, SrcExpr, DestType, OpRange) > - TSC_NotApplicable) { - return; - } - - // C++ 5.2.9p2: An expression e can be explicitly converted to a type T - // [...] if the declaration "T t(e);" is well-formed, [...]. - if (TryStaticImplicitCast(Self, SrcExpr, DestType, OpRange) > - TSC_NotApplicable) { - return; - } - - // C++ 5.2.9p6: May apply the reverse of any standard conversion, except - // lvalue-to-rvalue, array-to-pointer, function-to-pointer, and boolean - // conversions, subject to further restrictions. - // Also, C++ 5.2.9p1 forbids casting away constness, which makes reversal - // of qualification conversions impossible. - - // The lvalue-to-rvalue, array-to-pointer and function-to-pointer conversions - // are applied to the expression. - QualType OrigSrcType = SrcExpr->getType(); - Self.DefaultFunctionArrayConversion(SrcExpr); - - QualType SrcType = Self.Context.getCanonicalType(SrcExpr->getType()); - - // Reverse integral promotion/conversion. All such conversions are themselves - // again integral promotions or conversions and are thus already handled by - // p2 (TryDirectInitialization above). - // (Note: any data loss warnings should be suppressed.) - // The exception is the reverse of enum->integer, i.e. integer->enum (and - // enum->enum). See also C++ 5.2.9p7. - // The same goes for reverse floating point promotion/conversion and - // floating-integral conversions. Again, only floating->enum is relevant. - if (DestType->isEnumeralType()) { - if (SrcType->isComplexType() || SrcType->isVectorType()) { - // Fall through - these cannot be converted. - } else if (SrcType->isArithmeticType() || SrcType->isEnumeralType()) { - return; - } - } - - // Reverse pointer upcast. C++ 4.10p3 specifies pointer upcast. - // C++ 5.2.9p8 additionally disallows a cast path through virtual inheritance. - if (TryStaticPointerDowncast(Self, SrcType, DestType, OpRange) - > TSC_NotApplicable) { - return; - } - - // Reverse member pointer conversion. C++ 4.11 specifies member pointer - // conversion. C++ 5.2.9p9 has additional information. - // DR54's access restrictions apply here also. - if (TryStaticMemberPointerUpcast(Self, SrcType, DestType, OpRange) - > TSC_NotApplicable) { - return; - } - - // Reverse pointer conversion to void*. C++ 4.10.p2 specifies conversion to - // void*. C++ 5.2.9p10 specifies additional restrictions, which really is - // just the usual constness stuff. - if (const PointerType *SrcPointer = SrcType->getAsPointerType()) { - QualType SrcPointee = SrcPointer->getPointeeType(); - if (SrcPointee->isVoidType()) { - if (const PointerType *DestPointer = DestType->getAsPointerType()) { - QualType DestPointee = DestPointer->getPointeeType(); - if (DestPointee->isIncompleteOrObjectType()) { - // This is definitely the intended conversion, but it might fail due - // to a const violation. - if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) - << "static_cast" << DestType << OrigSrcType << OpRange; - } - return; - } - } - } - } - - // We tried everything. Everything! Nothing works! :-( - // FIXME: Error reporting could be a lot better. Should store the reason why - // every substep failed and, at the end, select the most specific and report - // that. - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_generic) - << "static_cast" << DestType << OrigSrcType - << OpRange; -} - -/// Tests whether a conversion according to N2844 is valid. -TryStaticCastResult -TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType, - const SourceRange &OpRange) -{ - // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue - // reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1". - const RValueReferenceType *R = DestType->getAsRValueReferenceType(); - if (!R) - return TSC_NotApplicable; - - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) - return TSC_NotApplicable; - - // Because we try the reference downcast before this function, from now on - // this is the only cast possibility, so we issue an error if we fail now. - bool DerivedToBase; - if (Self.CompareReferenceRelationship(SrcExpr->getType(), R->getPointeeType(), - DerivedToBase) < - Sema::Ref_Compatible_With_Added_Qualification) { - Self.Diag(OpRange.getBegin(), diag::err_bad_lvalue_to_rvalue_cast) - << SrcExpr->getType() << R->getPointeeType() << OpRange; - return TSC_Failed; - } - - // FIXME: Similar to CheckReferenceInit, we actually need more AST annotation - // than nothing. - return TSC_Success; -} - -/// Tests whether a conversion according to C++ 5.2.9p5 is valid. -TryStaticCastResult -TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType, - const SourceRange &OpRange) -{ - // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be - // cast to type "reference to cv2 D", where D is a class derived from B, - // if a valid standard conversion from "pointer to D" to "pointer to B" - // exists, cv2 >= cv1, and B is not a virtual base class of D. - // In addition, DR54 clarifies that the base must be accessible in the - // current context. Although the wording of DR54 only applies to the pointer - // variant of this rule, the intent is clearly for it to apply to the this - // conversion as well. - - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { - return TSC_NotApplicable; - } - - const ReferenceType *DestReference = DestType->getAsReferenceType(); - if (!DestReference) { - return TSC_NotApplicable; - } - QualType DestPointee = DestReference->getPointeeType(); - - return TryStaticDowncast(Self, SrcExpr->getType(), DestPointee, OpRange, - SrcExpr->getType(), DestType); -} - -/// Tests whether a conversion according to C++ 5.2.9p8 is valid. -TryStaticCastResult -TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType, - const SourceRange &OpRange) -{ - // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class - // type, can be converted to an rvalue of type "pointer to cv2 D", where D - // is a class derived from B, if a valid standard conversion from "pointer - // to D" to "pointer to B" exists, cv2 >= cv1, and B is not a virtual base - // class of D. - // In addition, DR54 clarifies that the base must be accessible in the - // current context. - - const PointerType *SrcPointer = SrcType->getAsPointerType(); - if (!SrcPointer) { - return TSC_NotApplicable; - } - - const PointerType *DestPointer = DestType->getAsPointerType(); - if (!DestPointer) { - return TSC_NotApplicable; - } - - return TryStaticDowncast(Self, SrcPointer->getPointeeType(), - DestPointer->getPointeeType(), - OpRange, SrcType, DestType); -} - -/// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and -/// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to -/// DestType, both of which must be canonical, is possible and allowed. -TryStaticCastResult -TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, - const SourceRange &OpRange, QualType OrigSrcType, - QualType OrigDestType) -{ - // Downcast can only happen in class hierarchies, so we need classes. - if (!DestType->isRecordType() || !SrcType->isRecordType()) { - return TSC_NotApplicable; - } - - BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false, - /*DetectVirtual=*/true); - if (!Self.IsDerivedFrom(DestType, SrcType, Paths)) { - return TSC_NotApplicable; - } - - // Target type does derive from source type. Now we're serious. If an error - // appears now, it's not ignored. - // This may not be entirely in line with the standard. Take for example: - // struct A {}; - // struct B : virtual A { - // B(A&); - // }; - // - // void f() - // { - // (void)static_cast<const B&>(*((A*)0)); - // } - // As far as the standard is concerned, p5 does not apply (A is virtual), so - // p2 should be used instead - "const B& t(*((A*)0));" is perfectly valid. - // However, both GCC and Comeau reject this example, and accepting it would - // mean more complex code if we're to preserve the nice error message. - // FIXME: Being 100% compliant here would be nice to have. - - // Must preserve cv, as always. - if (!DestType.isAtLeastAsQualifiedAs(SrcType)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) - << "static_cast" << OrigDestType << OrigSrcType << OpRange; - return TSC_Failed; - } - - if (Paths.isAmbiguous(SrcType.getUnqualifiedType())) { - // This code is analoguous to that in CheckDerivedToBaseConversion, except - // that it builds the paths in reverse order. - // To sum up: record all paths to the base and build a nice string from - // them. Use it to spice up the error message. - Paths.clear(); - Paths.setRecordingPaths(true); - Self.IsDerivedFrom(DestType, SrcType, Paths); - std::string PathDisplayStr; - std::set<unsigned> DisplayedPaths; - for (BasePaths::paths_iterator Path = Paths.begin(); - Path != Paths.end(); ++Path) { - if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { - // We haven't displayed a path to this particular base - // class subobject yet. - PathDisplayStr += "\n "; - for (BasePath::const_reverse_iterator Element = Path->rbegin(); - Element != Path->rend(); ++Element) - PathDisplayStr += Element->Base->getType().getAsString() + " -> "; - PathDisplayStr += DestType.getAsString(); - } - } - - Self.Diag(OpRange.getBegin(), diag::err_ambiguous_base_to_derived_cast) - << SrcType.getUnqualifiedType() << DestType.getUnqualifiedType() - << PathDisplayStr << OpRange; - return TSC_Failed; - } - - if (Paths.getDetectedVirtual() != 0) { - QualType VirtualBase(Paths.getDetectedVirtual(), 0); - Self.Diag(OpRange.getBegin(), diag::err_static_downcast_via_virtual) - << OrigSrcType << OrigDestType << VirtualBase << OpRange; - return TSC_Failed; - } - - // FIXME: Test accessibility. - - return TSC_Success; -} - -/// TryStaticMemberPointerUpcast - Tests whether a conversion according to -/// C++ 5.2.9p9 is valid: -/// -/// An rvalue of type "pointer to member of D of type cv1 T" can be -/// converted to an rvalue of type "pointer to member of B of type cv2 T", -/// where B is a base class of D [...]. -/// -TryStaticCastResult -TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, - const SourceRange &OpRange) -{ - const MemberPointerType *SrcMemPtr = SrcType->getAsMemberPointerType(); - if (!SrcMemPtr) - return TSC_NotApplicable; - const MemberPointerType *DestMemPtr = DestType->getAsMemberPointerType(); - if (!DestMemPtr) - return TSC_NotApplicable; - - // T == T, modulo cv - if (Self.Context.getCanonicalType( - SrcMemPtr->getPointeeType().getUnqualifiedType()) != - Self.Context.getCanonicalType(DestMemPtr->getPointeeType(). - getUnqualifiedType())) - return TSC_NotApplicable; - - // B base of D - QualType SrcClass(SrcMemPtr->getClass(), 0); - QualType DestClass(DestMemPtr->getClass(), 0); - BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false, - /*DetectVirtual=*/true); - if (!Self.IsDerivedFrom(SrcClass, DestClass, Paths)) { - return TSC_NotApplicable; - } - - // B is a base of D. But is it an allowed base? If not, it's a hard error. - if (Paths.isAmbiguous(DestClass)) { - Paths.clear(); - Paths.setRecordingPaths(true); - bool StillOkay = Self.IsDerivedFrom(SrcClass, DestClass, Paths); - assert(StillOkay); - StillOkay = StillOkay; - std::string PathDisplayStr = Self.getAmbiguousPathsDisplayString(Paths); - Self.Diag(OpRange.getBegin(), diag::err_ambiguous_memptr_conv) - << 1 << SrcClass << DestClass << PathDisplayStr << OpRange; - return TSC_Failed; - } - - if (const RecordType *VBase = Paths.getDetectedVirtual()) { - Self.Diag(OpRange.getBegin(), diag::err_memptr_conv_via_virtual) - << SrcClass << DestClass << QualType(VBase, 0) << OpRange; - return TSC_Failed; - } - - // FIXME: Test accessibility. - - return TSC_Success; -} - -/// TryStaticImplicitCast - Tests whether a conversion according to C++ 5.2.9p2 -/// is valid: -/// -/// An expression e can be explicitly converted to a type T using a -/// @c static_cast if the declaration "T t(e);" is well-formed [...]. -TryStaticCastResult -TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, - const SourceRange &OpRange) -{ - if (DestType->isReferenceType()) { - // At this point of CheckStaticCast, if the destination is a reference, - // this has to work. There is no other way that works. - return Self.CheckReferenceInit(SrcExpr, DestType) ? - TSC_Failed : TSC_Success; - } - if (DestType->isRecordType()) { - // FIXME: Use an implementation of C++ [over.match.ctor] for this. - return TSC_NotApplicable; - } - - // FIXME: To get a proper error from invalid conversions here, we need to - // reimplement more of this. - ImplicitConversionSequence ICS = Self.TryImplicitConversion( - SrcExpr, DestType); - return ICS.ConversionKind == ImplicitConversionSequence::BadConversion ? - TSC_NotApplicable : TSC_Success; -} - -/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid. -/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime- -/// checked downcasts in class hierarchies. -void -CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, - const SourceRange &OpRange, - const SourceRange &DestRange) -{ - QualType OrigDestType = DestType, OrigSrcType = SrcExpr->getType(); - DestType = Self.Context.getCanonicalType(DestType); - - // C++ 5.2.7p1: T shall be a pointer or reference to a complete class type, - // or "pointer to cv void". - - QualType DestPointee; - const PointerType *DestPointer = DestType->getAsPointerType(); - const ReferenceType *DestReference = DestType->getAsReferenceType(); - if (DestPointer) { - DestPointee = DestPointer->getPointeeType(); - } else if (DestReference) { - DestPointee = DestReference->getPointeeType(); - } else { - Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr) - << OrigDestType << DestRange; - return; - } - - const RecordType *DestRecord = DestPointee->getAsRecordType(); - if (DestPointee->isVoidType()) { - assert(DestPointer && "Reference to void is not possible"); - } else if (DestRecord) { - if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee, - diag::err_bad_dynamic_cast_incomplete, - DestRange)) - return; - } else { - Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) - << DestPointee.getUnqualifiedType() << DestRange; - return; - } - - // C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to - // complete class type, [...]. If T is an lvalue reference type, v shall be - // an lvalue of a complete class type, [...]. If T is an rvalue reference - // type, v shall be an expression having a complete effective class type, - // [...] - - QualType SrcType = Self.Context.getCanonicalType(OrigSrcType); - QualType SrcPointee; - if (DestPointer) { - if (const PointerType *SrcPointer = SrcType->getAsPointerType()) { - SrcPointee = SrcPointer->getPointeeType(); - } else { - Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr) - << OrigSrcType << SrcExpr->getSourceRange(); - return; - } - } else if (DestReference->isLValueReferenceType()) { - if (SrcExpr->isLvalue(Self.Context) != Expr::LV_Valid) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue) - << "dynamic_cast" << OrigDestType << OpRange; - } - SrcPointee = SrcType; - } else { - SrcPointee = SrcType; - } - - const RecordType *SrcRecord = SrcPointee->getAsRecordType(); - if (SrcRecord) { - if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee, - diag::err_bad_dynamic_cast_incomplete, - SrcExpr->getSourceRange())) - return; - } else { - Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class) - << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange(); - return; - } - - assert((DestPointer || DestReference) && - "Bad destination non-ptr/ref slipped through."); - assert((DestRecord || DestPointee->isVoidType()) && - "Bad destination pointee slipped through."); - assert(SrcRecord && "Bad source pointee slipped through."); - - // C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness. - if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) { - Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_const_away) - << "dynamic_cast" << OrigDestType << OrigSrcType << OpRange; - return; - } - - // C++ 5.2.7p3: If the type of v is the same as the required result type, - // [except for cv]. - if (DestRecord == SrcRecord) { - return; - } - - // C++ 5.2.7p5 - // Upcasts are resolved statically. - if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) { - Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee, - OpRange.getBegin(), OpRange); - // Diagnostic already emitted on error. - return; - } - - // C++ 5.2.7p6: Otherwise, v shall be [polymorphic]. - const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(Self.Context); - assert(SrcDecl && "Definition missing"); - if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) { - Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) - << SrcPointee.getUnqualifiedType() << SrcExpr->getSourceRange(); - } - - // Done. Everything else is run-time checks. -} diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp deleted file mode 100644 index c82e1a7..0000000 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ /dev/null @@ -1,1350 +0,0 @@ -//===--- SemaTemplateInstantiateExpr.cpp - C++ Template Expr Instantiation ===/ -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===/ -// -// This file implements C++ template instantiation for expressions. -// -//===----------------------------------------------------------------------===/ -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/Parse/DeclSpec.h" -#include "clang/Parse/Designator.h" -#include "clang/Lex/Preprocessor.h" // for the identifier table -#include "llvm/Support/Compiler.h" -using namespace clang; - -namespace { - class VISIBILITY_HIDDEN TemplateExprInstantiator - : public StmtVisitor<TemplateExprInstantiator, Sema::OwningExprResult> { - Sema &SemaRef; - const TemplateArgumentList &TemplateArgs; - - public: - typedef Sema::OwningExprResult OwningExprResult; - - TemplateExprInstantiator(Sema &SemaRef, - const TemplateArgumentList &TemplateArgs) - : SemaRef(SemaRef), TemplateArgs(TemplateArgs) { } - - // Declare VisitXXXStmt nodes for all of the expression kinds. -#define EXPR(Type, Base) OwningExprResult Visit##Type(Type *S); -#define STMT(Type, Base) -#include "clang/AST/StmtNodes.def" - - // Base case. We can't get here. - Sema::OwningExprResult VisitStmt(Stmt *S) { - S->dump(); - assert(false && "Cannot instantiate this kind of expression"); - return SemaRef.ExprError(); - } - }; -} - -// Base case. We can't get here. -Sema::OwningExprResult TemplateExprInstantiator::VisitExpr(Expr *E) { - E->dump(); - assert(false && "Cannot instantiate this kind of expression"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitPredefinedExpr(PredefinedExpr *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitIntegerLiteral(IntegerLiteral *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitFloatingLiteral(FloatingLiteral *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitStringLiteral(StringLiteral *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCharacterLiteral(CharacterLiteral *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitImaginaryLiteral(ImaginaryLiteral *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitGNUNullExpr(GNUNullExpr *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr( - UnresolvedFunctionNameExpr *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitTemplateIdRefExpr(TemplateIdRefExpr *E) { - TemplateName Template - = SemaRef.InstantiateTemplateName(E->getTemplateName(), E->getTemplateNameLoc(), - TemplateArgs); - // FIXME: Can InstantiateTemplateName report an error? - - llvm::SmallVector<TemplateArgument, 4> InstantiatedArgs; - for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { - TemplateArgument InstArg = SemaRef.Instantiate(E->getTemplateArgs()[I], - TemplateArgs); - if (InstArg.isNull()) - return SemaRef.ExprError(); - - InstantiatedArgs.push_back(InstArg); - } - - // FIXME: It's possible that we'll find out now that the template name - // actually refers to a type, in which case this is a functional cast. - // Implement this! - - return SemaRef.BuildTemplateIdExpr(Template, E->getTemplateNameLoc(), - E->getLAngleLoc(), - InstantiatedArgs.data(), - InstantiatedArgs.size(), - E->getRAngleLoc()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { - NamedDecl *D = E->getDecl(); - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { - assert(NTTP->getDepth() == 0 && "No nested templates yet"); - - // If the corresponding template argument is NULL or non-existent, it's - // because we are performing instantiation from explicitly-specified - // template arguments in a function template, but there were some - // arguments left unspecified. - if (NTTP->getPosition() >= TemplateArgs.size() || - TemplateArgs[NTTP->getPosition()].isNull()) - return SemaRef.Owned(E); // FIXME: Clone the expression! - - const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; - - // The template argument itself might be an expression, in which - // case we just return that expression. - if (Arg.getKind() == TemplateArgument::Expression) - // FIXME: Clone the expression! - return SemaRef.Owned(Arg.getAsExpr()); - - if (Arg.getKind() == TemplateArgument::Declaration) { - ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); - - // FIXME: Can VD ever have a dependent type? - return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), - false, false); - } - - assert(Arg.getKind() == TemplateArgument::Integral); - QualType T = Arg.getIntegralType(); - if (T->isCharType() || T->isWideCharType()) - return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral( - Arg.getAsIntegral()->getZExtValue(), - T->isWideCharType(), - T, - E->getSourceRange().getBegin())); - if (T->isBooleanType()) - return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr( - Arg.getAsIntegral()->getBoolValue(), - T, - E->getSourceRange().getBegin())); - - assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T)); - return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral( - *Arg.getAsIntegral(), - T, - E->getSourceRange().getBegin())); - } - - if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) { - // FIXME: instantiate each decl in the overload set - return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Ovl, - SemaRef.Context.OverloadTy, - E->getLocation(), - false, false)); - } - - NamedDecl *InstD = SemaRef.InstantiateCurrentDeclRef(D); - if (!InstD) - return SemaRef.ExprError(); - - // FIXME: nested-name-specifier for QualifiedDeclRefExpr - return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, - /*FIXME:*/false, - /*FIXME:*/0, - /*FIXME:*/false); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitParenExpr(ParenExpr *E) { - Sema::OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.Owned(new (SemaRef.Context) ParenExpr( - E->getLParen(), E->getRParen(), - (Expr *)SubExpr.release())); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitUnaryOperator(UnaryOperator *E) { - Sema::OwningExprResult Arg = Visit(E->getSubExpr()); - if (Arg.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(), - E->getOpcode(), - move(Arg)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { - Sema::OwningExprResult LHS = Visit(E->getLHS()); - if (LHS.isInvalid()) - return SemaRef.ExprError(); - - Sema::OwningExprResult RHS = Visit(E->getRHS()); - if (RHS.isInvalid()) - return SemaRef.ExprError(); - - // Since the overloaded array-subscript operator (operator[]) can - // only be a member function, we can make several simplifying - // assumptions here: - // 1) Normal name lookup (from the current scope) will not ever - // find any declarations of operator[] that won't also be found be - // member operator lookup, so it is safe to pass a NULL Scope - // during the instantiation to avoid the lookup entirely. - // - // 2) Neither normal name lookup nor argument-dependent lookup at - // template definition time will find any operators that won't be - // found at template instantiation time, so we do not need to - // cache the results of name lookup as we do for the binary - // operators. - SourceLocation LLocFake = ((Expr*)LHS.get())->getSourceRange().getBegin(); - return SemaRef.ActOnArraySubscriptExpr(/*Scope=*/0, move(LHS), - /*FIXME:*/LLocFake, - move(RHS), - E->getRBracketLoc()); -} - -Sema::OwningExprResult TemplateExprInstantiator::VisitCallExpr(CallExpr *E) { - // Instantiate callee - OwningExprResult Callee = Visit(E->getCallee()); - if (Callee.isInvalid()) - return SemaRef.ExprError(); - - // Instantiate arguments - ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef); - llvm::SmallVector<SourceLocation, 4> FakeCommaLocs; - for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { - OwningExprResult Arg = Visit(E->getArg(I)); - if (Arg.isInvalid()) - return SemaRef.ExprError(); - - FakeCommaLocs.push_back( - SemaRef.PP.getLocForEndOfToken(E->getArg(I)->getSourceRange().getEnd())); - Args.push_back(Arg.takeAs<Expr>()); - } - - SourceLocation FakeLParenLoc - = ((Expr *)Callee.get())->getSourceRange().getBegin(); - return SemaRef.ActOnCallExpr(/*Scope=*/0, move(Callee), - /*FIXME:*/FakeLParenLoc, - move_arg(Args), - /*FIXME:*/&FakeCommaLocs.front(), - E->getRParenLoc()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitMemberExpr(MemberExpr *E) { - // Instantiate the base of the expression. - OwningExprResult Base = Visit(E->getBase()); - if (Base.isInvalid()) - return SemaRef.ExprError(); - - // FIXME: Handle declaration names here - SourceLocation FakeOperatorLoc = - SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd()); - return SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0, - move(Base), - /*FIXME*/FakeOperatorLoc, - E->isArrow()? tok::arrow - : tok::period, - E->getMemberLoc(), - /*FIXME:*/*E->getMemberDecl()->getIdentifier(), - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) { - SourceLocation FakeTypeLoc - = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc()); - QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs, - FakeTypeLoc, - DeclarationName()); - if (T.isNull()) - return SemaRef.ExprError(); - - OwningExprResult Init = Visit(E->getInitializer()); - if (Init.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.ActOnCompoundLiteral(E->getLParenLoc(), - T.getAsOpaquePtr(), - /*FIXME*/E->getLParenLoc(), - move(Init)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitBinaryOperator(BinaryOperator *E) { - Sema::OwningExprResult LHS = Visit(E->getLHS()); - if (LHS.isInvalid()) - return SemaRef.ExprError(); - - Sema::OwningExprResult RHS = Visit(E->getRHS()); - if (RHS.isInvalid()) - return SemaRef.ExprError(); - - Sema::OwningExprResult Result - = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), - E->getOpcode(), - (Expr *)LHS.get(), - (Expr *)RHS.get()); - if (Result.isInvalid()) - return SemaRef.ExprError(); - - LHS.release(); - RHS.release(); - return move(Result); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCompoundAssignOperator( - CompoundAssignOperator *E) { - return VisitBinaryOperator(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { - Sema::OwningExprResult First = Visit(E->getArg(0)); - if (First.isInvalid()) - return SemaRef.ExprError(); - - Expr *Args[2] = { (Expr *)First.get(), 0 }; - - Sema::OwningExprResult Second(SemaRef); - if (E->getNumArgs() == 2) { - Second = Visit(E->getArg(1)); - - if (Second.isInvalid()) - return SemaRef.ExprError(); - - Args[1] = (Expr *)Second.get(); - } - - if (!E->isTypeDependent()) { - // Since our original expression was not type-dependent, we do not - // perform lookup again at instantiation time (C++ [temp.dep]p1). - // Instead, we just build the new overloaded operator call - // expression. - OwningExprResult Callee = Visit(E->getCallee()); - if (Callee.isInvalid()) - return SemaRef.ExprError(); - - First.release(); - Second.release(); - - return SemaRef.Owned(new (SemaRef.Context) CXXOperatorCallExpr( - SemaRef.Context, - E->getOperator(), - Callee.takeAs<Expr>(), - Args, E->getNumArgs(), - E->getType(), - E->getOperatorLoc())); - } - - bool isPostIncDec = E->getNumArgs() == 2 && - (E->getOperator() == OO_PlusPlus || E->getOperator() == OO_MinusMinus); - if (E->getNumArgs() == 1 || isPostIncDec) { - if (!Args[0]->getType()->isOverloadableType()) { - // The argument is not of overloadable type, so try to create a - // built-in unary operation. - UnaryOperator::Opcode Opc - = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec); - - return SemaRef.CreateBuiltinUnaryOp(E->getOperatorLoc(), Opc, - move(First)); - } - - // Fall through to perform overload resolution - } else { - assert(E->getNumArgs() == 2 && "Expected binary operation"); - - Sema::OwningExprResult Result(SemaRef); - if (!Args[0]->getType()->isOverloadableType() && - !Args[1]->getType()->isOverloadableType()) { - // Neither of the arguments is an overloadable type, so try to - // create a built-in binary operation. - BinaryOperator::Opcode Opc = - BinaryOperator::getOverloadedOpcode(E->getOperator()); - Result = SemaRef.CreateBuiltinBinOp(E->getOperatorLoc(), Opc, - Args[0], Args[1]); - if (Result.isInvalid()) - return SemaRef.ExprError(); - - First.release(); - Second.release(); - return move(Result); - } - - // Fall through to perform overload resolution. - } - - // Compute the set of functions that were found at template - // definition time. - Sema::FunctionSet Functions; - DeclRefExpr *DRE = cast<DeclRefExpr>(E->getCallee()); - OverloadedFunctionDecl *Overloads - = cast<OverloadedFunctionDecl>(DRE->getDecl()); - - // FIXME: Do we have to check - // IsAcceptableNonMemberOperatorCandidate for each of these? - for (OverloadedFunctionDecl::function_iterator - F = Overloads->function_begin(), - FEnd = Overloads->function_end(); - F != FEnd; ++F) - Functions.insert(cast<FunctionDecl>(*F)); - - // Add any functions found via argument-dependent lookup. - DeclarationName OpName - = SemaRef.Context.DeclarationNames.getCXXOperatorName(E->getOperator()); - SemaRef.ArgumentDependentLookup(OpName, Args, E->getNumArgs(), Functions); - - // Create the overloaded operator invocation. - if (E->getNumArgs() == 1 || isPostIncDec) { - UnaryOperator::Opcode Opc - = UnaryOperator::getOverloadedOpcode(E->getOperator(), isPostIncDec); - return SemaRef.CreateOverloadedUnaryOp(E->getOperatorLoc(), Opc, - Functions, move(First)); - } - - // FIXME: This would be far less ugly if CreateOverloadedBinOp took in ExprArg - // arguments! - BinaryOperator::Opcode Opc = - BinaryOperator::getOverloadedOpcode(E->getOperator()); - OwningExprResult Result - = SemaRef.CreateOverloadedBinOp(E->getOperatorLoc(), Opc, - Functions, Args[0], Args[1]); - - if (Result.isInvalid()) - return SemaRef.ExprError(); - - First.release(); - Second.release(); - return move(Result); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E) { - VarDecl *Var - = cast_or_null<VarDecl>(SemaRef.InstantiateDecl(E->getVarDecl(), - SemaRef.CurContext, - TemplateArgs)); - if (!Var) - return SemaRef.ExprError(); - - SemaRef.CurrentInstantiationScope->InstantiatedLocal(E->getVarDecl(), Var); - return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr( - E->getStartLoc(), - SourceLocation(), - Var)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitConditionalOperator(ConditionalOperator *E) { - Sema::OwningExprResult Cond = Visit(E->getCond()); - if (Cond.isInvalid()) - return SemaRef.ExprError(); - - Sema::OwningExprResult LHS = SemaRef.InstantiateExpr(E->getLHS(), - TemplateArgs); - if (LHS.isInvalid()) - return SemaRef.ExprError(); - - Sema::OwningExprResult RHS = Visit(E->getRHS()); - if (RHS.isInvalid()) - return SemaRef.ExprError(); - - if (!E->isTypeDependent()) { - // Since our original expression was not type-dependent, we do not - // perform lookup again at instantiation time (C++ [temp.dep]p1). - // Instead, we just build the new conditional operator call expression. - return SemaRef.Owned(new (SemaRef.Context) ConditionalOperator( - Cond.takeAs<Expr>(), - LHS.takeAs<Expr>(), - RHS.takeAs<Expr>(), - E->getType())); - } - - - return SemaRef.ActOnConditionalOp(/*FIXME*/E->getCond()->getLocEnd(), - /*FIXME*/E->getFalseExpr()->getLocStart(), - move(Cond), move(LHS), move(RHS)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitAddrLabelExpr(AddrLabelExpr *E) { - return SemaRef.ActOnAddrLabel(E->getAmpAmpLoc(), - E->getLabelLoc(), - E->getLabel()->getID()); -} - -Sema::OwningExprResult TemplateExprInstantiator::VisitStmtExpr(StmtExpr *E) { - Sema::OwningStmtResult SubStmt - = SemaRef.InstantiateCompoundStmt(E->getSubStmt(), TemplateArgs, true); - if (SubStmt.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.ActOnStmtExpr(E->getLParenLoc(), move(SubStmt), - E->getRParenLoc()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) { - assert(false && "__builtin_types_compatible_p is not legal in C++"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { - ASTOwningVector<&ActionBase::DeleteExpr> SubExprs(SemaRef); - for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) { - OwningExprResult SubExpr = Visit(E->getExpr(I)); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - SubExprs.push_back(SubExpr.takeAs<Expr>()); - } - - // Find the declaration for __builtin_shufflevector - const IdentifierInfo &Name - = SemaRef.Context.Idents.get("__builtin_shufflevector"); - TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl(); - DeclContext::lookup_result Lookup = TUDecl->lookup(DeclarationName(&Name)); - assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?"); - - // Build a reference to the __builtin_shufflevector builtin - FunctionDecl *Builtin = cast<FunctionDecl>(*Lookup.first); - Expr *Callee = new (SemaRef.Context) DeclRefExpr(Builtin, Builtin->getType(), - E->getBuiltinLoc(), - false, false); - SemaRef.UsualUnaryConversions(Callee); - - // Build the CallExpr - CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, - SubExprs.takeAs<Expr>(), - SubExprs.size(), - Builtin->getResultType(), - E->getRParenLoc()); - OwningExprResult OwnedCall(SemaRef.Owned(TheCall)); - - // Type-check the __builtin_shufflevector expression. - OwningExprResult Result = SemaRef.SemaBuiltinShuffleVector(TheCall); - if (Result.isInvalid()) - return SemaRef.ExprError(); - - OwnedCall.release(); - return move(Result); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitChooseExpr(ChooseExpr *E) { - OwningExprResult Cond = Visit(E->getCond()); - if (Cond.isInvalid()) - return SemaRef.ExprError(); - - OwningExprResult LHS = SemaRef.InstantiateExpr(E->getLHS(), TemplateArgs); - if (LHS.isInvalid()) - return SemaRef.ExprError(); - - OwningExprResult RHS = Visit(E->getRHS()); - if (RHS.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.ActOnChooseExpr(E->getBuiltinLoc(), - move(Cond), move(LHS), move(RHS), - E->getRParenLoc()); -} - -Sema::OwningExprResult TemplateExprInstantiator::VisitVAArgExpr(VAArgExpr *E) { - OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - SourceLocation FakeTypeLoc - = SemaRef.PP.getLocForEndOfToken(E->getSubExpr()->getSourceRange() - .getEnd()); - QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs, - /*FIXME:*/FakeTypeLoc, - DeclarationName()); - if (T.isNull()) - return SemaRef.ExprError(); - - return SemaRef.ActOnVAArg(E->getBuiltinLoc(), move(SubExpr), - T.getAsOpaquePtr(), E->getRParenLoc()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitInitListExpr(InitListExpr *E) { - ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef); - for (unsigned I = 0, N = E->getNumInits(); I != N; ++I) { - OwningExprResult Init = Visit(E->getInit(I)); - if (Init.isInvalid()) - return SemaRef.ExprError(); - Inits.push_back(Init.takeAs<Expr>()); - } - - return SemaRef.ActOnInitList(E->getLBraceLoc(), move_arg(Inits), - E->getRBraceLoc()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitDesignatedInitExpr(DesignatedInitExpr *E) { - Designation Desig; - - // Instantiate the initializer value - OwningExprResult Init = Visit(E->getInit()); - if (Init.isInvalid()) - return SemaRef.ExprError(); - - // Instantiate the designators. - ASTOwningVector<&ActionBase::DeleteExpr, 4> ArrayExprs(SemaRef); - for (DesignatedInitExpr::designators_iterator D = E->designators_begin(), - DEnd = E->designators_end(); - D != DEnd; ++D) { - if (D->isFieldDesignator()) { - Desig.AddDesignator(Designator::getField(D->getFieldName(), - D->getDotLoc(), - D->getFieldLoc())); - continue; - } - - if (D->isArrayDesignator()) { - OwningExprResult Index = Visit(E->getArrayIndex(*D)); - if (Index.isInvalid()) - return SemaRef.ExprError(); - - Desig.AddDesignator(Designator::getArray(Index.get(), - D->getLBracketLoc())); - - ArrayExprs.push_back(Index.release()); - continue; - } - - assert(D->isArrayRangeDesignator() && "New kind of designator?"); - OwningExprResult Start = Visit(E->getArrayRangeStart(*D)); - if (Start.isInvalid()) - return SemaRef.ExprError(); - - OwningExprResult End = Visit(E->getArrayRangeEnd(*D)); - if (End.isInvalid()) - return SemaRef.ExprError(); - - Desig.AddDesignator(Designator::getArrayRange(Start.get(), - End.get(), - D->getLBracketLoc(), - D->getEllipsisLoc())); - - ArrayExprs.push_back(Start.release()); - ArrayExprs.push_back(End.release()); - } - - OwningExprResult Result = - SemaRef.ActOnDesignatedInitializer(Desig, - E->getEqualOrColonLoc(), - E->usesGNUSyntax(), - move(Init)); - if (Result.isInvalid()) - return SemaRef.ExprError(); - - ArrayExprs.take(); - return move(Result); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitImplicitValueInitExpr( - ImplicitValueInitExpr *E) { - assert(!E->isTypeDependent() && !E->isValueDependent() && - "ImplicitValueInitExprs are never dependent"); - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitExtVectorElementExpr(ExtVectorElementExpr *E) { - OwningExprResult Base = Visit(E->getBase()); - if (Base.isInvalid()) - return SemaRef.ExprError(); - - SourceLocation FakeOperatorLoc = - SemaRef.PP.getLocForEndOfToken(E->getBase()->getSourceRange().getEnd()); - return SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0, - move(Base), - /*FIXME*/FakeOperatorLoc, - tok::period, - E->getAccessorLoc(), - E->getAccessor(), - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitBlockExpr(BlockExpr *E) { - assert(false && "FIXME:Template instantiation for blocks is unimplemented"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitBlockDeclRefExpr(BlockDeclRefExpr *E) { - assert(false && "FIXME:Template instantiation for blocks is unimplemented"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { - bool isSizeOf = E->isSizeOf(); - - if (E->isArgumentType()) { - QualType T = E->getArgumentType(); - if (T->isDependentType()) { - T = SemaRef.InstantiateType(T, TemplateArgs, - /*FIXME*/E->getOperatorLoc(), - &SemaRef.PP.getIdentifierTable().get("sizeof")); - if (T.isNull()) - return SemaRef.ExprError(); - } - - return SemaRef.CreateSizeOfAlignOfExpr(T, E->getOperatorLoc(), isSizeOf, - E->getSourceRange()); - } - - Sema::OwningExprResult Arg(SemaRef); - { - // C++0x [expr.sizeof]p1: - // The operand is either an expression, which is an unevaluated operand - // [...] - EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); - - Arg = Visit(E->getArgumentExpr()); - if (Arg.isInvalid()) - return SemaRef.ExprError(); - } - - Sema::OwningExprResult Result - = SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(), - isSizeOf, E->getSourceRange()); - if (Result.isInvalid()) - return SemaRef.ExprError(); - - Arg.release(); - return move(Result); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *E) { - NestedNameSpecifier *NNS - = SemaRef.InstantiateNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange(), - TemplateArgs); - if (!NNS) - return SemaRef.ExprError(); - - CXXScopeSpec SS; - SS.setRange(E->getQualifierRange()); - SS.setScopeRep(NNS); - - // FIXME: We're passing in a NULL scope, because - // ActOnDeclarationNameExpr doesn't actually use the scope when we - // give it a non-empty scope specifier. Investigate whether it would - // be better to refactor ActOnDeclarationNameExpr. - return SemaRef.ActOnDeclarationNameExpr(/*Scope=*/0, E->getLocation(), - E->getDeclName(), - /*HasTrailingLParen=*/false, - &SS, - /*FIXME:isAddressOfOperand=*/false); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXTemporaryObjectExpr( - CXXTemporaryObjectExpr *E) { - QualType T = E->getType(); - if (T->isDependentType()) { - T = SemaRef.InstantiateType(T, TemplateArgs, - E->getTypeBeginLoc(), DeclarationName()); - if (T.isNull()) - return SemaRef.ExprError(); - } - - ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef); - Args.reserve(E->getNumArgs()); - for (CXXTemporaryObjectExpr::arg_iterator Arg = E->arg_begin(), - ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) { - OwningExprResult InstantiatedArg = Visit(*Arg); - if (InstantiatedArg.isInvalid()) - return SemaRef.ExprError(); - - Args.push_back((Expr *)InstantiatedArg.release()); - } - - SourceLocation CommaLoc; - // FIXME: HACK! - if (Args.size() > 1) { - Expr *First = (Expr *)Args[0]; - CommaLoc - = SemaRef.PP.getLocForEndOfToken(First->getSourceRange().getEnd()); - } - return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc() - /*, FIXME*/), - T.getAsOpaquePtr(), - /*FIXME*/E->getTypeBeginLoc(), - move_arg(Args), - /*HACK*/&CommaLoc, - E->getSourceRange().getEnd()); -} - -Sema::OwningExprResult TemplateExprInstantiator::VisitCastExpr(CastExpr *E) { - assert(false && "Cannot instantiate abstract CastExpr"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult TemplateExprInstantiator::VisitImplicitCastExpr( - ImplicitCastExpr *E) { - assert(!E->isTypeDependent() && "Implicit casts must have known types"); - - Sema::OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - ImplicitCastExpr *ICE = - new (SemaRef.Context) ImplicitCastExpr(E->getType(), - (Expr *)SubExpr.release(), - E->isLvalueCast()); - return SemaRef.Owned(ICE); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitExplicitCastExpr(ExplicitCastExpr *E) { - assert(false && "Cannot instantiate abstract ExplicitCastExpr"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCStyleCastExpr(CStyleCastExpr *E) { - // Instantiate the type that we're casting to. - SourceLocation TypeStartLoc - = SemaRef.PP.getLocForEndOfToken(E->getLParenLoc()); - QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(), - TemplateArgs, - TypeStartLoc, - DeclarationName()); - if (ExplicitTy.isNull()) - return SemaRef.ExprError(); - - // Instantiate the subexpression. - OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.ActOnCastExpr(E->getLParenLoc(), - ExplicitTy.getAsOpaquePtr(), - E->getRParenLoc(), - move(SubExpr)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { - return VisitCallExpr(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXNamedCastExpr(CXXNamedCastExpr *E) { - // Figure out which cast operator we're dealing with. - tok::TokenKind Kind; - switch (E->getStmtClass()) { - case Stmt::CXXStaticCastExprClass: - Kind = tok::kw_static_cast; - break; - - case Stmt::CXXDynamicCastExprClass: - Kind = tok::kw_dynamic_cast; - break; - - case Stmt::CXXReinterpretCastExprClass: - Kind = tok::kw_reinterpret_cast; - break; - - case Stmt::CXXConstCastExprClass: - Kind = tok::kw_const_cast; - break; - - default: - assert(false && "Invalid C++ named cast"); - return SemaRef.ExprError(); - } - - // Instantiate the type that we're casting to. - SourceLocation TypeStartLoc - = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc()); - QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(), - TemplateArgs, - TypeStartLoc, - DeclarationName()); - if (ExplicitTy.isNull()) - return SemaRef.ExprError(); - - // Instantiate the subexpression. - OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - SourceLocation FakeLAngleLoc - = SemaRef.PP.getLocForEndOfToken(E->getOperatorLoc()); - SourceLocation FakeRAngleLoc = E->getSubExpr()->getSourceRange().getBegin(); - SourceLocation FakeRParenLoc - = SemaRef.PP.getLocForEndOfToken( - E->getSubExpr()->getSourceRange().getEnd()); - return SemaRef.ActOnCXXNamedCast(E->getOperatorLoc(), Kind, - /*FIXME:*/FakeLAngleLoc, - ExplicitTy.getAsOpaquePtr(), - /*FIXME:*/FakeRAngleLoc, - /*FIXME:*/FakeRAngleLoc, - move(SubExpr), - /*FIXME:*/FakeRParenLoc); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXStaticCastExpr(CXXStaticCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXReinterpretCastExpr( - CXXReinterpretCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXConstCastExpr(CXXConstCastExpr *E) { - return VisitCXXNamedCastExpr(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXThisExpr(CXXThisExpr *E) { - QualType ThisType = - cast<CXXMethodDecl>(SemaRef.CurContext)->getThisType(SemaRef.Context); - - CXXThisExpr *TE = - new (SemaRef.Context) CXXThisExpr(E->getLocStart(), ThisType); - - return SemaRef.Owned(TE); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXTypeidExpr(CXXTypeidExpr *E) { - if (E->isTypeOperand()) { - QualType T = SemaRef.InstantiateType(E->getTypeOperand(), - TemplateArgs, - /*FIXME*/E->getSourceRange().getBegin(), - DeclarationName()); - if (T.isNull()) - return SemaRef.ExprError(); - - return SemaRef.ActOnCXXTypeid(E->getSourceRange().getBegin(), - /*FIXME*/E->getSourceRange().getBegin(), - true, T.getAsOpaquePtr(), - E->getSourceRange().getEnd()); - } - - // We don't know whether the expression is potentially evaluated until - // after we perform semantic analysis, so the expression is potentially - // potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, - Action::PotentiallyPotentiallyEvaluated); - - OwningExprResult Operand = Visit(E->getExprOperand()); - if (Operand.isInvalid()) - return SemaRef.ExprError(); - - OwningExprResult Result - = SemaRef.ActOnCXXTypeid(E->getSourceRange().getBegin(), - /*FIXME*/E->getSourceRange().getBegin(), - false, Operand.get(), - E->getSourceRange().getEnd()); - if (Result.isInvalid()) - return SemaRef.ExprError(); - - Operand.release(); // FIXME: since ActOnCXXTypeid silently took ownership - return move(Result); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXThrowExpr(CXXThrowExpr *E) { - OwningExprResult SubExpr(SemaRef, (void *)0); - if (E->getSubExpr()) { - SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - } - - return SemaRef.ActOnCXXThrow(E->getThrowLoc(), move(SubExpr)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) { - assert(false && - "FIXME: Instantiation for default arguments is unimplemented"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXBindTemporaryExpr( - CXXBindTemporaryExpr *E) { - OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.MaybeBindToTemporary(SubExpr.takeAs<Expr>()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXConstructExpr(CXXConstructExpr *E) { - assert(!cast<CXXRecordDecl>(E->getConstructor()->getDeclContext()) - ->isDependentType() && "Dependent constructor shouldn't be here"); - - QualType T = SemaRef.InstantiateType(E->getType(), TemplateArgs, - /*FIXME*/E->getSourceRange().getBegin(), - DeclarationName()); - if (T.isNull()) - return SemaRef.ExprError(); - - ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef); - for (CXXConstructExpr::arg_iterator Arg = E->arg_begin(), - ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) { - OwningExprResult ArgInst = Visit(*Arg); - if (ArgInst.isInvalid()) - return SemaRef.ExprError(); - - Args.push_back(ArgInst.takeAs<Expr>()); - } - - return SemaRef.Owned(CXXConstructExpr::Create(SemaRef.Context, T, - E->getConstructor(), - E->isElidable(), - Args.takeAs<Expr>(), - Args.size())); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXFunctionalCastExpr( - CXXFunctionalCastExpr *E) { - // Instantiate the type that we're casting to. - QualType ExplicitTy = SemaRef.InstantiateType(E->getTypeAsWritten(), - TemplateArgs, - E->getTypeBeginLoc(), - DeclarationName()); - if (ExplicitTy.isNull()) - return SemaRef.ExprError(); - - // Instantiate the subexpression. - OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - // FIXME: The end of the type's source range is wrong - Expr *Sub = SubExpr.takeAs<Expr>(); - return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc()), - ExplicitTy.getAsOpaquePtr(), - /*FIXME:*/E->getTypeBeginLoc(), - Sema::MultiExprArg(SemaRef, - (void **)&Sub, - 1), - 0, - E->getRParenLoc()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { - return SemaRef.Clone(E); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXNewExpr(CXXNewExpr *E) { - // Instantiate the type that we're allocating - QualType AllocType = SemaRef.InstantiateType(E->getAllocatedType(), - TemplateArgs, - /*FIXME:*/E->getSourceRange().getBegin(), - DeclarationName()); - if (AllocType.isNull()) - return SemaRef.ExprError(); - - // Instantiate the size of the array we're allocating (if any). - OwningExprResult ArraySize = SemaRef.InstantiateExpr(E->getArraySize(), - TemplateArgs); - if (ArraySize.isInvalid()) - return SemaRef.ExprError(); - - // Instantiate the placement arguments (if any). - ASTOwningVector<&ActionBase::DeleteExpr> PlacementArgs(SemaRef); - for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) { - OwningExprResult Arg = Visit(E->getPlacementArg(I)); - if (Arg.isInvalid()) - return SemaRef.ExprError(); - - PlacementArgs.push_back(Arg.take()); - } - - // Instantiate the constructor arguments (if any). - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(SemaRef); - for (unsigned I = 0, N = E->getNumConstructorArgs(); I != N; ++I) { - OwningExprResult Arg = Visit(E->getConstructorArg(I)); - if (Arg.isInvalid()) - return SemaRef.ExprError(); - - ConstructorArgs.push_back(Arg.take()); - } - - return SemaRef.BuildCXXNew(E->getSourceRange().getBegin(), - E->isGlobalNew(), - /*FIXME*/SourceLocation(), - move_arg(PlacementArgs), - /*FIXME*/SourceLocation(), - E->isParenTypeId(), - AllocType, - /*FIXME*/E->getSourceRange().getBegin(), - SourceRange(), - move(ArraySize), - /*FIXME*/SourceLocation(), - Sema::MultiExprArg(SemaRef, - ConstructorArgs.take(), - ConstructorArgs.size()), - E->getSourceRange().getEnd()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXDeleteExpr(CXXDeleteExpr *E) { - OwningExprResult Operand = Visit(E->getArgument()); - if (Operand.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.ActOnCXXDelete(E->getSourceRange().getBegin(), - E->isGlobalDelete(), - E->isArrayForm(), - move(Operand)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { - QualType T = SemaRef.InstantiateType(E->getQueriedType(), TemplateArgs, - /*FIXME*/E->getSourceRange().getBegin(), - DeclarationName()); - if (T.isNull()) - return SemaRef.ExprError(); - - SourceLocation FakeLParenLoc - = SemaRef.PP.getLocForEndOfToken(E->getSourceRange().getBegin()); - return SemaRef.ActOnUnaryTypeTrait(E->getTrait(), - E->getSourceRange().getBegin(), - /*FIXME*/FakeLParenLoc, - T.getAsOpaquePtr(), - E->getSourceRange().getEnd()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) { - NestedNameSpecifier *NNS - = SemaRef.InstantiateNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange(), - TemplateArgs); - if (!NNS) - return SemaRef.ExprError(); - - CXXScopeSpec SS; - SS.setRange(E->getQualifierRange()); - SS.setScopeRep(NNS); - return SemaRef.ActOnDeclarationNameExpr(/*Scope=*/0, - E->getLocation(), - E->getDecl()->getDeclName(), - /*Trailing lparen=*/false, - &SS, - /*FIXME:*/false); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXExprWithTemporaries( - CXXExprWithTemporaries *E) { - OwningExprResult SubExpr = Visit(E->getSubExpr()); - if (SubExpr.isInvalid()) - return SemaRef.ExprError(); - - Expr *Temp = - SemaRef.MaybeCreateCXXExprWithTemporaries(SubExpr.takeAs<Expr>(), - E->shouldDestroyTemporaries()); - return SemaRef.Owned(Temp); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXUnresolvedConstructExpr( - CXXUnresolvedConstructExpr *E) { - QualType T = SemaRef.InstantiateType(E->getTypeAsWritten(), TemplateArgs, - E->getTypeBeginLoc(), - DeclarationName()); - if (T.isNull()) - return SemaRef.ExprError(); - - ASTOwningVector<&ActionBase::DeleteExpr> Args(SemaRef); - llvm::SmallVector<SourceLocation, 8> FakeCommaLocs; - for (CXXUnresolvedConstructExpr::arg_iterator Arg = E->arg_begin(), - ArgEnd = E->arg_end(); - Arg != ArgEnd; ++Arg) { - OwningExprResult InstArg = Visit(*Arg); - if (InstArg.isInvalid()) - return SemaRef.ExprError(); - - FakeCommaLocs.push_back( - SemaRef.PP.getLocForEndOfToken((*Arg)->getSourceRange().getEnd())); - Args.push_back(InstArg.takeAs<Expr>()); - } - - // FIXME: The end of the type range isn't exactly correct. - // FIXME: we're faking the locations of the commas - return SemaRef.ActOnCXXTypeConstructExpr(SourceRange(E->getTypeBeginLoc(), - E->getLParenLoc()), - T.getAsOpaquePtr(), - E->getLParenLoc(), - move_arg(Args), - &FakeCommaLocs.front(), - E->getRParenLoc()); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitCXXUnresolvedMemberExpr( - CXXUnresolvedMemberExpr *E) { - // Instantiate the base of the expression. - OwningExprResult Base = Visit(E->getBase()); - if (Base.isInvalid()) - return SemaRef.ExprError(); - - // FIXME: Instantiate the declaration name. - return SemaRef.ActOnMemberReferenceExpr(/*Scope=*/0, - move(Base), E->getOperatorLoc(), - E->isArrow()? tok::arrow - : tok::period, - E->getMemberLoc(), - /*FIXME:*/*E->getMember().getAsIdentifierInfo(), - /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0)); -} - -//---------------------------------------------------------------------------- -// Objective-C Expressions -//---------------------------------------------------------------------------- -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCStringLiteral(ObjCStringLiteral *E) { - return SemaRef.Owned(E->Clone(SemaRef.Context)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { - QualType EncodedType = SemaRef.InstantiateType(E->getEncodedType(), - TemplateArgs, - /*FIXME:*/E->getAtLoc(), - DeclarationName()); - if (EncodedType.isNull()) - return SemaRef.ExprError(); - - return SemaRef.Owned(SemaRef.BuildObjCEncodeExpression(E->getAtLoc(), - EncodedType, - E->getRParenLoc())); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCMessageExpr(ObjCMessageExpr *E) { - assert(false && "FIXME: Template instantiations for ObjC expressions"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCSelectorExpr(ObjCSelectorExpr *E) { - return SemaRef.Owned(E->Clone(SemaRef.Context)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCProtocolExpr(ObjCProtocolExpr *E) { - return SemaRef.Owned(E->Clone(SemaRef.Context)); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { - assert(false && "FIXME: Template instantiations for ObjC expressions"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - assert(false && "FIXME: Template instantiations for ObjC expressions"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCKVCRefExpr(ObjCKVCRefExpr *E) { - assert(false && "FIXME: Template instantiations for ObjC expressions"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -TemplateExprInstantiator::VisitObjCSuperExpr(ObjCSuperExpr *E) { - assert(false && "FIXME: Template instantiations for ObjC expressions"); - return SemaRef.ExprError(); -} - -Sema::OwningExprResult -Sema::InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs) { - if (!E) - return Owned((Expr *)0); - - TemplateExprInstantiator Instantiator(*this, TemplateArgs); - return Instantiator.Visit(E); -} diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp deleted file mode 100644 index 565b95b..0000000 --- a/lib/Sema/SemaTemplateInstantiateStmt.cpp +++ /dev/null @@ -1,450 +0,0 @@ -//===--- SemaTemplateInstantiateStmt.cpp - C++ Template Stmt Instantiation ===/ -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===/ -// -// This file implements C++ template instantiation for statements. -// -//===----------------------------------------------------------------------===/ -#include "Sema.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/StmtVisitor.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprCXX.h" -#include "clang/Parse/DeclSpec.h" -#include "llvm/Support/Compiler.h" -using namespace clang; - -namespace { - class VISIBILITY_HIDDEN TemplateStmtInstantiator - : public StmtVisitor<TemplateStmtInstantiator, Sema::OwningStmtResult> { - Sema &SemaRef; - const TemplateArgumentList &TemplateArgs; - - template<typename T> - Sema::FullExprArg FullExpr(T &expr) { - return SemaRef.FullExpr(expr); - } - - public: - typedef Sema::OwningExprResult OwningExprResult; - typedef Sema::OwningStmtResult OwningStmtResult; - - TemplateStmtInstantiator(Sema &SemaRef, - const TemplateArgumentList &TemplateArgs) - : SemaRef(SemaRef), TemplateArgs(TemplateArgs) { } - - // Declare VisitXXXStmt nodes for all of the statement kinds. -#define STMT(Type, Base) OwningStmtResult Visit##Type(Type *S); -#define EXPR(Type, Base) -#include "clang/AST/StmtNodes.def" - - // Visit an expression (which will use the expression - // instantiator). - OwningStmtResult VisitExpr(Expr *E); - - // Base case. I'm supposed to ignore this. - OwningStmtResult VisitStmt(Stmt *S) { - S->dump(); - assert(false && "Cannot instantiate this kind of statement"); - return SemaRef.StmtError(); - } - }; -} - -//===----------------------------------------------------------------------===/ -// Common/C statements -//===----------------------------------------------------------------------===/ -Sema::OwningStmtResult TemplateStmtInstantiator::VisitDeclStmt(DeclStmt *S) { - llvm::SmallVector<Decl *, 4> Decls; - for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); - D != DEnd; ++D) { - Decl *Instantiated = SemaRef.InstantiateDecl(*D, SemaRef.CurContext, - TemplateArgs); - if (!Instantiated) - return SemaRef.StmtError(); - - Decls.push_back(Instantiated); - SemaRef.CurrentInstantiationScope->InstantiatedLocal(*D, Instantiated); - } - - return SemaRef.Owned(new (SemaRef.Context) DeclStmt( - DeclGroupRef::Create(SemaRef.Context, - &Decls[0], - Decls.size()), - S->getStartLoc(), - S->getEndLoc())); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitNullStmt(NullStmt *S) { - return SemaRef.Owned(S->Clone(SemaRef.Context)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitLabelStmt(LabelStmt *S) { - OwningStmtResult SubStmt = Visit(S->getSubStmt()); - - if (SubStmt.isInvalid()) - return SemaRef.StmtError(); - - // FIXME: Pass the real colon loc in. - return SemaRef.ActOnLabelStmt(S->getIdentLoc(), S->getID(), SourceLocation(), - move(SubStmt)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitGotoStmt(GotoStmt *S) { - return SemaRef.ActOnGotoStmt(S->getGotoLoc(), S->getLabelLoc(), - S->getLabel()->getID()); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitIndirectGotoStmt(IndirectGotoStmt *S) { - OwningExprResult Target = SemaRef.InstantiateExpr(S->getTarget(), - TemplateArgs); - if (Target.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnIndirectGotoStmt(S->getGotoLoc(), S->getStarLoc(), - move(Target)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitBreakStmt(BreakStmt *S) { - return SemaRef.Owned(S->Clone(SemaRef.Context)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitContinueStmt(ContinueStmt *S) { - return SemaRef.Owned(S->Clone(SemaRef.Context)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitReturnStmt(ReturnStmt *S) { - Sema::OwningExprResult Result = SemaRef.ExprEmpty(); - if (Expr *E = S->getRetValue()) { - Result = SemaRef.InstantiateExpr(E, TemplateArgs); - - if (Result.isInvalid()) - return SemaRef.StmtError(); - } - - return SemaRef.ActOnReturnStmt(S->getReturnLoc(), FullExpr(Result)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) { - return SemaRef.InstantiateCompoundStmt(S, TemplateArgs, false); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitSwitchCase(SwitchCase *S) { - assert(false && "SwitchCase statements are never directly instantiated"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) { - // The case value expressions are not potentially evaluated. - EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); - - // Instantiate left-hand case value. - OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs); - if (LHS.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate right-hand case value (for the GNU case-range extension). - OwningExprResult RHS = SemaRef.InstantiateExpr(S->getRHS(), TemplateArgs); - if (RHS.isInvalid()) - return SemaRef.StmtError(); - - // Build the case statement. - OwningStmtResult Case = SemaRef.ActOnCaseStmt(S->getCaseLoc(), - move(LHS), - S->getEllipsisLoc(), - move(RHS), - S->getColonLoc()); - if (Case.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the statement following the case - OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(), - TemplateArgs); - if (SubStmt.isInvalid()) - return SemaRef.StmtError(); - - SemaRef.ActOnCaseStmtBody(Case.get(), move(SubStmt)); - return move(Case); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitDefaultStmt(DefaultStmt *S) { - // Instantiate the statement following the default case - OwningStmtResult SubStmt = SemaRef.InstantiateStmt(S->getSubStmt(), - TemplateArgs); - if (SubStmt.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnDefaultStmt(S->getDefaultLoc(), - S->getColonLoc(), - move(SubStmt), - /*CurScope=*/0); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) { - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - Sema::FullExprArg FullCond(FullExpr(Cond)); - - // Instantiate the "then" branch. - OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs); - if (Then.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the "else" branch. - OwningStmtResult Else = SemaRef.InstantiateStmt(S->getElse(), TemplateArgs); - if (Else.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnIfStmt(S->getIfLoc(), FullCond, move(Then), - S->getElseLoc(), move(Else)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitSwitchStmt(SwitchStmt *S) { - // Instantiate the condition. - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - // Start the switch statement itself. - OwningStmtResult Switch = SemaRef.ActOnStartOfSwitchStmt(move(Cond)); - if (Switch.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the body of the switch statement. - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - // Complete the switch statement. - return SemaRef.ActOnFinishSwitchStmt(S->getSwitchLoc(), move(Switch), - move(Body)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) { - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - Sema::FullExprArg FullCond(FullExpr(Cond)); - - // Instantiate the body - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnWhileStmt(S->getWhileLoc(), FullCond, move(Body)); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) { - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the body - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnDoStmt(S->getDoLoc(), move(Body), S->getWhileLoc(), - SourceLocation(), move(Cond), S->getRParenLoc()); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitForStmt(ForStmt *S) { - // Instantiate the initialization statement - OwningStmtResult Init = SemaRef.InstantiateStmt(S->getInit(), TemplateArgs); - if (Init.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the condition - OwningExprResult Cond = SemaRef.InstantiateExpr(S->getCond(), TemplateArgs); - if (Cond.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the increment - OwningExprResult Inc = SemaRef.InstantiateExpr(S->getInc(), TemplateArgs); - if (Inc.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the body - OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); - if (Body.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.ActOnForStmt(S->getForLoc(), S->getLParenLoc(), - move(Init), move(Cond), move(Inc), - S->getRParenLoc(), move(Body)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitAsmStmt(AsmStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an 'asm' statement"); - return SemaRef.StmtError(); -} - -//===----------------------------------------------------------------------===/ -// C++ statements -//===----------------------------------------------------------------------===/ -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitCXXTryStmt(CXXTryStmt *S) { - // Instantiate the try block itself. - OwningStmtResult TryBlock = VisitCompoundStmt(S->getTryBlock()); - if (TryBlock.isInvalid()) - return SemaRef.StmtError(); - - // Instantiate the handlers. - ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef); - for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) { - OwningStmtResult Handler = VisitCXXCatchStmt(S->getHandler(I)); - if (Handler.isInvalid()) - return SemaRef.StmtError(); - - Handlers.push_back(Handler.takeAs<Stmt>()); - } - - return SemaRef.ActOnCXXTryBlock(S->getTryLoc(), move(TryBlock), - move_arg(Handlers)); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitCXXCatchStmt(CXXCatchStmt *S) { - // Instantiate the exception declaration, if any. - VarDecl *Var = 0; - if (S->getExceptionDecl()) { - VarDecl *ExceptionDecl = S->getExceptionDecl(); - QualType T = SemaRef.InstantiateType(ExceptionDecl->getType(), - TemplateArgs, - ExceptionDecl->getLocation(), - ExceptionDecl->getDeclName()); - if (T.isNull()) - return SemaRef.StmtError(); - - Var = SemaRef.BuildExceptionDeclaration(0, T, - ExceptionDecl->getIdentifier(), - ExceptionDecl->getLocation(), - /*FIXME: Inaccurate*/ - SourceRange(ExceptionDecl->getLocation())); - if (Var->isInvalidDecl()) { - Var->Destroy(SemaRef.Context); - return SemaRef.StmtError(); - } - - // Introduce the exception declaration into scope. - SemaRef.CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var); - } - - // Instantiate the actual exception handler. - OwningStmtResult Handler = Visit(S->getHandlerBlock()); - if (Handler.isInvalid()) { - if (Var) - Var->Destroy(SemaRef.Context); - return SemaRef.StmtError(); - } - - return SemaRef.Owned(new (SemaRef.Context) CXXCatchStmt(S->getCatchLoc(), - Var, - Handler.takeAs<Stmt>())); -} - -//===----------------------------------------------------------------------===/ -// Objective-C statements -//===----------------------------------------------------------------------===/ -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtFinallyStmt(ObjCAtFinallyStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @finally statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtSynchronizedStmt( - ObjCAtSynchronizedStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @synchronized statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtTryStmt(ObjCAtTryStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @try statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCForCollectionStmt( - ObjCForCollectionStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C \"for\" statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @throw statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult -TemplateStmtInstantiator::VisitObjCAtCatchStmt(ObjCAtCatchStmt *S) { - // FIXME: Implement this - assert(false && "Cannot instantiate an Objective-C @catch statement"); - return SemaRef.StmtError(); -} - -Sema::OwningStmtResult TemplateStmtInstantiator::VisitExpr(Expr *E) { - Sema::OwningExprResult Result = SemaRef.InstantiateExpr(E, TemplateArgs); - if (Result.isInvalid()) - return SemaRef.StmtError(); - - return SemaRef.Owned(Result.takeAs<Stmt>()); -} - -Sema::OwningStmtResult -Sema::InstantiateStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) { - if (!S) - return Owned((Stmt *)0); - - TemplateStmtInstantiator Instantiator(*this, TemplateArgs); - return Instantiator.Visit(S); -} - -Sema::OwningStmtResult -Sema::InstantiateCompoundStmt(CompoundStmt *S, - const TemplateArgumentList &TemplateArgs, - bool isStmtExpr) { - if (!S) - return Owned((Stmt *)0); - - TemplateStmtInstantiator Instantiator(*this, TemplateArgs); - ASTOwningVector<&ActionBase::DeleteStmt> Statements(*this); - for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end(); - B != BEnd; ++B) { - OwningStmtResult Result = Instantiator.Visit(*B); - if (Result.isInvalid()) - return StmtError(); - - Statements.push_back(Result.takeAs<Stmt>()); - } - - return ActOnCompoundStmt(S->getLBracLoc(), S->getRBracLoc(), - move_arg(Statements), isStmtExpr); -} |