summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-15 17:07:18 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-15 17:07:18 +0000
commite5557c18e5d41b4b62f2af8a24af20eba40b0225 (patch)
tree06710cc8b660a5b76972f4e154656b80b8a37662 /lib/Sema
parent7dc062fe0c5b1560bb94c297bf1b71df517c9767 (diff)
downloadFreeBSD-src-e5557c18e5d41b4b62f2af8a24af20eba40b0225.zip
FreeBSD-src-e5557c18e5d41b4b62f2af8a24af20eba40b0225.tar.gz
Delete some more files.
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaInherit.cpp350
-rw-r--r--lib/Sema/SemaInherit.h248
-rw-r--r--lib/Sema/SemaNamedCast.cpp932
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp1350
-rw-r--r--lib/Sema/SemaTemplateInstantiateStmt.cpp450
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);
-}
OpenPOWER on IntegriCloud