aboutsummaryrefslogtreecommitdiff
path: root/lib/AST
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST')
-rw-r--r--lib/AST/ASTContext.cpp52
-rw-r--r--lib/AST/CFG.cpp6
-rw-r--r--lib/AST/Decl.cpp39
-rw-r--r--lib/AST/DeclBase.cpp7
-rw-r--r--lib/AST/DeclCXX.cpp9
-rw-r--r--lib/AST/Expr.cpp4
-rw-r--r--lib/AST/ExprConstant.cpp22
-rw-r--r--lib/AST/StmtViz.cpp3
-rw-r--r--lib/AST/Type.cpp20
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())