diff options
Diffstat (limited to 'lib/AST')
| -rw-r--r-- | lib/AST/ASTContext.cpp | 52 | ||||
| -rw-r--r-- | lib/AST/CFG.cpp | 6 | ||||
| -rw-r--r-- | lib/AST/Decl.cpp | 39 | ||||
| -rw-r--r-- | lib/AST/DeclBase.cpp | 7 | ||||
| -rw-r--r-- | lib/AST/DeclCXX.cpp | 9 | ||||
| -rw-r--r-- | lib/AST/Expr.cpp | 4 | ||||
| -rw-r--r-- | lib/AST/ExprConstant.cpp | 22 | ||||
| -rw-r--r-- | lib/AST/StmtViz.cpp | 3 | ||||
| -rw-r--r-- | lib/AST/Type.cpp | 20 |
9 files changed, 152 insertions, 10 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b80142fef3096..12f75ae863a2f 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -179,6 +179,10 @@ void ASTContext::InitBuiltinTypes() { // expressions. InitBuiltinType(DependentTy, BuiltinType::Dependent); + // Placeholder type for C++0x auto declarations whose real type has + // not yet been deduced. + InitBuiltinType(UndeducedAutoTy, BuiltinType::UndeducedAuto); + // C99 6.2.5p11. FloatComplexTy = getComplexType(FloatTy); DoubleComplexTy = getComplexType(DoubleTy); @@ -460,6 +464,10 @@ ASTContext::getTypeInfo(const Type *T) { case Type::TypeOf: return getTypeInfo(cast<TypeOfType>(T)->getUnderlyingType().getTypePtr()); + case Type::Decltype: + return getTypeInfo(cast<DecltypeType>(T)->getUnderlyingExpr()->getType() + .getTypePtr()); + case Type::QualifiedName: return getTypeInfo(cast<QualifiedNameType>(T)->getNamedType().getTypePtr()); @@ -1659,6 +1667,50 @@ QualType ASTContext::getTypeOfType(QualType tofType) { return QualType(tot, 0); } +/// getDecltypeForExpr - Given an expr, will return the decltype for that +/// expression, according to the rules in C++0x [dcl.type.simple]p4 +static QualType getDecltypeForExpr(const Expr *e, ASTContext &Context) { + if (e->isTypeDependent()) + return Context.DependentTy; + + // If e is an id expression or a class member access, decltype(e) is defined + // as the type of the entity named by e. + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(e)) { + if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) + return VD->getType(); + } + if (const MemberExpr *ME = dyn_cast<MemberExpr>(e)) { + if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) + return FD->getType(); + } + // If e is a function call or an invocation of an overloaded operator, + // (parentheses around e are ignored), decltype(e) is defined as the + // return type of that function. + if (const CallExpr *CE = dyn_cast<CallExpr>(e->IgnoreParens())) + return CE->getCallReturnType(); + + QualType T = e->getType(); + + // Otherwise, where T is the type of e, if e is an lvalue, decltype(e) is + // defined as T&, otherwise decltype(e) is defined as T. + if (e->isLvalue(Context) == Expr::LV_Valid) + T = Context.getLValueReferenceType(T); + + return T; +} + +/// getDecltypeType - Unlike many "get<Type>" functions, we don't unique +/// DecltypeType AST's. The only motivation to unique these nodes would be +/// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be +/// an issue. This doesn't effect the type checker, since it operates +/// on canonical type's (which are always unique). +QualType ASTContext::getDecltypeType(Expr *e) { + QualType T = getDecltypeForExpr(e, *this); + DecltypeType *dt = new (*this, 8) DecltypeType(e, getCanonicalType(T)); + Types.push_back(dt); + return QualType(dt, 0); +} + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType ASTContext::getTagDeclType(TagDecl *Decl) { diff --git a/lib/AST/CFG.cpp b/lib/AST/CFG.cpp index 9f2f2079a0941..d7a830726fa46 100644 --- a/lib/AST/CFG.cpp +++ b/lib/AST/CFG.cpp @@ -22,9 +22,6 @@ #include "llvm/Support/Compiler.h" #include <llvm/Support/Allocator.h> #include <llvm/Support/Format.h> -#include <iomanip> -#include <algorithm> -#include <sstream> using namespace clang; @@ -1887,7 +1884,8 @@ void CFG::viewCFG() const { namespace llvm { template<> struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits { - static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) { + static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph, + bool ShortNames) { #ifndef NDEBUG std::string OutSStr; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 71e88a9efc491..5382ab52ab5b0 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -269,6 +269,14 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { // For function declarations, we keep track of redeclarations. return FD->getPreviousDeclaration() == OldD; + // For function templates, the underlying function declarations are linked. + if (const FunctionTemplateDecl *FunctionTemplate + = dyn_cast<FunctionTemplateDecl>(this)) + if (const FunctionTemplateDecl *OldFunctionTemplate + = dyn_cast<FunctionTemplateDecl>(OldD)) + return FunctionTemplate->getTemplatedDecl() + ->declarationReplaces(OldFunctionTemplate->getTemplatedDecl()); + // For method declarations, we keep track of redeclarations. if (isa<ObjCMethodDecl>(this)) return false; @@ -289,6 +297,19 @@ bool NamedDecl::hasLinkage() const { return false; } +NamedDecl *NamedDecl::getUnderlyingDecl() { + NamedDecl *ND = this; + while (true) { + if (UsingDecl *UD = dyn_cast<UsingDecl>(ND)) + ND = UD->getTargetDecl(); + else if (ObjCCompatibleAliasDecl *AD + = dyn_cast<ObjCCompatibleAliasDecl>(ND)) + return AD->getClassInterface(); + else + return ND; + } +} + //===----------------------------------------------------------------------===// // VarDecl Implementation //===----------------------------------------------------------------------===// @@ -351,6 +372,10 @@ void FunctionDecl::Destroy(ASTContext& C) { C.Deallocate(ParamInfo); + if (TemplateSpecializationInfo *Info + = TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>()) + C.Deallocate(Info); + Decl::Destroy(C); } @@ -547,6 +572,20 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { return OO_None; } +void +FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context, + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs) { + TemplateSpecializationInfo *Info + = TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>(); + if (!Info) + Info = new (Context) TemplateSpecializationInfo; + + Info->Template = Template; + Info->TemplateArguments = TemplateArgs; + TemplateOrSpecialization = Info; +} + //===----------------------------------------------------------------------===// // TagDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 02e71d7a8681e..5815d820aef60 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -96,6 +96,13 @@ bool Decl::isTemplateParameterPack() const { return false; } +bool Decl::isFunctionOrFunctionTemplate() const { + if (const UsingDecl *UD = dyn_cast<UsingDecl>(this)) + return UD->getTargetDecl()->isFunctionOrFunctionTemplate(); + + return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this); +} + //===----------------------------------------------------------------------===// // PrettyStackTraceDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 25e4d19617785..752218db042a1 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -420,6 +420,15 @@ OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, return new (C) OverloadedFunctionDecl(DC, N); } +void OverloadedFunctionDecl::addOverload(FunctionTemplateDecl *FTD) { + Functions.push_back(FTD); + + // An overloaded function declaration always has the location of + // the most-recently-added function declaration. + if (FTD->getLocation().isValid()) + this->setLocation(FTD->getLocation()); +} + LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 4a3ad2641ef4b..fce88cc0da28c 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1496,7 +1496,7 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { return false; // Advance past s-char prefix on hex swizzles. - if (*compStr == 's') { + if (*compStr == 's' || *compStr == 'S') { compStr++; length--; } @@ -1514,7 +1514,7 @@ bool ExtVectorElementExpr::containsDuplicateElements() const { void ExtVectorElementExpr::getEncodedElementAccess( llvm::SmallVectorImpl<unsigned> &Elts) const { const char *compStr = Accessor->getName(); - if (*compStr == 's') + if (*compStr == 's' || *compStr == 'S') compStr++; bool isHi = !strcmp(compStr, "hi"); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 4815ae5c3b943..9d765924e02a2 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -486,12 +486,28 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { const Expr* SE = E->getSubExpr(); + QualType SETy = SE->getType(); + APValue Result = APValue(); - // Check for vector->vector bitcast. - if (SE->getType()->isVectorType()) + // Check for vector->vector bitcast and scalar->vector splat. + if (SETy->isVectorType()) { return this->Visit(const_cast<Expr*>(SE)); + } else if (SETy->isIntegerType()) { + APSInt IntResult; + if (EvaluateInteger(SE, IntResult, Info)) + Result = APValue(IntResult); + } else if (SETy->isRealFloatingType()) { + APFloat F(0.0); + if (EvaluateFloat(SE, F, Info)) + Result = APValue(F); + } - return APValue(); + if (Result.isInt() || Result.isFloat()) { + unsigned NumElts = E->getType()->getAsVectorType()->getNumElements(); + llvm::SmallVector<APValue, 4> Elts(NumElts, Result); + Result = APValue(&Elts[0], Elts.size()); + } + return Result; } APValue diff --git a/lib/AST/StmtViz.cpp b/lib/AST/StmtViz.cpp index 1316d3551d91a..96b5218ba2f0b 100644 --- a/lib/AST/StmtViz.cpp +++ b/lib/AST/StmtViz.cpp @@ -31,7 +31,8 @@ void Stmt::viewAST() const { namespace llvm { template<> struct DOTGraphTraits<const Stmt*> : public DefaultDOTGraphTraits { - static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph) { + static std::string getNodeLabel(const Stmt* Node, const Stmt* Graph, + bool ShortNames) { #ifndef NDEBUG std::string OutSStr; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 7b45b21e5d0c6..41536612fec81 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -112,6 +112,8 @@ QualType Type::getDesugaredType(bool ForDisplay) const { return TOE->getUnderlyingExpr()->getType().getDesugaredType(); if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this)) return TOT->getUnderlyingType().getDesugaredType(); + if (const DecltypeType *DTT = dyn_cast<DecltypeType>(this)) + return DTT->getUnderlyingExpr()->getType().getDesugaredType(); if (const TemplateSpecializationType *Spec = dyn_cast<TemplateSpecializationType>(this)) { if (ForDisplay) @@ -962,6 +964,7 @@ const char *BuiltinType::getName(bool CPlusPlus) const { case NullPtr: return "nullptr_t"; case Overload: return "<overloaded function type>"; case Dependent: return "<dependent type>"; + case UndeducedAuto: return "<undeduced auto type>"; } } @@ -1052,6 +1055,13 @@ TypeOfExprType::TypeOfExprType(Expr *E, QualType can) assert(!isa<TypedefType>(can) && "Invalid canonical type"); } +DecltypeType::DecltypeType(Expr *E, QualType can) + : Type(Decltype, can, E->isTypeDependent()), E(E) { + assert(can->isDependentType() == E->isTypeDependent() && + "type dependency mismatch!"); + assert(!isa<TypedefType>(can) && "Invalid canonical type"); +} + TagType::TagType(TypeClass TC, TagDecl *D, QualType can) : Type(TC, can, D->isDependentType()), decl(D, 0) {} @@ -1421,6 +1431,16 @@ void TypeOfType::getAsStringInternal(std::string &InnerString, const PrintingPol InnerString = "typeof(" + Tmp + ")" + InnerString; } +void DecltypeType::getAsStringInternal(std::string &InnerString, + const PrintingPolicy &Policy) const { + if (!InnerString.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. + InnerString = ' ' + InnerString; + std::string Str; + llvm::raw_string_ostream s(Str); + getUnderlyingExpr()->printPretty(s, 0, Policy); + InnerString = "decltype(" + s.str() + ")" + InnerString; +} + void FunctionNoProtoType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { // If needed for precedence reasons, wrap the inner part in grouping parens. if (!S.empty()) |
