Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -2678,6 +2678,23 @@ NewParam != NewParamEnd; ++NewParam) { // Variables used to diagnose redundant default arguments bool RedundantDefaultArg = false; + // Variable used to not diagnose redundant default arguments + // from modules. + // + // [basic.def.odr]/13: + // There can be more than one definition of a + // ... + // default template argument + // ... + // in a program provided that each definition appears in a different + // translation unit and the definitions satisfy the [same-meaning + // criteria of the ODR]. + // + // Simply, the design of modules allows the definition of template default + // argument to be repeated across translation unit. Note that the ASTReader + // would check the ODR criteria mentioned above so we could skip it here. + bool IsOldParamFromModule = false; + SourceLocation OldDefaultLoc; SourceLocation NewDefaultLoc; @@ -2710,6 +2727,8 @@ OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc(); SawDefaultArgument = true; + if (OldTypeParm->isFromASTFile()) + IsOldParamFromModule = true; RedundantDefaultArg = true; PreviousDefaultArgLoc = NewDefaultLoc; } else if (OldTypeParm && OldTypeParm->hasDefaultArgument()) { @@ -2755,6 +2774,8 @@ OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc(); SawDefaultArgument = true; + if (OldNonTypeParm->isFromASTFile()) + IsOldParamFromModule = true; RedundantDefaultArg = true; PreviousDefaultArgLoc = NewDefaultLoc; } else if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument()) { @@ -2799,6 +2820,8 @@ OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation(); NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation(); SawDefaultArgument = true; + if (OldTemplateParm->isFromASTFile()) + IsOldParamFromModule = true; RedundantDefaultArg = true; PreviousDefaultArgLoc = NewDefaultLoc; } else if (OldTemplateParm && OldTemplateParm->hasDefaultArgument()) { @@ -2826,7 +2849,7 @@ Invalid = true; } - if (RedundantDefaultArg) { + if (RedundantDefaultArg && !IsOldParamFromModule) { // C++ [temp.param]p12: // A template-parameter shall not be given default arguments // by two different declarations in the same scope. Index: clang/test/Modules/Inputs/redundant-template-default-arg/foo.h =================================================================== --- /dev/null +++ clang/test/Modules/Inputs/redundant-template-default-arg/foo.h @@ -0,0 +1,11 @@ +template +T v; + +template +int v2; + +template +class my_array {}; + +template