<div dir="ltr">Yup, that looks like my fault, again.<div><br></div><div>Thanks, Greg, for the test case.  It's very similar to the final test in odr_hash.cc, which I thought I had fixed.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 12, 2017 at 8:09 AM, Greg Bedwell <span dir="ltr"><<a href="mailto:gregbedwell@gmail.com" target="_blank">gregbedwell@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">We're seeing the same assertion failing in our internal testing (I've not bisected to a specific change yet though, but it seems likely it's the same thing as in the log from the modules bot).  Here's a reduced example that triggers it:<div><br></div><div><div>$ cat 2.h</div><div>// ==============================<wbr>==============</div><div>template <typename alpha> struct Bravo {</div><div>  void charlie(bool delta = false) {}</div><div>};</div><div>typedef Bravo<char> echo;</div><div>echo foxtrot;</div><div>// ==============================<wbr>==============</div><div><br></div><div>$ clang.exe -x c++-header 2.h</div><div>Assertion failed: !hasUninstantiatedDefaultArg() && "Default argument is not yet instantiated!", file C:\llvm\tools\clang\lib\AST\<wbr>Decl.cpp, line 2424</div><span class="HOEnZb"><font color="#888888"><div><br></div><div>-Greg<br><div><br></div><div><br></div></div></font></span></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On 12 April 2017 at 02:52, Richard Smith via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Either this or your other ODR hash change seems to have broken the modules buildbot:<div><br></div><div><a href="http://lab.llvm.org:8011/builders/clang-x86_64-linux-selfhost-modules-2/builds/6274/steps/compile.llvm.stage2/logs/stdio" target="_blank">http://lab.llvm.org:8011/build<wbr>ers/clang-x86_64-linux-selfhos<wbr>t-modules-2/builds/6274/steps/<wbr>compile.llvm.stage2/logs/stdio</a><br></div></div><div class="m_-5867415698945407785HOEnZb"><div class="m_-5867415698945407785h5"><div class="gmail_extra"><br><div class="gmail_quote">On 11 April 2017 at 15:32, Richard Trieu via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rtrieu<br>
Date: Tue Apr 11 17:32:03 2017<br>
New Revision: 300001<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=300001&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=300001&view=rev</a><br>
Log:<br>
Revert r298824 & r298816, recommit r298742 & r298754<br>
<br>
r299989 fixes the underlying issue by waiting long enough to late parsed<br>
arguments to be processed before doing an calculating the hash.<br>
<br>
r298742<br>
[ODRHash] Add error messages for mismatched parameters in methods.<br>
<br>
r298754<br>
[ODRHash] Add support for array and decayed types.<br>
<br>
Modified:<br>
  Â  cfe/trunk/include/clang/Basic/<wbr>DiagnosticSerializationKinds.t<wbr>d<br>
  Â  cfe/trunk/lib/AST/ODRHash.cpp<br>
  Â  cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp<br>
  Â  cfe/trunk/test/Modules/odr_has<wbr>h.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSerializationKinds.t<wbr>d<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSerializationKinds.td?rev=300001&r1=300000&r2=300001&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Basic/DiagnosticSerializationK<wbr>inds.td?rev=300001&r1=300000&r<wbr>2=300001&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSerializationKinds.t<wbr>d (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSerializationKinds.t<wbr>d Tue Apr 11 17:32:03 2017<br>
@@ -146,7 +146,12 @@ def err_module_odr_violation_misma<wbr>tch_de<br>
  Â "method %4 is %select{not static|static}5|"<br>
  Â "method %4 is %select{not volatile|volatile}5|"<br>
  Â "method %4 is %select{not const|const}5|"<br>
-  "method %4 is %select{not inline|inline}5}3">;<br>
+  "method %4 is %select{not inline|inline}5|"<br>
+  "method %4 that has %5 parameter%s5|"<br>
+  "method %4 with %ordinal5 parameter of type %6%select{| decayed from %8}7|"<br>
+  "method %4 with %ordinal5 parameter named %6|"<br>
+  "method %4 with %ordinal5 parameter with %select{no |}6default argument|"<br>
+  "method %4 with %ordinal5 parameter with default argument}3">;<br>
<br>
 def note_module_odr_violation_mism<wbr>atch_decl_diff : Note<"but in '%0' found "<br>
  Â "%select{"<br>
@@ -166,7 +171,12 @@ def note_module_odr_violation_mism<wbr>atch_d<br>
  Â "method %2 is %select{not static|static}3|"<br>
  Â "method %2 is %select{not volatile|volatile}3|"<br>
  Â "method %2 is %select{not const|const}3|"<br>
-  "method %2 is %select{not inline|inline}3}1">;<br>
+  "method %2 is %select{not inline|inline}3|"<br>
+  "method %2 that has %3 parameter%s3|"<br>
+  "method %2 with %ordinal3 parameter of type %4%select{| decayed from %6}5|"<br>
+  "method %2 with %ordinal3 parameter named %4|"<br>
+  "method %2 with %ordinal3 parameter with %select{no |}4default argument|"<br>
+  "method %2 with %ordinal3 parameter with different default argument}1">;<br>
<br>
 def warn_module_uses_date_time : Warning<<br>
  Â "%select{precompiled header|module}0 uses __DATE__ or __TIME__">,<br>
<br>
Modified: cfe/trunk/lib/AST/ODRHash.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ODRHash.cpp?rev=300001&r1=300000&r2=300001&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/AST/ODRHas<wbr>h.cpp?rev=300001&r1=300000&r2=<wbr>300001&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ODRHash.cpp (original)<br>
+++ cfe/trunk/lib/AST/ODRHash.cpp Tue Apr 11 17:32:03 2017<br>
@@ -169,6 +169,11 @@ public:<br>
  Â  Â Inherited::VisitValueDecl(D);<br>
  Â }<br>
<br>
+  void VisitParmVarDecl(const ParmVarDecl *D) {<br>
+  Â  AddStmt(D->getDefaultArg());<br>
+  Â  Inherited::VisitParmVarDecl(D)<wbr>;<br>
+  }<br>
+<br>
  Â void VisitAccessSpecDecl(const AccessSpecDecl *D) {<br>
  Â  Â ID.AddInteger(D->getAccess())<wbr>;<br>
  Â  Â Inherited::VisitAccessSpecDec<wbr>l(D);<br>
@@ -202,6 +207,12 @@ public:<br>
  Â  Â Hash.AddBoolean(D->isPure());<br>
  Â  Â Hash.AddBoolean(D->isDeletedA<wbr>sWritten());<br>
<br>
+  Â  ID.AddInteger(D->param_size())<wbr>;<br>
+<br>
+  Â  for (auto *Param : D->parameters()) {<br>
+  Â  Â  Hash.AddSubDecl(Param);<br>
+  Â  }<br>
+<br>
  Â  Â Inherited::VisitFunctionDecl(<wbr>D);<br>
  Â }<br>
<br>
@@ -315,6 +326,14 @@ public:<br>
  Â  Â }<br>
  Â }<br>
<br>
+  void AddQualType(QualType T) {<br>
+  Â  Hash.AddQualType(T);<br>
+  }<br>
+<br>
+  void VisitQualifiers(Qualifiers Quals) {<br>
+  Â  ID.AddInteger(Quals.getAsOpaqu<wbr>eValue());<br>
+  }<br>
+<br>
  Â void Visit(const Type *T) {<br>
  Â  Â ID.AddInteger(T->getTypeClass<wbr>());<br>
  Â  Â Inherited::Visit(T);<br>
@@ -322,11 +341,92 @@ public:<br>
<br>
  Â void VisitType(const Type *T) {}<br>
<br>
+  void VisitAdjustedType(const AdjustedType *T) {<br>
+  Â  AddQualType(T->getOriginalType<wbr>());<br>
+  Â  AddQualType(T->getAdjustedType<wbr>());<br>
+  Â  VisitType(T);<br>
+  }<br>
+<br>
+  void VisitDecayedType(const DecayedType *T) {<br>
+  Â  AddQualType(T->getDecayedType(<wbr>));<br>
+  Â  AddQualType(T->getPointeeType(<wbr>));<br>
+  Â  VisitAdjustedType(T);<br>
+  }<br>
+<br>
+  void VisitArrayType(const ArrayType *T) {<br>
+  Â  AddQualType(T->getElementType(<wbr>));<br>
+  Â  ID.AddInteger(T->getSizeModifi<wbr>er());<br>
+  Â  VisitQualifiers(T->getIndexTyp<wbr>eQualifiers());<br>
+  Â  VisitType(T);<br>
+  }<br>
+  void VisitConstantArrayType(const ConstantArrayType *T) {<br>
+  Â  T->getSize().Profile(ID);<br>
+  Â  VisitArrayType(T);<br>
+  }<br>
+<br>
+  void VisitDependentSizedArrayType(c<wbr>onst DependentSizedArrayType *T) {<br>
+  Â  AddStmt(T->getSizeExpr());<br>
+  Â  VisitArrayType(T);<br>
+  }<br>
+<br>
+  void VisitIncompleteArrayType(const IncompleteArrayType *T) {<br>
+  Â  VisitArrayType(T);<br>
+  }<br>
+<br>
+  void VisitVariableArrayType(const VariableArrayType *T) {<br>
+  Â  AddStmt(T->getSizeExpr());<br>
+  Â  VisitArrayType(T);<br>
+  }<br>
+<br>
  Â void VisitBuiltinType(const BuiltinType *T) {<br>
  Â  Â ID.AddInteger(T->getKind());<br>
  Â  Â VisitType(T);<br>
  Â }<br>
<br>
+  void VisitFunctionType(const FunctionType *T) {<br>
+  Â  AddQualType(T->getReturnType()<wbr>);<br>
+  Â  T->getExtInfo().Profile(ID);<br>
+  Â  Hash.AddBoolean(T->isConst());<br>
+  Â  Hash.AddBoolean(T->isVolatile(<wbr>));<br>
+  Â  Hash.AddBoolean(T->isRestrict(<wbr>));<br>
+  Â  VisitType(T);<br>
+  }<br>
+<br>
+  void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {<br>
+  Â  VisitFunctionType(T);<br>
+  }<br>
+<br>
+  void VisitFunctionProtoType(const FunctionProtoType *T) {<br>
+  Â  ID.AddInteger(T->getNumParams(<wbr>));<br>
+  Â  for (auto ParamType : T->getParamTypes())<br>
+  Â  Â  AddQualType(ParamType);<br>
+<br>
+  Â  const auto &epi = T->getExtProtoInfo();<br>
+  Â  ID.AddInteger(epi.Variadic);<br>
+  Â  ID.AddInteger(epi.TypeQuals);<br>
+  Â  ID.AddInteger(epi.RefQualifier<wbr>);<br>
+  Â  ID.AddInteger(epi.ExceptionSpe<wbr>c.Type);<br>
+<br>
+  Â  if (epi.ExceptionSpec.Type == EST_Dynamic) {<br>
+  Â  Â  for (QualType Ex : epi.ExceptionSpec.Exceptions)<br>
+  Â  Â  Â  AddQualType(Ex);<br>
+  Â  } else if (epi.ExceptionSpec.Type == EST_ComputedNoexcept &&<br>
+  Â  Â  Â  Â  Â  Â  Â epi.ExceptionSpec.NoexceptExp<wbr>r) {<br>
+  Â  Â  AddStmt(epi.ExceptionSpec.Noex<wbr>ceptExpr);<br>
+  Â  } else if (epi.ExceptionSpec.Type == EST_Uninstantiated ||<br>
+  Â  Â  Â  Â  Â  Â  Â epi.ExceptionSpec.Type == EST_Unevaluated) {<br>
+  Â  Â  AddDecl(epi.ExceptionSpec.Sour<wbr>ceDecl->getCanonicalDecl());<br>
+  Â  }<br>
+  Â  if (epi.ExtParameterInfos) {<br>
+  Â  Â  for (unsigned i = 0; i != T->getNumParams(); ++i)<br>
+  Â  Â  Â  ID.AddInteger(epi.ExtParameter<wbr>Infos[i].getOpaqueValue());<br>
+  Â  }<br>
+  Â  epi.ExtInfo.Profile(ID);<br>
+  Â  Hash.AddBoolean(epi.HasTrailin<wbr>gReturn);<br>
+<br>
+  Â  VisitFunctionType(T);<br>
+  }<br>
+<br>
  Â void VisitTypedefType(const TypedefType *T) {<br>
  Â  Â AddDecl(T->getDecl());<br>
  Â  Â Hash.AddQualType(T->getDecl()<wbr>->getUnderlyingType());<br>
<br>
Modified: cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=300001&r1=300000&r2=300001&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Serializat<wbr>ion/ASTReader.cpp?rev=300001&r<wbr>1=300000&r2=300001&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/AS<wbr>TReader.cpp Tue Apr 11 17:32:03 2017<br>
@@ -9282,6 +9282,11 @@ void ASTReader::diagnoseOdrViolatio<wbr>ns()<br>
  Â  Â  Â  Â MethodVolatile,<br>
  Â  Â  Â  Â MethodConst,<br>
  Â  Â  Â  Â MethodInline,<br>
+  Â  Â  Â  MethodNumberParameters,<br>
+  Â  Â  Â  MethodParameterType,<br>
+  Â  Â  Â  MethodParameterName,<br>
+  Â  Â  Â  MethodParameterSingleDefaultAr<wbr>gument,<br>
+  Â  Â  Â  MethodParameterDifferentDefaul<wbr>tArguments,<br>
  Â  Â  Â };<br>
<br>
  Â  Â  Â // These lambdas have the common portions of the ODR diagnostics.  This<br>
@@ -9605,6 +9610,104 @@ void ASTReader::diagnoseOdrViolatio<wbr>ns()<br>
  Â  Â  Â  Â  Â Diagnosed = true;<br>
  Â  Â  Â  Â  Â break;<br>
  Â  Â  Â  Â }<br>
+<br>
+  Â  Â  Â  const unsigned FirstNumParameters = FirstMethod->param_size();<br>
+  Â  Â  Â  const unsigned SecondNumParameters = SecondMethod->param_size();<br>
+  Â  Â  Â  if (FirstNumParameters != SecondNumParameters) {<br>
+  Â  Â  Â  Â  ODRDiagError(FirstMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â FirstMethod->getSourceRange()<wbr>, MethodNumberParameters)<br>
+  Â  Â  Â  Â  Â  Â  << FirstName << FirstNumParameters;<br>
+  Â  Â  Â  Â  ODRDiagNote(SecondMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  SecondMethod->getSourceRange()<wbr>, MethodNumberParameters)<br>
+  Â  Â  Â  Â  Â  Â  << SecondName << SecondNumParameters;<br>
+  Â  Â  Â  Â  Diagnosed = true;<br>
+  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  }<br>
+<br>
+  Â  Â  Â  // Need this status boolean to know when break out of the switch.<br>
+  Â  Â  Â  bool ParameterMismatch = false;<br>
+  Â  Â  Â  for (unsigned I = 0; I < FirstNumParameters; ++I) {<br>
+  Â  Â  Â  Â  const ParmVarDecl *FirstParam = FirstMethod->getParamDecl(I);<br>
+  Â  Â  Â  Â  const ParmVarDecl *SecondParam = SecondMethod->getParamDecl(I);<br>
+<br>
+  Â  Â  Â  Â  QualType FirstParamType = FirstParam->getType();<br>
+  Â  Â  Â  Â  QualType SecondParamType = SecondParam->getType();<br>
+  Â  Â  Â  Â  if (FirstParamType != SecondParamType) {<br>
+  Â  Â  Â  Â  Â  if (const DecayedType *ParamDecayedType =<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  FirstParamType->getAs<DecayedT<wbr>ype>()) {<br>
+  Â  Â  Â  Â  Â  Â  ODRDiagError(FirstMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â FirstMethod->getSourceRange()<wbr>, MethodParameterType)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  << FirstName << (I + 1) << FirstParamType << true<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  << ParamDecayedType->getOriginalT<wbr>ype();<br>
+  Â  Â  Â  Â  Â  } else {<br>
+  Â  Â  Â  Â  Â  Â  ODRDiagError(FirstMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â FirstMethod->getSourceRange()<wbr>, MethodParameterType)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  << FirstName << (I + 1) << FirstParamType << false;<br>
+  Â  Â  Â  Â  Â  }<br>
+<br>
+  Â  Â  Â  Â  Â  if (const DecayedType *ParamDecayedType =<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  SecondParamType->getAs<Decayed<wbr>Type>()) {<br>
+  Â  Â  Â  Â  Â  Â  ODRDiagNote(SecondMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  SecondMethod->getSourceRange()<wbr>, MethodParameterType)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  << SecondName << (I + 1) << SecondParamType << true<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  << ParamDecayedType->getOriginalT<wbr>ype();<br>
+  Â  Â  Â  Â  Â  } else {<br>
+  Â  Â  Â  Â  Â  Â  ODRDiagNote(SecondMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  SecondMethod->getSourceRange()<wbr>, MethodParameterType)<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  << SecondName << (I + 1) << SecondParamType << false;<br>
+  Â  Â  Â  Â  Â  }<br>
+  Â  Â  Â  Â  Â  ParameterMismatch = true;<br>
+  Â  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  Â  }<br>
+<br>
+  Â  Â  Â  Â  DeclarationName FirstParamName = FirstParam->getDeclName();<br>
+  Â  Â  Â  Â  DeclarationName SecondParamName = SecondParam->getDeclName();<br>
+  Â  Â  Â  Â  if (FirstParamName != SecondParamName) {<br>
+  Â  Â  Â  Â  Â  ODRDiagError(FirstMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â FirstMethod->getSourceRange()<wbr>, MethodParameterName)<br>
+  Â  Â  Â  Â  Â  Â  Â  << FirstName << (I + 1) << FirstParamName;<br>
+  Â  Â  Â  Â  Â  ODRDiagNote(SecondMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  SecondMethod->getSourceRange()<wbr>, MethodParameterName)<br>
+  Â  Â  Â  Â  Â  Â  Â  << SecondName << (I + 1) << SecondParamName;<br>
+  Â  Â  Â  Â  Â  ParameterMismatch = true;<br>
+  Â  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  Â  }<br>
+<br>
+  Â  Â  Â  Â  const Expr* FirstDefaultArg = FirstParam->getDefaultArg();<br>
+  Â  Â  Â  Â  const Expr* SecondDefaultArg = SecondParam->getDefaultArg();<br>
+  Â  Â  Â  Â  if ((!FirstDefaultArg && SecondDefaultArg) ||<br>
+  Â  Â  Â  Â  Â  Â  (FirstDefaultArg && !SecondDefaultArg)) {<br>
+  Â  Â  Â  Â  Â  ODRDiagError(FirstMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â FirstMethod->getSourceRange()<wbr>,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â MethodParameterSingleDefaultA<wbr>rgument)<br>
+  Â  Â  Â  Â  Â  Â  Â  << FirstName << (I + 1) << (FirstDefaultArg != nullptr);<br>
+  Â  Â  Â  Â  Â  ODRDiagNote(SecondMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  SecondMethod->getSourceRange()<wbr>,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  MethodParameterSingleDefaultAr<wbr>gument)<br>
+  Â  Â  Â  Â  Â  Â  Â  << SecondName << (I + 1) << (SecondDefaultArg != nullptr);<br>
+  Â  Â  Â  Â  Â  ParameterMismatch = true;<br>
+  Â  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  Â  }<br>
+<br>
+  Â  Â  Â  Â  if (ComputeODRHash(FirstDefaultAr<wbr>g) !=<br>
+  Â  Â  Â  Â  Â  Â  ComputeODRHash(SecondDefaultAr<wbr>g)) {<br>
+  Â  Â  Â  Â  Â  ODRDiagError(FirstMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â FirstMethod->getSourceRange()<wbr>,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â MethodParameterDifferentDefau<wbr>ltArguments)<br>
+  Â  Â  Â  Â  Â  Â  Â  << FirstName << (I + 1);<br>
+  Â  Â  Â  Â  Â  ODRDiagNote(SecondMethod->getL<wbr>ocation(),<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  SecondMethod->getSourceRange()<wbr>,<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  MethodParameterDifferentDefaul<wbr>tArguments)<br>
+  Â  Â  Â  Â  Â  Â  Â  << SecondName << (I + 1);<br>
+  Â  Â  Â  Â  Â  ParameterMismatch = true;<br>
+  Â  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  Â  }<br>
+  Â  Â  Â  }<br>
+<br>
+  Â  Â  Â  if (ParameterMismatch) {<br>
+  Â  Â  Â  Â  Diagnosed = true;<br>
+  Â  Â  Â  Â  break;<br>
+  Â  Â  Â  }<br>
<br>
  Â  Â  Â  Â break;<br>
  Â  Â  Â }<br>
<br>
Modified: cfe/trunk/test/Modules/odr_has<wbr>h.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/odr_hash.cpp?rev=300001&r1=300000&r2=300001&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/Modules/o<wbr>dr_hash.cpp?rev=300001&r1=3000<wbr>00&r2=300001&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Modules/odr_has<wbr>h.cpp (original)<br>
+++ cfe/trunk/test/Modules/odr_has<wbr>h.cpp Tue Apr 11 17:32:03 2017<br>
@@ -275,6 +275,33 @@ S11 s11;<br>
 // expected-note@first.h:* {{but in 'FirstModule' found field 'x' with a different initializer}}<br>
 #endif<br>
<br>
+#if defined(FIRST)<br>
+struct S12 {<br>
+  unsigned x[5];<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S12 {<br>
+  unsigned x[7];<br>
+};<br>
+#else<br>
+S12 s12;<br>
+// expected-error@first.h:* {{'Field::S12::x' from module 'FirstModule' is not present in definition of 'Field::S12' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+#endif<br>
+<br>
+#if defined(FIRST)<br>
+struct S13 {<br>
+  unsigned x[7];<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S13 {<br>
+  double x[7];<br>
+};<br>
+#else<br>
+S13 s13;<br>
+// expected-error@first.h:* {{'Field::S13::x' from module 'FirstModule' is not present in definition of 'Field::S13' in module 'SecondModule'}}<br>
+// expected-note@second.h:* {{declaration of 'x' does not match}}<br>
+#endif<br>
 }  // namespace Field<br>
<br>
 namespace Method {<br>
@@ -403,6 +430,93 @@ S8 s8;<br>
 // expected-note@first.h:* {{but in 'FirstModule' found method 'A' is const}}<br>
 #endif<br>
<br>
+#if defined(FIRST)<br>
+struct S9 {<br>
+  void A(int x) {}<br>
+  void A(int x, int y) {}<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S9 {<br>
+  void A(int x, int y) {}<br>
+  void A(int x) {}<br>
+};<br>
+#else<br>
+S9 s9;<br>
+// expected-error@second.h:* {{'Method::S9' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' that has 2 parameters}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found method 'A' that has 1 parameter}}<br>
+#endif<br>
+<br>
+#if defined(FIRST)<br>
+struct S10 {<br>
+  void A(int x) {}<br>
+  void A(float x) {}<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S10 {<br>
+  void A(float x) {}<br>
+  void A(int x) {}<br>
+};<br>
+#else<br>
+S10 s10;<br>
+// expected-error@second.h:* {{'Method::S10' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter of type 'float'}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter of type 'int'}}<br>
+#endif<br>
+<br>
+#if defined(FIRST)<br>
+struct S11 {<br>
+  void A(int x) {}<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S11 {<br>
+  void A(int y) {}<br>
+};<br>
+#else<br>
+S11 s11;<br>
+// expected-error@second.h:* {{'Method::S11' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter named 'y'}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter named 'x'}}<br>
+#endif<br>
+<br>
+#if defined(FIRST)<br>
+struct S12 {<br>
+  void A(int x) {}<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S12 {<br>
+  void A(int x = 1) {}<br>
+};<br>
+#else<br>
+S12 s12;<br>
+// expected-error@second.h:* {{'Method::S12' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter with default argument}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter with no default argument}}<br>
+#endif<br>
+<br>
+#if defined(FIRST)<br>
+struct S13 {<br>
+  void A(int x = 1 + 0) {}<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S13 {<br>
+  void A(int x = 1) {}<br>
+};<br>
+#else<br>
+S13 s13;<br>
+// expected-error@second.h:* {{'Method::S13' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter with default argument}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter with different default argument}}<br>
+#endif<br>
+<br>
+#if defined(FIRST)<br>
+struct S14 {<br>
+  void A(int x[2]) {}<br>
+};<br>
+#elif defined(SECOND)<br>
+struct S14 {<br>
+  void A(int x[3]) {}<br>
+};<br>
+#else<br>
+S14 s14;<br>
+// expected-error@second.h:* {{'Method::S14' has different definitions in different modules; first difference is definition in module 'SecondModule' found method 'A' with 1st parameter of type 'int *' decayed from 'int [3]'}}<br>
+// expected-note@first.h:* {{but in 'FirstModule' found method 'A' with 1st parameter of type 'int *' decayed from 'int [2]'}}<br>
+#endif<br>
 }  // namespace Method<br>
<br>
 // Naive parsing of AST can lead to cycles in processing.  Ensure<br>
@@ -522,71 +636,54 @@ S3 s3;<br>
 #endif<br>
 }  // namespace Using<br>
<br>
-<br>
 // Interesting cases that should not cause errors.  struct S should not error<br>
 // while struct T should error at the access specifier mismatch at the end.<br>
+#define ALL_DECLS  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+public:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+private:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+protected:  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  static_assert(1 == 1, "Message");  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+  static_assert(2 == 2);  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  int x;  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  double y;  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  INT z;  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  unsigned a : 1;  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+  unsigned b : 2 * 2 + 5 / 2;  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  mutable int c = sizeof(x + y);  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  void method() {}  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  static void static_method() {}  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  virtual void virtual_method() {}  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  virtual void pure_virtual_method() = 0;  Â  Â  Â  Â  Â  Â  Â  \<br>
+  inline void inline_method() {}  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  void volatile_method() volatile {}  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  void const_method() const {}  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  typedef int typedef_int;  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  using using_int = int;  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  void method_one_arg(int x) {}  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+  void method_one_arg_default_argumen<wbr>t(int x = 5 + 5) {} \<br>
+  void method_decayed_type(int x[5]) {}  Â  Â  Â  Â  Â  Â  Â  Â  \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  int constant_arr[5];  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â  Â \<br>
+  double last_decl;<br>
+<br>
 namespace AllDecls {<br>
 #if defined(FIRST)<br>
 typedef int INT;<br>
 struct S {<br>
-  public:<br>
-  private:<br>
-  protected:<br>
-<br>
-  static_assert(1 == 1, "Message");<br>
-  static_assert(2 == 2);<br>
-<br>
-  int x;<br>
-  double y;<br>
-<br>
-  INT z;<br>
-<br>
-  unsigned a : 1;<br>
-  unsigned b : 2*2 + 5/2;<br>
-<br>
-  mutable int c = sizeof(x + y);<br>
-<br>
-  void method() {}<br>
-  static void static_method() {}<br>
-  virtual void virtual_method() {}<br>
-  virtual void pure_virtual_method() = 0;<br>
-  inline void inline_method() {}<br>
-  void volatile_method() volatile {}<br>
-  void const_method() const {}<br>
-<br>
-  typedef int typedef_int;<br>
-  using using_int = int;<br>
+  ALL_DECLS<br>
 };<br>
 #elif defined(SECOND)<br>
 typedef int INT;<br>
 struct S {<br>
-  public:<br>
-  private:<br>
-  protected:<br>
-<br>
-  static_assert(1 == 1, "Message");<br>
-  static_assert(2 == 2);<br>
-<br>
-  int x;<br>
-  double y;<br>
-<br>
-  INT z;<br>
-<br>
-  unsigned a : 1;<br>
-  unsigned b : 2 * 2 + 5 / 2;<br>
-<br>
-  mutable int c = sizeof(x + y);<br>
-<br>
-  void method() {}<br>
-  static void static_method() {}<br>
-  virtual void virtual_method() {}<br>
-  virtual void pure_virtual_method() = 0;<br>
-  inline void inline_method() {}<br>
-  void volatile_method() volatile {}<br>
-  void const_method() const {}<br>
-<br>
-  typedef int typedef_int;<br>
-  using using_int = int;<br>
+  ALL_DECLS<br>
 };<br>
 #else<br>
 S *s;<br>
@@ -595,66 +692,14 @@ S *s;<br>
 #if defined(FIRST)<br>
 typedef int INT;<br>
 struct T {<br>
-  public:<br>
-  private:<br>
-  protected:<br>
-<br>
-  static_assert(1 == 1, "Message");<br>
-  static_assert(2 == 2);<br>
-<br>
-  int x;<br>
-  double y;<br>
-<br>
-  INT z;<br>
-<br>
-  unsigned a : 1;<br>
-  unsigned b : 2 * 2 + 5 / 2;<br>
-<br>
-  mutable int c = sizeof(x + y);<br>
-<br>
-  void method() {}<br>
-  static void static_method() {}<br>
-  virtual void virtual_method() {}<br>
-  virtual void pure_virtual_method() = 0;<br>
-  inline void inline_method() {}<br>
-  void volatile_method() volatile {}<br>
-  void const_method() const {}<br>
-<br>
-  typedef int typedef_int;<br>
-  using using_int = int;<br>
+  ALL_DECLS<br>
<br>
  Â private:<br>
 };<br>
 #elif defined(SECOND)<br>
 typedef int INT;<br>
 struct T {<br>
-  public:<br>
-  private:<br>
-  protected:<br>
-<br>
-  static_assert(1 == 1, "Message");<br>
-  static_assert(2 == 2);<br>
-<br>
-  int x;<br>
-  double y;<br>
-<br>
-  INT z;<br>
-<br>
-  unsigned a : 1;<br>
-  unsigned b : 2 * 2 + 5 / 2;<br>
-<br>
-  mutable int c = sizeof(x + y);<br>
-<br>
-  void method() {}<br>
-  static void static_method() {}<br>
-  virtual void virtual_method() {}<br>
-  virtual void pure_virtual_method() = 0;<br>
-  inline void inline_method() {}<br>
-  void volatile_method() volatile {}<br>
-  void const_method() const {}<br>
-<br>
-  typedef int typedef_int;<br>
-  using using_int = int;<br>
+  ALL_DECLS<br>
<br>
  Â public:<br>
 };<br>
@@ -944,6 +989,22 @@ T t;<br>
 #endif<br>
 }  // namespace StructWithForwardDeclarationNo<wbr>Definition<br>
<br>
+namespace LateParsedDefaultArgument {<br>
+#if defined(FIRST)<br>
+template <typename T><br>
+struct S {<br>
+  struct R {<br>
+  Â  void foo(T x = 0) {}<br>
+  };<br>
+};<br>
+#elif defined(SECOND)<br>
+#else<br>
+void run() {<br>
+  S<int>::R().foo();<br>
+}<br>
+#endif<br>
+}<br>
+<br>
 // Keep macros contained to one file.<br>
 #ifdef FIRST<br>
 #undef FIRST<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div><br>______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
<br></blockquote></div><br></div>
</div></div></blockquote></div><br></div>