Implement initialization of a reference (C++ [dcl.init.ref]) as part
of copy initialization. Other pieces of the puzzle:
- Try/Perform-ImplicitConversion now handles implicit conversions
that don't involve references.
- Try/Perform-CopyInitialization uses
CheckSingleAssignmentConstraints for C. PerformCopyInitialization
is now used for all argument passing and returning values from a
function.
- Diagnose errors with declaring references and const values without
an initializer. (Uses a new Action callback, ActOnUninitializedDecl).
We do not yet have implicit conversion sequences for reference
binding, which means that we don't have any overloading support for
reference parameters yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58353 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 71c0ceb..78f0d8f 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -628,6 +628,13 @@
}
bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {
+ // C++ [dcl.init.ref]p1:
+ // A variable declared to be a T&, that is “reference to type T”
+ // (8.3.2), shall be initialized by an object, or function, of
+ // type T or by an object that can be converted into a T.
+ if (DeclType->isReferenceType())
+ return CheckReferenceInit(Init, DeclType);
+
// C99 6.7.8p3: The type of the entity to be initialized shall be an array
// of unknown size ("[]") or an object type that is not a variable array type.
if (const VariableArrayType *VAT = Context.getAsVariableArrayType(DeclType))
@@ -1516,6 +1523,49 @@
return;
}
+void Sema::ActOnUninitializedDecl(DeclTy *dcl) {
+ Decl *RealDecl = static_cast<Decl *>(dcl);
+
+ if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) {
+ QualType Type = Var->getType();
+ // C++ [dcl.init.ref]p3:
+ // The initializer can be omitted for a reference only in a
+ // parameter declaration (8.3.5), in the declaration of a
+ // function return type, in the declaration of a class member
+ // within its class declaration (9.2), and where the extern
+ // specifier is explicitly used.
+ if (Type->isReferenceType() && Var->getStorageClass() != VarDecl::Extern)
+ Diag(Var->getLocation(),
+ diag::err_reference_var_requires_init,
+ Var->getName(),
+ SourceRange(Var->getLocation(), Var->getLocation()));
+
+ // C++ [dcl.init]p9:
+ //
+ // If no initializer is specified for an object, and the
+ // object is of (possibly cv-qualified) non-POD class type (or
+ // array thereof), the object shall be default-initialized; if
+ // the object is of const-qualified type, the underlying class
+ // type shall have a user-declared default
+ // constructor. Otherwise, if no initializer is specified for
+ // an object, the object and its subobjects, if any, have an
+ // indeterminate initial value; if the object or any of its
+ // subobjects are of const-qualified type, the program is
+ // ill-formed.
+ //
+ // This isn't technically an error in C, so we don't diagnose it.
+ //
+ // FIXME: Actually perform the POD/user-defined default
+ // constructor check.
+ if (getLangOptions().CPlusPlus &&
+ Context.getCanonicalType(Type).isConstQualified())
+ Diag(Var->getLocation(),
+ diag::err_const_var_requires_init,
+ Var->getName(),
+ SourceRange(Var->getLocation(), Var->getLocation()));
+ }
+}
+
/// The declarators are chained together backwards, reverse the list.
Sema::DeclTy *Sema::FinalizeDeclaratorGroup(Scope *S, DeclTy *group) {
// Often we have single declarators, handle them quickly.